diff options
author | Norbert Preining <norbert@preining.info> | 2022-01-14 03:01:14 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2022-01-14 03:01:14 +0000 |
commit | 45623da68203ac8d7aa04b779a6ed65c92c3f866 (patch) | |
tree | 151ca3ede3ee826360d4b32c0029cfc106346ec9 /macros/latex | |
parent | ee3f9ca89b21a2174f7e427d9d48247b1912e130 (diff) |
CTAN sync 202201140301
Diffstat (limited to 'macros/latex')
124 files changed, 6539 insertions, 5506 deletions
diff --git a/macros/latex/contrib/dbshow/README.md b/macros/latex/contrib/dbshow/README.md index f91034d6cb..940f8ce35b 100644 --- a/macros/latex/contrib/dbshow/README.md +++ b/macros/latex/contrib/dbshow/README.md @@ -1,32 +1,71 @@ +Package dbshow +============== -# Package dbshow - -## Overview +Introduction +------------ The package provides four core functions: -1. data storage and display +1. data storage 2. data filtering 3. data sorting 4. data display -All data is saved once and then you can display these data with custom filters, orders and styles. The package can be used, for example, to record and display something you'd like to review, maybe the question you always answered incorrectly or some forgettable knowledge. But obviously, the package is much more powerful and extensible for more interesting tasks depending on the individual. +All data is saved once and then you can display these data with custom filters, +orders and styles. The package can be used, for example, to record and +display something you'd like to review, maybe the question you always answered +incorrectly or some forgettable knowledge. But obviously, the package is much +more powerful and extensible for more interesting tasks depending on the +individual. + +Install +------- + +If you are using TeX Live, install `dbshow` by `tlmgr` package manager + + tlmgr update --self --all + tlmgr install dbshow + +You can also download the zip file from +[CTAN](https://ctan.org/pkg/dbshow) or +[GitHub](https://github.com/ZhiyuanLck/dbshow/releases/latest). + +The zip file should contain the file `dbshow.dtx`, and you can extract +`dbshow.sty` from it by + + tex dbshow.dtx + +Compile Document +---------------- + +Use following commands to compile the document: + + git clone https://github.com/ZhiyuanLck/dbshow.git + cd dbshow + latexmk dbshow.dtx -## LICENSE +Copyright and License +--------------------- - dbshow.sty - Copyright 2022 Li Changkai <lichangkai225@qq.com> + Copyright (C) 2022- by Changkai Li <lichangkai225@qq.com> + -------------------------------------------------------------------------- -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 may be distributed and/or modified under the + conditions of the LaTeX Project Public License, either + version 1.3c of this license or (at your option) any later + version. This version of this license is in + http://www.latex-project.org/lppl/lppl-1-3c.txt + and 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'. + This work has the LPPL maintenance status "maintained". -The Current Maintainer of this work is Li Changkai. + The Current Maintainer of this work is Changkai Li. -This work consists of the files dbshow.sty, dbshow-doc.tex. + This package consists of the file dbshow.dtx, + and the derived files dbshow.pdf, + dbshow.sty, + dbshow.ins and + README.md (this file). diff --git a/macros/latex/contrib/dbshow/dbshow-doc.pdf b/macros/latex/contrib/dbshow/dbshow-doc.pdf Binary files differdeleted file mode 100644 index c6d4b714d4..0000000000 --- a/macros/latex/contrib/dbshow/dbshow-doc.pdf +++ /dev/null diff --git a/macros/latex/contrib/dbshow/dbshow-doc.tex b/macros/latex/contrib/dbshow/dbshow-doc.tex deleted file mode 100644 index ebfe69c535..0000000000 --- a/macros/latex/contrib/dbshow/dbshow-doc.tex +++ /dev/null @@ -1,1662 +0,0 @@ -\documentclass[full]{l3doc} -\usepackage[scheme=plain, fontset=ubuntu]{ctex} -\usepackage{multicol} -\usepackage{adjustbox} -\usepackage{zhlineskip} -\usepackage{enumitem} -\usepackage{indentfirst} -\usepackage{titling} -\usepackage{geometry} -\usepackage{tabularray} -\usepackage{xcolor} -\usepackage{tcolorbox} -\tcbuselibrary{listings, skins, raster, breakable} -\usepackage{tabularray} - -\def\zhdate{2022年1月10日} -\def\endate{2022/01/10} -\def\version{v1.3} - -\geometry{ - left=4.5cm, - right=2cm, - top=2cm, - bottom=2cm, -} -\hypersetup { - CJKbookmarks, - bookmarksopen, - bookmarksopenlevel=3, - pdfstartview=FitH, - pdfinfo = { - Title = The package 'dbshow' , - Subject = A LaTeX package , - Author = Li Changkai - } -} - -\IndexPrologue { - \part*{Index} - \markboth{Index}{Index} - \addcontentsline{toc}{part}{Index} - The~italic~numbers~denote~the~pages~where~the~ - corresponding~entry~is~described,~ - numbers~underlined~point~to~the~definition,~ - all~others~indicate~the~places~where~it~is~used. -} - -\GlossaryPrologue { - \part*{Change~History} - {\GlossaryParms\ttfamily\hyphenchar\font=`\-} - \markboth{Change~History}{Change~History} - \addcontentsline{toc}{part}{Change~History} -} - -\let\subsubitem\subitem - -\DoNotIndex{\begin, \end} -\setlength{\parskip}{\medskipamount} - -\newcommand\tikzmark[1]{\tikz \coordinate[overlay, remember picture] (#1);} -\def\levelchar{?} -\def\orbar{\textup{\textbar}} -\def\defaultval#1{\textbf{\textup{#1}}} -\def\TF{true\orbar false} -\def\TTF{\defaultval{true}\orbar false} -\def\TFF{true\orbar\defaultval{false}} -\def\zhbefore{\textbf{前}} -\def\zhafter{\textbf{后}} -\def\enbefore{\textbf{before}~} -\def\enafter{\textbf{after}~} -\DeclareDocumentEnvironment { note } { +b } { - \par\textbf{\textsf{NOTE:~}}#1\par -} {} - -\AtEndDocument{ - \newgeometry{ - left=2cm, - right=2cm, - top=2cm, - bottom=2cm - } - \PrintChanges - \PrintIndex -} - -\ExplSyntaxOn -\makeatletter -\cs_new_protected:Nn \dbshow_changes:nnnn { - \@bsphack\group_begin:\@sanitize - \catcode`\\\z@ \catcode`\ 10 \MakePercentIgnore - \exp_args:Nx \glossary { - \exp_not:N \textbf{#1}\levelchar - \exp_not:N \textit{#2}\c_space_tl - \exp_not:N \textbf{#3}\c_colon_str\c_space_tl - \exp_not:n { #4 } - } - \group_end:\@esphack -} -\cs_generate_variant:Nn \dbshow_changes:nnnn { xnnn } - -\cs_new_protected:Nn \dbshow_changes_what:nnnn { - \regex_extract_once:nnNT { doc|macro|bug|option } - { #3 } \l_tmpa_seq { - \dbshow_changes:xnnn { - \str_case_e:nn { \seq_item:Nn \l_tmpa_seq { 1 } } { - { doc } { Documentation } - { macro } { Macro } - { bug } { Bug } - { option } { Option } - { logic } { Logic } - } - } - {#2} {#3} {#4} - } -} - -\cs_new_protected:Nn \dbshow_changes_how:nnnn { - \regex_extract_once:nnNT { Add|Update|Remove } { #3 } \l_tmpa_seq { - \dbshow_changes:xnnn { \seq_item:Nn \l_tmpa_seq { 1 } } - {#2} {#3} {#4} - } -} - -% #1 version #2 date #3 type #4 desc -\DeclareDocumentCommand \changes { m m m m } { - \dbshow_changes:nnnn {#1} {#2} {#3} {#4} - \dbshow_changes_what:nnnn {#1} {#2} {#3} {#4} - \dbshow_changes_how:nnnn {#1} {#2} {#3} {#4} -} -\makeatother - -\DeclareDocumentEnvironment { Description } { o +b } { - \hbox_set:Nn \l_tmpa_box { #1 } - \dim_set:Nn \l_tmpa_dim { \box_wd:N \l_tmpa_box } - \begin{itemize}[labelwidth=\l_tmpa_dim, align=left] - #2 - \end{itemize} -} { } - -\cs_new_protected:Nn \dbshowdoc_function_begin:N { - \cs_set_eq:NN \__codedoc_tmp_cs:nN \__codedoc_typeset_function_block:nN - \cs_set_protected:Npn \__codedoc_typeset_function_block:nN ##1##2 { - \__codedoc_function_label:xN {##1} ##2 - \hbox_set:Nn \l_tmpa_box {##1} - \int_compare:nTF { \str_count:n {##1} <= 22 } - {##1} { \adjustbox{width=.7\marginparwidth, height=\box_ht:N \l_tmpa_box}{##1} } - #1{##1} - \__codedoc_typeset_expandability: \\ - } -} -\cs_new_protected:Nn \dbshowdoc_function_end: { - \cs_set_eq:NN \__codedoc_typeset_function_block:nN \__codedoc_tmp_cs:nN -} -\DeclareDocumentEnvironment { option } { O{} +v } - { - \dbshowdoc_function_begin:N \SpecialOptionIndex - \__codedoc_function:nnw {#1} {#2} - } - { - \__codedoc_function_end: - \dbshowdoc_function_end: - } -\DeclareDocumentEnvironment { environment } { O{} +v } - { - \dbshowdoc_function_begin:N \SpecialEnvIndex - \__codedoc_function:nnw {#1} {#2} - } - { - \__codedoc_function_end: - \dbshowdoc_function_end: - } - -\DeclareDocumentCommand \opt { O{} m } - { \__codedoc_cmd:no {#1} { #2 } } - -\NewDocumentCommand \linktarget { m m m } {% - \hyperlink{#1}{#3}% - \raisebox{1em}{\hypertarget{#2}{}}% -} -\ExplSyntaxOff - - -\begin{document} -\title{ - \pkg{dbshow} 宏包 \version% - \protect\footnote{% - 代码仓库:\url{https://github.com/ZhiyuanLck/dbshow}, - QQ群:788706534} - \rlap{\makebox[4cm][r]{ - \normalsize $\Longrightarrow$ \color{red} - \linktarget{en}{zh}{English Version} - }} -} -\author{\textit{李昌锴} \texttt{<lichangkai225@qq.com>}} -\date{\zhdate} -\maketitle - -\tableofcontents - -\begin{documentation} - -\section{引言} -编写本宏包的动机来源于当前没有一个很好的错题本宏包,可以方便的根据各种条件对错 -题进行筛选、排序,然后以自定义的样式展示出来。\pkg{dbshow} 宏包实现了四个核心 -功能:数据存储和使用、数据筛选、数据排序、数据展示。 - -数据只需要存储一次,就可以通过预定义的筛选、排序条件和样式展示部分或全部的数据。 -如上所述,本宏包其实实现了一个非常简单的数据库,复习错题的功能只是其中一个应用, -和其他数据库宏包比如 \pkg{datatool} 相比,\pkg{dbshow} 更专注于非图表类型的数 -据展示。 - -\changes{1.2}{2022-01-09}{Add doc}{descripton for expansion} -\begin{itemize} - \item 名字后带有 $\star$ 的命令是可以完全展开的(fully-expandable); - \item 名字后带有 \ding{73} 的命令可以有限制地展开(restricted-expandable); - \item 名字后不带有特殊字符的命令是不可展开的(non-expandable); - \item 名字后带有 $\star$ 的选项不影响相关的代码的是否可展开; - \item 名字后带有 \ding{73} 的选项是否影响相关代码的可展开性取决于选项的设置; - \item 名字后不带有特殊字符的选项会使与之相关的代码变得不可展开。 -\end{itemize} - -\subsection{数据类型} - -宏包基于 \pkg{expl3} 的基础类型构建了6种类型: -\begin{Description}[\texttt{clist}] - \item[\texttt{date}] - 日期类型,以 |yyyy/mm/dd| 形式存储,支持大小比较,排序(转 - 换成字符串)。默认值为 \cs{dbtoday}。 - \item[\texttt{str}] - 字符串类型,支持正则匹配,英文排序。默认值为空。 - \item[\texttt{tl}] - \meta{token list}类型,支持正则匹配。默认值为空。 - \item[\texttt{int}] - 整数类型,支持大小比较,排序。默认值为0。 - \item[\texttt{fp}] - 浮点数类型,支持大小比较,排序。默认值为0。 - \item[\texttt{clist}] - 逗号分隔的列表类型。默认值为空列表。 -\end{Description} - -\changes{1.3}{2022-01-08}{Remove dependency}{\pkg{datatime2}} -除了日期类型,所有类型都是 \pkg{expl3} 的内置类型。\pkg{dbshow} 构建了一个简单 -的 |date| 类型,支持转换成整数以及带样式的打印。 - -\subsection{与 \pkg{datatool} 的区别} - -\changes{1.2}{2022-01-07}{Add doc}{add comparison to \pkg{datatool}} - -从核心功能上看,\pkg{dbshow} 和 \pkg{datatool} 实现了相同的功能。区别在于 -\pkg{dbshow} 基于 \pkg{expl3} 实现,支持字符串的正则匹配,还支持多级排序。使用 -方式上更倾向于样式与内容分离,所有的样式都可以通过选项提前定义好并且可以复用。 -\pkg{dbshow} 并没有实现从外部文件读取数据以及将数据持久化的功能,我认为这些应 -该是更专业的外部程序的工作而不应该在 \LaTeX 中设计这些功能。因此,\pkg{dbshow} -只提供了一个运行时的临时数据库,足够轻便且满足大部分正常需求。如果你想删除或修 -改数据库中某一条记录,请去对应的位置删除或修改掉对应的 \env{dbitem} 环境,而不 -是让宏包提供一个输出某一行记录的命令。某种意义上记录数据库的 \TeX 源文件本身就 -是数据的一种持久化。 - -\section{接口文档} - -\subsection{创建、展示和清空数据库} -\begin{function}[added=2022-01-05]{\dbNewDatabase, \dbNewDatabase*} - \begin{syntax} - \cs{dbNewDatabase} \oarg{base database} \marg{database} \{ \\ - ~~\meta{attr1} = \meta{type spec1}, \\ - ~~\meta{attr2} = \meta{type spec2}, \\ - ~~\ldots{} \\ - \} \\ - \cs{dbNewDatabase}* \marg{database} \{ \\ - ~~\meta{attr1} = \meta{type spec1}, \\ - ~~\meta{attr2} = \meta{type spec2}, \\ - ~~\ldots{} \\ - \} \\ - \end{syntax} - -\end{function} - - 新建一个数据库,不带星号的版本可以指定一个数据库来继承其属性设置,该版本总是 - 会舍弃掉之前的定义。 - - 带星号的版本不会舍弃之前已有的定义,而是将新的选项添加到后面。 - - \meta{attr} 为属性名称,\meta{type spec} 负责声明属性类型和属性默认值: - - \noindent\begin{tblr}{ - colspec = {ll}, - column{1} = {font = \ttfamily} - } - \meta{attr} = \meta{type} & - 将 \meta{attr} 声明为 \meta{type} 类型 \\ - \meta{attr} = \meta{type}\orbar\meta{default} & - 将 \meta{attr} 声明为 \meta{type} 类型,并且将默认值设置为 \meta{default}。 - \\ - \end{tblr} - - \begin{note} - 每个数据库都有一个默认的属性 |id| 用来存储数据的索引。 - \end{note} - - 下面是定义一个错题数据库的示例,|question| 和 |answer| 属性用来存储问题和答 - 案,|date| 属性存储日期,|info| 属性存储额外信息,|labels| 存储题目标签。 -\begin{verbatim} - \dbNewDatabase{ques}{ - question = tl, - answer = tl, - date = date, - info = tl, - labels = clist - } -\end{verbatim} - -\begin{function}[added=2022-01-05]{\dbshow} - \begin{syntax} - \cs{dbshow} \marg{style} \marg{database} - \end{syntax} - - 使用 \meta{style} 样式来展示 \meta{database}。 -\end{function} - -\changes{1.2}{2022-01-07}{Add macro}{\cs{dbclear}} -\begin{function}[added=2022-01-07]{\dbclear} - \begin{syntax} - \cs{dbclear} \marg{database} - \end{syntax} - 清空 \meta{database} 里的所有内容。 -\end{function} - -\subsection{\cs{dbNewStyle} 和样式选项} - -\begin{function}[added=2022-01-05]{\dbNewStyle} - \begin{syntax} - \cs{dbNewStyle} \oarg{base styles} \marg{style} \marg{database} \marg{opts} - \end{syntax} - - 为 \meta{database} 定义一个新的样式 \meta{style},该样式可以基于已有的样式 - \meta{base styles},比如 |\dbNewStyle[base1, base2]{new-style}{ques}{}|。 -\end{function} - -\subsubsection{通用选项} - -\begin{option}[added=2022-01-05]{filter} - \begin{syntax} - filter = <filter> - \end{syntax} - - 为当前样式设置由 \cs{dbCombineFilters} 所定义的过滤器 -\end{option} - -\begin{option}[added=2022-01-06]{raw-filter} - \begin{syntax} - raw-filter = <conditional expression> - \end{syntax} - - 使用条件表达式设置匿名过滤器,这里的条件指通过 \cs{dbNewConditional} 定义的 - 条件。下面代码中两个示例的过滤器具有相同的功能。 -\end{option} - -\changes{1.1}{2022-01-06}{Add option}{\opt{raw-filter}} - -\begin{verbatim} - % method 1 - \begin{dbFilters}{db} - \dbNewConditional{cond1}{int-attr}{\rval > 1} - \dbNewConditional*{cond2}{str-attr}{\d+} - \end{dbFilters} - \dbNewStyle{style}{db}{raw-filter={cond1 && cond2}} - % method 2 - \begin{dbFilters}{db} - \dbNewConditional{cond1}{int-attr}{\rval > 1} - \dbNewConditional*{cond2}{str-attr}{\d+} - \dbCombineFilters{filter}{cond1 && cond2} - \end{dbFilters} - \dbNewStyle{style}{db}{filter=filter} -\end{verbatim} - -\changes{1.2}{2022-01-08}{Fix bug}{string sorting bug} -\begin{option}[added=2022-01-05]{sort} - \begin{syntax} - sort = \{ <attr spec1>, <attr spec2>, \ldots{} \} - \end{syntax} - - 为当前样式设置排序规则。支持根据 |str|,|date|,|int|,|fp| 类型的数据进行排 - 序,支持多级排序。\meta{attr} 表示增序,\meta{attr}* 表示降序。下面例子中, - 使用 |sort-style| 展示数据时的顺序为先按 |level| 降序,|level| 相同的再按出 - 生日期 |birth| 增序,以此类推。 -\end{option} - -\begin{verbatim} - \dbNewDatabase{sort-example}{ - name = str, - birth = date, - level = int, - weight = fp, - } - \dbNewStyle{sort-style}{sort-example}{ - sort = { level*, birth, name, weight } - } -\end{verbatim} - -\begin{option}[added=2022-01-05, rEXP]{item-code} - \begin{syntax} - item-code = <code> - \end{syntax} - - 该选项用来设置展示数据库中每条记录的代码。你可以使用 \cs{dbuse} 来展示属性的 - 值。 -\end{option} - -\changes{1.3}{2022-01-09}{Update option}{\opt{<attr>/sep}} -\begin{option}[added=2022-01-05, updated=2022-01-08, rEXP]{<attr>/sep} - \begin{syntax} - <attr>/sep = <separator> \\ - <attr>/sep = \{ \\ - ~~\meta{separator between two}, \\ - ~~\meta{separator between more than two}, \\ - ~~\meta{separator between final two} \\ - \} \\ - <attr>/sep = \{ \\ - ~~\meta{separator before year}, \\ - ~~\meta{separator between year and month}, \\ - ~~\meta{separator between month and day}, \\ - ~~\meta{separator after day} \\ - \} \\ - \end{syntax} - - 该选项只适用于类型为 |clist| 或 |date| 的属性,用来设置列表间元素的间隔。参 - 数为一个 \meta{separator} 时,所有元素间的分隔符被设置为 \meta{separator}。 - \meta{separator before year} 和 \meta{separator after day} 被设置为空。 -\end{option} - - 参数为3个元素的逗号分隔的列表时,此选项用来设置列表元素的分隔符,分别用来设 - 置只有两个元素时的分隔符 \meta{separator between two},超过两个元素时的分隔 - 符 \meta{separator between more than two},和最后两个元素之间的分隔符 - \meta{separator between final two}。对于类型为 |clist| 的属性,设置此选项时 - 如果参数列表数量不是1或者3会触发报错。 - -\begin{verbatim} - % clist-attr is an attribute of database db - % suppose the val of clist-attr is { 1, 2, 3 } - \dbNewStyle{clist-sep}{db}{ - clist-attr/sep = { ,~ }, % print 1, 2, 3 - clist-attr/sep = { {,~}, {,~}, {and~} } % print 1, 2 and 3 - } -\end{verbatim} - - 参数为4个元素的逗号分隔的列表时,此选项用来设置日期的分隔符,分别用来设 - 置 \meta{year} 之前的分隔符 \meta{separator before year} ,\meta{year} 和 - \meta{month} 之间的分隔符 \meta{separator between year and month} , - \meta{month} 和 \meta{day} 之间的分隔符,以及 \meta{day} 之后的分隔符。对于 - 类型为 |date| 的属性,设置此选项时如果参数列表数量不是1或者4会触发报错。 - -\begin{verbatim} - % date-attr is an attribute of database db - % suppose the val of date-attr is 2022/01/01 - \dbNewStyle{date-sep}{db}{ - date-attr/sep = -, % print 2022-01-01 - date-attr/sep = { |, -, -, | } % print |2022-01-01| - } -\end{verbatim} - -\changes{1.3}{2022-01-08}{Add option}{\opt{<attr>/zfill}} -\begin{option}[added=2022-01-08, EXP]{<attr>/zfill} - \begin{syntax} - <attr>/zfill = <\TTF> - \end{syntax} - - 该选项只适用于类型为 |date| 的属性。控制输出月份和天时是否补零。 -\end{option} - -\subsubsection{装饰器} - -下面这些选项在不同层次上装饰原有的展示代码,有些其实不必通过选项的形式来装饰, -但这样做的好处是可以进一步使样式与内容分离。下面的例子中,\meta{style1} 和 -\meta{style2} 是相同的样式,都用 * 将 \meta{attr1} 包裹住了,但是如果你还想定 -义一个样式用 = 将 \meta{attr1} 包裹住,如果用 \meta{style1} 的方式,那就可能 -需要重复大片代码,用 \meta{style2} 的方式则可以很轻松的继承 \meta{style1} 中的 -代码。 - -\begin{verbatim} - \dbNewStyle{style1}{db}{ - item-code = {% - *\rvuse{attr1}*\rvuse{attr2} - % more code - } - } - \dbNewStyle{base-style}{db}{ - item-code = {% - \rvuse{attr1}\rvuse{attr2} - % more code - } - } - \dbNewStyle[base-style]{style2}{db}{ - attr1/before-code = { * }, - attr1/after-code = { * }, - } - \dbNewStyle[base-style]{style3}{db}{ - attr1/before-code = { = }, - attr1/after-code = { = }, - } -\end{verbatim} - -\changes{1.3}{2022-01-08}{Add option}{\opt{<attr>/wrapper}} -\begin{option}[added=2022-01-08, rEXP]{<attr>/wrapper} - \begin{syntax} - <attr>/wrapper = <control sequence> - \end{syntax} - - 该选项只适用于类型为 |date| 的属性。\meta{control sequence} 只接收一个参数即 - 日期,如果设置了此选项,则最后输出的日期为 - \meta{control sequence}\marg{date}。 -\end{option} - -\begin{option}[added=2022-01-05, rEXP]{before-code} - \begin{syntax} - before-code = <code> - \end{syntax} - - 该选项用来设置在展示整个数据库之\zhbefore 需要执行的代码。 -\end{option} - -\begin{option}[added=2022-01-05, rEXP]{after-code} - \begin{syntax} - after-code = <code> - \end{syntax} - - 该选项用来设置在展示整个数据库之\zhafter 需要执行的代码。 -\end{option} - -\changes{1.2}{2022-01-08}{Add options}{\opt{record-before-code}, -\opt{record-after-code}} -\begin{option}[added=2022-01-05, rEXP]{record-before-code} - \begin{syntax} - record-before-code = <code> - \end{syntax} - - 该选项用来设置在展示当前记录之\zhbefore 需要执行的代码。 -\end{option} - -\begin{option}[added=2022-01-05, rEXP]{record-after-code} - \begin{syntax} - record-after-code = <code> - \end{syntax} - - 该选项用来设置在展示当前记录之\zhafter 需要执行的代码。 -\end{option} - -\begin{option}[added=2022-01-05, rEXP]{<attr>/before-code} - \begin{syntax} - <attr>/before-code = <code> - \end{syntax} - - 该选项用来设置展示数据库中属性 \meta{attr} 对应数据之\zhbefore 需要执行的代 - 码。\cs{dbuse} 会在展示属性数据\zhbefore 执行此代码。 -\end{option} - -\begin{option}[added=2022-01-05, rEXP]{<attr>/after-code} - \begin{syntax} - <attr>/after-code = <code> - \end{syntax} - - 该选项用来设置展示数据库中属性 \meta{attr} 对应数据之\zhafter 需要执行的代码。 - \cs{dbuse} 会在展示属性数据\zhafter 执行此代码。 -\end{option} - -\begin{option}[added=2022-01-05, rEXP]{<attr>/item-before-code} - \begin{syntax} - <attr>/item-before-code = <code> - \end{syntax} - - 该选项只适用于类型为 |clist| 的属性,用来设置展示列表每个元素\zhbefore 需要 - 执行的代码。 -\end{option} - -\begin{option}[added=2022-01-05, rEXP]{<attr>/item-after-code} - \begin{syntax} - <attr>/item-after-code = <code> - \end{syntax} - - 该选项只适用于类型为 |clist| 的属性,用来设置展示列表每个元素\zhafter 需要执 - 行的代码。 -\end{option} - -\subsection{使用 \cs{dbNewReviewPoints} 定义复习点} - -\begin{function}[added=2022-01-05]{\dbNewReviewPoints} - \begin{syntax} - \cs{dbNewReviewPoints} \marg{name} \marg{points} - \end{syntax} - - 定义名为 \meta{name} 的复习点。这是专门为错题本或复习所定制的功能, - \meta{points}是一系列整数,现在假设每道错题你都将写错时的日期记录在了 |date| - 属性中,并且你希望每隔2,5,15天复习一次。下面的代码给出了一个实现示例。 -\end{function} - -\begin{verbatim} - \dbNewReviewPoints{review-point}{2, 5, 15} % 定义复习点 - \begin{dbFilters} - \dbNewConditional{cond1}{date}{review-point|\Today} % 定义复习条件 - \dbCombineConditionals{filter1}{cond1} % 定义过滤器 - \end{dbFilters} - \dbNewStyle{review-style}{ques}{filter=filter1} % 定义展示样式 -\end{verbatim} - -\subsection{在 \env{dbFilters} 环境中定义过滤器} - -\begin{environment}[added=2022-01-05]{dbFilters} - \begin{syntax} - |\begin{dbFilters}|\marg{database} \\ - ~~\meta{code} - |\end{dbFilters}| \\ - \end{syntax} - - \env{dbFilters}用来定义过滤器,此环境中定义了 \cs{dbNewConditional} 命令用来 - 定义条件和 \cs{dbCombineConditionals} 命令用来组合条件定义过滤器。过滤器独立 - 于每个 \meta{database},这意味着你可以在不同数据库中定义名称相同的过滤条件和 - 过滤器。 -\end{environment} - -\begin{function}[added=2022-01-05, updated=2022-01-08]{\dbNewConditional, \dbNewConditional*} - \begin{syntax} - \cs{dbNewConditional} \marg{name} \marg{attr} \marg{cond spec} \\ - \cs{dbNewConditional}* \marg{name} \marg{attr} \marg{cond spec} \\[2pt] - \cs{dbNewConditional} \marg{name} \marg{int/fp attr} \marg{expr} \\ - \cs{dbNewConditional}* \marg{name} \marg{int/fp attr} \marg{expr} \\ - \cs{dbNewConditional} \marg{name} \marg{str/tl attr} \marg{regex expr} \\ - \cs{dbNewConditional}* \marg{name} \marg{str/tl attr} \marg{regex expr} \\ - \cs{dbNewConditional} \marg{name} \marg{clist attr} \marg{val list} \\ - \cs{dbNewConditional}* \marg{name} \marg{clist attr} \marg{val list} \\ - \cs{dbNewConditional} \marg{name} \marg{date attr} \marg{expr} - \cs{dbNewConditional}* \marg{name} \marg{date attr} \{\meta{review points}\orbar\meta{date}\} \\ - \end{syntax} - - \cs{dbNewConditional} 用来定义名为 \meta{name} 的条件,\meta{attr} 指定条件 - 所绑定的属性,在 \meta{cond spec} 中可以用 \cs{dbval} 指代属性的值。 -\end{function} - - \changes{1.3}{2022-01-10}{Update doc}{truncated division} - 对于类型为 |int| 和 |fp| 的属性,\meta{expr} 传递给 \cs{int_compare:nTF} 或 - \cs{fp_compare:nTF} 处理。 - \begin{note} - |/| 为四舍五入除法,截断除法请用 \cs{dbIntDivTruncate}。 - \end{note} - - 对于类型为 |str| 和 |tl| 的属性,\meta{regex} 为正则表达式, - \cs{dbNewConditional} 表示部分匹配,\cs{dbNewConditional*} 表示整体匹配。 - -\begin{verbatim} - \dbNewConditional {cond1}{str-attr}{abc} % 匹配 abc, abcd, 1abc, =abc= 等 - \dbNewConditional*{cond2}{str-attr}{abc} % 只匹配 abc -\end{verbatim} - - 对于类型为 |clist| 的属性,使用 \cs{dbNewConditional} 定义的条件只要 - \meta{val list} 中的任意一个元素在属性值(列表)中则条件成立;使用 - \cs{dbNewConditional*} 定义的条件只有 \meta{val list} 中每一个值都在属性值 - (列表)中条件才成立。 - -\begin{verbatim} - \dbNewConditional {cond1}{clist-attr}{a, b, c} % a, b, d 满足条件 - \dbNewConditional*{cond2}{clist-attr}{a, b, c} % a, b, d 不满足条件 -\end{verbatim} - - \changes{1.3}{2022-01-08}{Update logic}{swap definition of starred and - unstarred conditionals of date} - 对于类型为 |date| 的属性,\cs{dbNewConditional} 定义的条件后续处理中会将 - \meta{expr} 中的所有日期转换成相对\textit{1971年1月1日}的一个整数值,然后将 - 处理后的表达式传递给 \cs{int_compare:nTF} 做进一步处理; - \cs{dbNewConditional*} 使用复习点来定义过滤条件,\meta{review points} 是 - \cs{dbNewReviewPoints} 定义的复习点,\meta{date} 是用来比较的日期。 - -\begin{function}[added=2022-01-05]{\dbCombineConditionals} - \begin{syntax} - \cs{dbCombineConditionals} \marg{name} \marg{cond combination} \oarg{info} - \end{syntax} - - \cs{dbCombineConditionals} 定义名为 \marg{name} 的过滤器,并将 - \cs{dbNewConditional} 定义的条件组合起来,比如 - \verb=\dbCombineConditionals{filter}{(cond1 && cond2) || !cond3}=。 - \meta{cond combination} 中可以使用的关系操作符为 \verb=&&, ||, !=。 - 可以将 \opt{filter} 选项设置为 \meta{name} 来应用过滤器。\meta{info} 为过滤 - 器的相关信息,在展示数据库的时候可以用 \cs{dbFilterInfo} 指代。 -\end{function} - -\subsection{使用 \env{dbitem} 环境存储数据} - -\begin{environment}[added=2022-01-05]{dbitem} - \begin{syntax} - |\begin{dbitem}|\marg{database}[ \\ - ~~\meta{attr1} = \meta{val1}, \\ - ~~\meta{attr2} = \meta{val2}, \\ - ~~\ldots{} \\ - ] \\ - ~~\meta{code} \\ - |\end{dbitem}| - \end{syntax} - - \env{dbitem} 环境用来存储数据。有两种存储数据的方法,较短的数据可以在选项列 - 表中通过键值对设置值,较长的数据可以在 \meta{code} 中使用 \cs{dbsave} 存储。 - \cs{dbsave}会覆盖选项中设置的值。没有设置的值将会被设置为全局默认值,下面给 - 出一个存储示例。 -\end{environment} - -\begin{verbatim} - \begin{dbitem}[date = 2022-01-01, info = 测试] - \dbsave{question}{这是一个测试问题} - \dbsave{answer} {这是一个测试答案} - \end{dbitem} -\end{verbatim} - -\subsection{\cs{dbsave} 和 \cs{dbuse}} - -\changes{1.3}{2022-01-08}{Add macro}{\cs{dbsave*}} -\begin{function}[added=2022-01-05, updated=2022-01-08]{\dbsave, \dbsave*} - \begin{syntax} - \cs{dbsave} \marg{attr} \marg{data} \\ - \cs{dbsave}* \marg{attr} \marg{data} - \end{syntax} - - \cs{dbsave} 用来存储数据,只能在 \env{item} 环境中使用。使用 \cs{dbsave*} 存 - 储的数据会被 \cs{exp_not:n} 包裹。 -\end{function} - -\changes{1.2}{2022-01-08}{Update macro}{make \cs{dbuse} fully-expandable} -\begin{function}[added=2022-01-05, updated=2022-01-08, EXP]{\dbuse} - \begin{syntax} - \cs{dbuse} \marg{attr} - \end{syntax} - - \cs{dbuse} 用来展示数据,只能在 \opt{item-code} 选项中使用。\cs{dbuse} 是可 - 展开的。 -\end{function} - -\subsection{条件判别式} - -\begin{function}[added=2022-01-05, EXP]{\dbIfEmptyT, \dbIfEmptyF, \dbIfEmptyTF} - \begin{syntax} - \cs{dbIfEmptyTF} \marg{true code} \marg{false code} \\ - \cs{dbIfEmptyT} \marg{true code} \\ - \cs{dbIfEmptyF} \marg{false code} - \end{syntax} - - 该判别式用来判断当前数据库是否为空。下面的示例展示了如何预防空的列表环境。 -\end{function} - -\begin{verbatim} - \dbNewStyle{style-cond1}{database-test}{ - before-code = {\dbIfEmptyF{\begin{enumerate}}}, - after-code = {\dbIfEmptyF{\end{enumerate}}}, - item-code = {\item \dbuse{attr-test}} - } -\end{verbatim} - -\changes{1.2}{2022-01-08}{Remove macros}{\cs{dbItemIfEmpty(TF)}, \cs{dbClistItemIfEmpty(TF)}} - -\subsection{表达式函数} - -\changes{1.3}{2022-01-10}{Add macros}{expression function aliases} -\begin{function}[added=2022-01-10, EXP]{ - \dbIntAbs, \dbIntSign, \dbIntDivRound, \dbIntDivTruncate, \dbIntMax, - \dbIntMin, \dbIntMod, \dbFpSign, -} - \begin{syntax} - \cs{dbIntAbs} \Arg{intexpr} - \cs{dbIntSign} \Arg{intexpr} - \cs{dbIntDivRound} \Arg{intexpr_1} \marg{intexpr_2} - \cs{dbIntDivTruncate} \Arg{intexpr_1} \marg{intexpr_2} - \cs{dbIntMax} \Arg{intexpr_1} \marg{intexpr_2} - \cs{dbIntMin} \Arg{intexpr_1} \marg{intexpr_2} - \cs{dbIntMod} \Arg{intexpr_1} \marg{intexpr_2} - \cs{dbFpSign} \Arg{fpexpr} - \end{syntax} - \cs{dbIntAbs} 等同于 \cs{int_abs:n} \\ - \cs{dbIntSign} 等同于 \cs{int_sign:n} \\ - \cs{dbIntDivRound} 等同于 \cs{int_div_round:nn} \\ - \cs{dbIntDivTruncate} 等同于 \cs{int_div_truncate:nn} \\ - \cs{dbIntMax} 等同于 \cs{int_max:nn} \\ - \cs{dbIntMin} 等同于 \cs{int_min:nn} \\ - \cs{dbIntMod} 等同于 \cs{int_mod:nn} \\ - \cs{dbFpSign} 等同于 \cs{fp_sign:n} \\ - 详细的文档见 \pkg{interface3} \\ -\end{function} - -\subsection{特殊命令} - -\pkg{dbshow} 定义了一些特殊的命令,会根据语境展开为不同的内容。 - -\changes{1.1}{2022-01-05}{Add macro}{ - \cs{dbarabic}, \cs{dbalph}, \cs{dbAlph}, \cs{dbroman}, - \cs{dbRoman} -} -\changes{1.1}{2022-01-06}{Fix bug}{\cs{dbIndex} not defined} -\begin{function}[added=2022-01-05, EXP]{ - \dbval, \dbDatabase, \dbFilterName, \dbFilterInfo, - \dbIndex, \dbarabic, \dbalph, \dbAlph, \dbroman, \dbRoman -} -\begin{tblr}{ll} - \cs{dbval} & 当前属性的值 \\ - \cs{dbDatabase} & 数据库名称 \\ - \cs{dbFilterName} & 当前样式过滤器的名称 \\ - \cs{dbFilterInfo} & 当前样式过滤器的相关信息 \\ - \cs{dbIndex} & 数据索引,等同于 \cs{dbuse}|{id}| \\ - \cs{dbarabic} & 用数字表示的查询集数据计数 \\ - \cs{dbalph} & 用小写字母表示的查询集数据计数 \\ - \cs{dbAlph} & 用大写字母表示的查询集数据计数 \\ - \cs{dbroman} & 用小写罗马字母表示的查询集数据计数 \\ - \cs{dbroman} & 用大写罗马字母表示的查询集数据计数 \\ - \end{tblr} -\end{function} - -\section{错题本示例} -见第 \ref{sec:example} 节。 - -\changes{1.1}{2022-01-07}{Update doc}{improve example} - -\title{ - Package \pkg{dbshow} \version% - \protect\footnote{% - Repository: \url{https://github.com/ZhiyuanLck/dbshow}, - Telegram Group: \url{https://t.me/latex_dbshow}} - \rlap{\makebox[4cm][r]{ - \normalsize $\Longrightarrow$ \color{red} - \linktarget{zh}{en}{中文版本} - }} -} -\author{Li Changkai \texttt{<lichangkai225@qq.com>}} -\date{\endate} -\maketitle - -\section{Introduction} - -The initial motivation to write this package is that I want to write a -template, which can collect questions you gave the wrong answer and can -display those questions you would like to review by some conditionals, such as -questions with certain label, questions you have answered uncorrectly for -certain times or questions having not been reviewed for certain days. So this -package provides a database to do such thing. - -The package provides four core functions: data storage and display, data -filtering, data sorting and data display. All data is saved once and then you -can display these data with custom filters, orders and styles. - -\changes{1.2}{2022-01-09}{Add doc}{descripton for expansion} -\begin{itemize} - \item Macros with a $\star$ are fully-expandable; - \item Macros with a \ding{73} are restricted-expandable; - \item Macros without appending a special symbol are nonexpandable; - \item Options with a $\star$ \textit{do not} affect the expandability of - related macros; - \item Options with a \ding{73} affect the expandability of related macros - according to its value; - \item Options without appending a special symbol make the related macros - nonexpandable. -\end{itemize} - -\subsection{Data Types} - -The package constructs 6 types based on the internal typed of \pkg{expl3}: -\begin{Description}[\texttt{clist}] - \item[\texttt{date}] - date saved in |yyyy/mm/dd| format, supports comparison, sorting - (converting to string), default \cs{dbtoday}. - \item[\texttt{str}] - string,supports regex match and sorting, default empty. - \item[\texttt{tl}] - token list, supports regex match, default empty. - \item[\texttt{int}] - integer, supports comparison and sorting, default 0. - \item[\texttt{fp}] - floating point, supports comparison and sorting, default 0. - \item[\texttt{clist}] - comma list, default empty. -\end{Description} - -\changes{1.3}{2022-01-08}{Remove dependency}{\pkg{datatime2}} -All types are internal types of \pkg{expl3} except |date| type, which provides -by \pkg{dbshow} itself and supports converting to integer and printing with -style. - -\subsection{Comparison to \pkg{datatool}} - -\changes{1.2}{2022-01-07}{Add doc}{add comparison to \pkg{datatool}} - -\pkg{dbshow} and \pkg{datatool} implement the same core functions. But -\pkg{dbshow} is based on \pkg{expl3} and it supports string regex and -multi-level sorting. \pkg{dbshow} tries to divide style from the contents -(data in database): all styles are predefined and can be reused conveniently -so that there can be only codes to save data and one-line code to show the -database inside the \env{document} environment. You can hide the details in -the preamble and focus on the data you want to display. \pkg{dbshow} provides -a simple temporary runtime database, which means it can not input and output -data from/to extern files (they should be responsible by some professional -programming languages). When you need to delete or revise a record, just go to -where it is recorded in the source code rather than use a macro to manipulate -data after they are saved. In a sense, \TeX~file is also a kind of data -persistence. - -\section{Interfaces} - -\subsection{Create, Display and Clear Database} - -\begin{function}[added=2022-01-05]{\dbNewDatabase, \dbNewDatabase*} - \begin{syntax} - \cs{dbNewDatabase} \oarg{base database} \marg{database} \{ \\ - ~~\meta{attr1} = \meta{type spec1}, \\ - ~~\meta{attr2} = \meta{type spec2}, \\ - ~~\ldots{} \\ - \} \\ - \cs{dbNewDatabase}* \marg{database} \{ \\ - ~~\meta{attr1} = \meta{type spec1}, \\ - ~~\meta{attr2} = \meta{type spec2}, \\ - ~~\ldots{} \\ - \} \\ - \end{syntax} - -\end{function} - -Create a new database named \meta{database}, unstarred form provides the optional -\meta{base database} from which current database inherit the attributes settings. -The unstarred form always replace the old definition, while starred form -appends the new options. - -\begin{syntax} - \meta{attr} = \meta{type} \\ - \meta{attr} = \meta{type}\orbar\meta{default} -\end{syntax} - -The first form defines the \meta{attr} as \meta{type}, and the second also -sets the default value. - -\begin{note} - Every database has a default attribute |id| to store the index of the item. -\end{note} - -The example below define a database named |ques|. -\begin{verbatim} - \dbNewDatabase{ques}{ - question = tl, % store question - answer = tl, % store corresponding answer - date = date, % store the date when you were wrong - info = tl, % store extra info - labels = clist % store question labels - } -\end{verbatim} - -\begin{function}[added=2022-01-05]{\dbshow} - \begin{syntax} - \cs{dbshow} \marg{style} \marg{database} - \end{syntax} - - Show the \meta{database} with \meta{style}. -\end{function} - -\changes{1.2}{2022-01-07}{Add macro}{\cs{dbclear}} -\begin{function}[added=2022-01-07]{\dbclear} - \begin{syntax} - \cs{dbclear} \marg{database} - \end{syntax} - - Clear the content of \meta{database}. -\end{function} - -\subsection{\cs{dbNewStyle} and Style Options} - -\begin{function}[added=2022-01-05]{\dbNewStyle} - \begin{syntax} - \cs{dbNewStyle} \oarg{base styles} \marg{style} \marg{database} \marg{opts} - \end{syntax} - - Define a new \meta{style} that binds to \meta{database}. The style can - inherit from a list of \meta{base styles} such as - |\dbNewStyle[base1, base2]{new-style}{ques}{}|. -\end{function} - -\subsubsection{General Options} - -\begin{option}[added=2022-01-05]{filter} - \begin{syntax} - filter = <filter> - \end{syntax} - - Set the \meta{filter} defined by \cs{dbCombineFilters}. -\end{option} - -\changes{1.1}{2022-01-06}{Add option}{\opt{raw-filter}} -\begin{option}[added=2022-01-06]{raw-filter} - \begin{syntax} - raw-filter = <conditional expression> - \end{syntax} - - Set anonymous with conditionals defined by \cs{dbNewConditional}. Two - filters shows in the code below have the same meaning. -\end{option} - -\begin{verbatim} - % method 1 - \begin{dbFilters}{db} - \dbNewConditional{cond1}{int-attr}{\rval > 1} - \dbNewConditional*{cond2}{str-attr}{\d+} - \end{dbFilters} - \dbNewStyle{style}{db}{raw-filter={cond1 && cond2}} - % method 2 - \begin{dbFilters}{db} - \dbNewConditional{cond1}{int-attr}{\rval > 1} - \dbNewConditional*{cond2}{str-attr}{\d+} - \dbCombineFilters{filter}{cond1 && cond2} - \end{dbFilters} - \dbNewStyle{style}{db}{filter=filter} -\end{verbatim} - -\changes{1.2}{2022-01-08}{Fix bug}{string sorting bug} -\begin{option}[added=2022-01-05]{sort} - \begin{syntax} - sort = \{ <attr spec1>, <attr spec2>, \ldots{} \} - \end{syntax} - - Set sorting rules. Attributes of type |str, date, int, fp| is supported to - sort. Multi-level sort is allowed. \meta{attr} represents for ascending - order, and \meta{attr}* represents for descending order. The example below - use four fields to determine the order of the records. It sorts on |level| - in descending order first and if two |levels| are same then sorts on |birth| - in ascending order and so on. -\end{option} - -\begin{verbatim} - \dbNewDatabase{sort-example}{ - name = str, - birth = date, - level = int, - weight = fp, - } - \dbNewStyle{sort-style}{sort-example}{ - sort = { level*, birth, name, weight } - } -\end{verbatim} - -\begin{option}[added=2022-01-05, rEXP]{item-code} - \begin{syntax} - item-code = <code> - \end{syntax} - - Set the code that show a single record. You can use \cs{dbuse} to display - certian attribute. -\end{option} - -\changes{1.3}{2022-01-09}{Update option}{\opt{<attr>/sep}} -\begin{option}[added=2022-01-05, updated=2022-01-08, rEXP]{<attr>/sep} - \begin{syntax} - <attr>/sep = <separator> \\ - <attr>/sep = \{ \\ - ~~\meta{separator between two}, \\ - ~~\meta{separator between more than two}, \\ - ~~\meta{separator between final two} \\ - \} \\ - <attr>/sep = \{ \\ - ~~\meta{separator before year}, \\ - ~~\meta{separator between year and month}, \\ - ~~\meta{separator between month and day}, \\ - ~~\meta{separator after day} \\ - \} \\ - \end{syntax} - - Only for attributes of type |clist| or |date|. Set the separator between - items. If the argument is an one-item comma list, all separators are set to - \meta{separator} but \meta{separator before year} and \meta{separator after - day} is set empty. -\end{option} - - If the argument is a comma list of 3 items, it is used to set the separator - between items of the comma list. Following documentation is quoted from - \pkg{interface3}: - \begin{quote} - If the comma list has more than two items, the \meta{separator between - more than two} is placed between each pair of items except the last, for - which the \meta{separator between final two} is used. If the comma list - has exactly two items, then they are placed in the input stream separated - by the \meta{separator between two}. If the comma list has a single item, - it is placed in the input stream, and a comma list with no items produces - no output. - \end{quote} - For attributes of type |clist|, incorrect number (numbers exclude 1 and 3) - of items of the argument will raise an error. - -\begin{verbatim} - % clist-attr is an attribute of database db - % suppose the val of clist-attr is { 1, 2, 3 } - \dbNewStyle{clist-sep}{db}{ - clist-attr/sep = { ,~ }, % print 1, 2, 3 - clist-attr/sep = { {,~}, {,~}, {and~} } % print 1, 2 and 3 - } -\end{verbatim} - - If the argument is a comma list of 4 items, it is used to set the separators - of the date. For attributes of type |date|, incorrect number (numbers - exclude 1 and 4) will raise an error. - -\begin{verbatim} - % date-attr is an attribute of database db - % suppose the val of date-attr is 2022/01/01 - \dbNewStyle{date-sep}{db}{ - date-attr/sep = -, % print 2022-01-01 - date-attr/sep = { |, -, -, | } % print |2022-01-01| - } -\end{verbatim} - -\changes{1.3}{2022-01-08}{Add option}{\opt{<attr>/zfill}} -\begin{option}[added=2022-01-08, EXP]{<attr>/zfill} - \begin{syntax} - <attr>/zfill = <\TTF> - \end{syntax} - - Only for attributes of type |date|. Control whether to fill zero on the left - of the month or day. -\end{option} - -\subsubsection{Decorators} - -The options below serves as decorators. In some cases, decorator can also be -encoded directly into |item-code| or some other places, which is convenient -sometimes. The benefit of defining decorators with options is that styles step -further to be divided with contents. In the examples below, \meta{style1} and -\meta{style2} is the same style, which wrap \meta{attr1} with *. When you want -another style which wrap \meta{attr1} with =, if you choose the way of -\meta{style1}, \meta{item code} are repeated, otherwise if you choose the way -of \meta{style2}, \meta{item code} is inherited and you only need define the -decorators. - -\begin{verbatim} - \dbNewStyle{style1}{db}{ - item-code = {% - *\rvuse{attr1}*\rvuse{attr2} - % more code - } - } - \dbNewStyle{base-style}{db}{ - item-code = {% - \rvuse{attr1}\rvuse{attr2} - % more code - } - } - \dbNewStyle[base-style]{style2}{db}{ - attr1/before-code = { * }, - attr1/after-code = { * }, - } - \dbNewStyle[base-style]{style3}{db}{ - attr1/before-code = { = }, - attr1/after-code = { = }, - } -\end{verbatim} - -\changes{1.3}{2022-01-08}{Add option}{\opt{<attr>/wrapper}} -\begin{option}[added=2022-01-08, rEXP]{<attr>/wrapper} - \begin{syntax} - <attr>/wrapper = <control sequence> - \end{syntax} - - Only for attributes of type |date|. Output of \cs{dbuse}\marg{date attr} - will be \meta{control sequence}\marg{date}. -\end{option} - -\begin{option}[added=2022-01-05, rEXP]{before-code} - \begin{syntax} - before-code = <code> - \end{syntax} - - Set the \meta{code} that is executed \enbefore displaying the database. -\end{option} - -\begin{option}[added=2022-01-05, rEXP]{after-code} - \begin{syntax} - after-code = <code> - \end{syntax} - - Set the \meta{code} that is executed \enafter displaying the database. -\end{option} - -\changes{1.2}{2022-01-08}{Add options}{\opt{record-before-code}, -\opt{record-after-code}} -\begin{option}[added=2022-01-05, rEXP]{record-before-code} - \begin{syntax} - record-before-code = <code> - \end{syntax} - - Set the \meta{code} that is executed \enbefore displaying a record. -\end{option} - -\begin{option}[added=2022-01-05, rEXP]{record-after-code} - \begin{syntax} - record-after-code = <code> - \end{syntax} - - Set the \meta{code} that is executed \enafter displaying the record. -\end{option} - -\begin{option}[added=2022-01-05, rEXP]{<attr>/before-code} - \begin{syntax} - <attr>/before-code = <code> - \end{syntax} - - Set the \meta{code} that is executed by \cs{dbuse} \enbefore displaying - certain attribute. -\end{option} - -\begin{option}[added=2022-01-05, rEXP]{<attr>/after-code} - \begin{syntax} - <attr>/after-code = <code> - \end{syntax} - - Set the \meta{code} that is executed by \cs{dbuse} \enafter displaying - certain attribute. -\end{option} - -\begin{option}[added=2022-01-05, rEXP]{<attr>/item-before-code} - \begin{syntax} - <attr>/item-before-code = <code> - \end{syntax} - - Only for attributes of type |clist|. Set the \meta{code} that is excuted - \enbefore displaying the item of the comma list. -\end{option} - -\begin{option}[added=2022-01-05, rEXP]{<attr>/item-after-code} - \begin{syntax} - <attr>/item-after-code = <code> - \end{syntax} - - Only for attributes of type |clist|. Set the \meta{code} that is excuted - \enafter displaying the item of the comma list. -\end{option} - -\subsection{Use \cs{dbNewReviewPoints} to Define Review Points} - -\begin{function}[added=2022-01-05]{\dbNewReviewPoints} - \begin{syntax} - \cs{dbNewReviewPoints} \marg{name} \marg{points} - \end{syntax} - - Define the new \meta{points} that is specially designed for reviewing - something. \meta{points} is a list of integers. Suppose you record the date - when you did not answer correctly and you plan to review every 2, 5 and 15 - days. The following code give what you want. -\end{function} - -\begin{verbatim} - \dbNewReviewPoints{review-point}{2, 5, 15} % define points - \begin{dbFilters} - \dbNewConditional{cond1}{date}{review-point|\Today} % define conditional - \dbCombineConditionals{filter1}{cond1} % define filter - \end{dbFilters} - \dbNewStyle{review-style}{ques}{filter=filter1} % define style -\end{verbatim} - -\subsection{Define Filters inside \env{dbFilters} Environment} - -\begin{environment}[added=2022-01-05]{dbFilters} - \begin{syntax} - |\begin{dbFilters}|\marg{database} \\ - ~~\meta{code} - |\end{dbFilters}| \\ - \end{syntax} - - Filters are defined inside \env{dbFilters} environment, inside which, - \cs{dbNewConditional} is defined to declare conditionals and - \cs{dbCombineConditionals} is defined to combine conditionals. Filters are - independent in different databases, which means the same name of filters is - allowed in different databases. -\end{environment} - -\begin{function}[added=2022-01-05, updated=2022-01-08]{\dbNewConditional, \dbNewConditional*} - \begin{syntax} - \cs{dbNewConditional} \marg{name} \marg{attr} \marg{cond spec} \\ - \cs{dbNewConditional}* \marg{name} \marg{attr} \marg{cond spec} \\[2pt] - \cs{dbNewConditional} \marg{name} \marg{int/fp attr} \marg{expr} \\ - \cs{dbNewConditional}* \marg{name} \marg{int/fp attr} \marg{expr} \\ - \cs{dbNewConditional} \marg{name} \marg{str/tl attr} \marg{regex expr} \\ - \cs{dbNewConditional}* \marg{name} \marg{str/tl attr} \marg{regex expr} \\ - \cs{dbNewConditional} \marg{name} \marg{clist attr} \marg{val list} \\ - \cs{dbNewConditional}* \marg{name} \marg{clist attr} \marg{val list} \\ - \cs{dbNewConditional} \marg{name} \marg{date attr} \marg{expr} - \cs{dbNewConditional}* \marg{name} \marg{date attr} \{\meta{review points}\orbar\meta{date}\} \\ - \end{syntax} - - Define the conditional named \meta{name} that binds to \meta{attr}. \cs{dbval} - is replaced with the real value of the attribute inside the \meta{cond spec}. -\end{function} - - \changes{1.3}{2022-01-10}{Update doc}{truncated division} - For attributes of type |int| and |fp|, \meta{expr} is passed to - \cs{int_compare:nTF} or \cs{fp_compare:nTF}. - \begin{note} - Division using |/| rounds to the closest integer. Use \cs{dbIntDivTruncate} to rounds - the result toward 0. - \end{note} - - For attribute of type |str| and |tl|, unstarred form matches any part while - starred form matches the whole part with the \meta{regex expr}. - -\begin{verbatim} - \dbNewConditional {cond1}{str-attr}{abc} % match abc, abcd, 1abc, =abc=, etc - \dbNewConditional*{cond2}{str-attr}{abc} % only match abc -\end{verbatim} - - For attributes of type |clist|, the conditional defined by unstarred form is - true if any item of \meta{val list} is in the comma list. While the - conditional defined by starred form is true only if every item of \meta{val - list} is in the comma list. As is showed below, for |cond1|, |a| is in - |{a, b, d}| so |cond1| is true. While |c| is not in |{a, b, d}| so |cond2| - is false. - -\begin{verbatim} - \dbNewConditional {cond1}{clist-attr}{a, b, c} % {a, b, d} -> true - \dbNewConditional*{cond2}{clist-attr}{a, b, c} % {a, b, d} -> false -\end{verbatim} - - \changes{1.3}{2022-01-08}{Update logic}{swap definition of starred and - unstarred conditionals of date} - For attributes of type |date|, unstarred form replace each date with a - integer representing for the days between \meta{date} and - \textit{1971/01/01}, and the result is passed to \cs{int_compare:nTF}. - Starred form defines the conditional with review points defined by - \cs{dbNewRdbNewReviewPoints} and \meta{date} is the date to be compared. - -\begin{function}[added=2022-01-05]{\dbCombineConditionals} - \begin{syntax} - \cs{dbCombineConditionals} \marg{name} \marg{cond combination} \oarg{info} - \end{syntax} - - Define the filter \meta{name}, which combine the conditionals and store the - extra \meta{info} into \cs{dbFilterInfo}. So you can write something as\\ - \verb=\dbCombineConditionals{filter}{(cond1 && cond2) || !cond3}=.\\ - Supported operators are \verb=&&, ||, !=. You can set the option \opt{filter} - to \meta{name} to apply the filter when you display the database. -\end{function} - -\subsection{Store Data with \env{dbitem} Environment} - -\begin{environment}[added=2022-01-05]{dbitem} - \begin{syntax} - |\begin{dbitem}|\marg{database}[ \\ - ~~\meta{attr1} = \meta{val1}, \\ - ~~\meta{attr2} = \meta{val2}, \\ - ~~\ldots{} \\ - ] \\ - ~~\meta{code} \\ - |\end{dbitem}| - \end{syntax} - - The data are stored with \env{dbitem} environment in two ways. Smaller data - can be stored in the option list and the bigger data can be stored by - \cs{dbsave}, which will suppress the value set by the option list. An - example code is showned below. -\end{environment} - -\begin{verbatim} - \begin{dbitem}[date=2022-01-01, info=test] - \dbsave{question}{This is a test question.} - \dbsave{answer} {This is a test answer.} - \end{dbitem} -\end{verbatim} - -\subsection{\cs{dbsave} and \cs{dbuse}} - -\changes{1.3}{2022-01-08}{Add macro}{\cs{dbsave*}} -\begin{function}[added=2022-01-05, updated=2022-01-08]{\dbsave, \dbsave*} - \begin{syntax} - \cs{dbsave} \marg{attr} \marg{data} \\ - \cs{dbsave}* \marg{attr} \marg{data} - \end{syntax} - - \cs{dbsave} save the \meta{data} to \meta{attr} of current record. - \cs{dbsave} can be used only inside the \env{dbitem} environment. - \meta{data} stored by \cs{dbsave*} is wrapped with \cs{exp_not:n} while - \meta{data} stored by \cs{dbsave} keeps the same. -\end{function} - -\changes{1.2}{2022-01-08}{Update macro}{make \cs{dbuse} fully-expandable} -\begin{function}[added=2022-01-05, updated=2022-01-08, EXP]{\dbuse} - \begin{syntax} - \cs{dbuse} \marg{attr} - \end{syntax} - - Display the value of \meta{attr} of current record. \cs{dbuse} is - \textbf{expandable} and can be only used inside the option \opt{item-code}. -\end{function} - -\subsection{Conditionals} - -\begin{function}[added=2022-01-05, EXP]{\dbIfEmptyT, \dbIfEmptyF, \dbIfEmptyTF} - \begin{syntax} - \cs{dbIfEmptyTF} \marg{true code} \marg{false code} \\ - \cs{dbIfEmptyT} \marg{true code} \\ - \cs{dbIfEmptyF} \marg{false code} - \end{syntax} - - Test if the database is empty. The example below shows how to avoid an empty - list environment. -\end{function} - -\begin{verbatim} - \dbNewStyle{style-cond1}{database-test}{ - before-code = {\dbIfEmptyF{\begin{enumerate}}}, - after-code = {\dbIfEmptyF{\end{enumerate}}}, - item-code = {\item \dbuse{attr-test}} - } -\end{verbatim} - -\changes{1.2}{2022-01-08}{Remove macros}{\cs{dbItemIfEmpty(TF)}, \cs{dbClistItemIfEmpty(TF)}} - -\subsection{Expression Functions} - -\changes{1.3}{2022-01-10}{Add macros}{expression function aliases} -\begin{function}[added=2022-01-10, EXP]{ - \dbIntAbs, \dbIntSign, \dbIntDivRound, \dbIntDivTruncate, \dbIntMax, - \dbIntMin, \dbIntMod, \dbFpSign, -} - \begin{syntax} - \cs{dbIntAbs} \Arg{intexpr} - \cs{dbIntSign} \Arg{intexpr} - \cs{dbIntDivRound} \Arg{intexpr_1} \marg{intexpr_2} - \cs{dbIntDivTruncate} \Arg{intexpr_1} \marg{intexpr_2} - \cs{dbIntMax} \Arg{intexpr_1} \marg{intexpr_2} - \cs{dbIntMin} \Arg{intexpr_1} \marg{intexpr_2} - \cs{dbIntMod} \Arg{intexpr_1} \marg{intexpr_2} - \cs{dbFpSign} \Arg{fpexpr} - \end{syntax} - \cs{dbIntAbs} is identical to \cs{int_abs:n} \\ - \cs{dbIntSign} is identical to \cs{int_sign:n} \\ - \cs{dbIntDivRound} is identical to \cs{int_div_round:nn} \\ - \cs{dbIntDivTruncate} is identical to \cs{int_div_truncate:nn} \\ - \cs{dbIntMax} is identical to \cs{int_max:nn} \\ - \cs{dbIntMin} is identical to \cs{int_min:nn} \\ - \cs{dbIntMod} is identical to \cs{int_mod:nn} \\ - \cs{dbFpSign} is identical to \cs{fp_sign:n} \\ - Detailed documentation see \pkg{interface3} \\ -\end{function} - -\subsection{Special Macros} - -Some special macros are defined to expand to different contents according to context. - -\changes{1.1}{2022-01-05}{Add macro}{ - \cs{dbarabic}, \cs{dbalph}, \cs{dbAlph}, \cs{dbroman}, - \cs{dbRoman} -} -\changes{1.1}{2022-01-06}{Fix bug}{\cs{dbIndex} not defined} -\begin{function}[added=2022-01-05, EXP]{ - \dbval, \dbDatabase, \dbFilterName, \dbFilterInfo, - \dbIndex, \dbarabic, \dbalph, \dbAlph, \dbroman, \dbRoman -} -\begin{tblr}{ll} - \cs{dbval} & Attribute value, only according in \cs{dbNewConditional}. \\ - \cs{dbDatabase} & Database name. \\ - \cs{dbFilterName} & Filter name. \\ - \cs{dbFilterInfo} & Filter information. \\ - \cs{dbIndex} & Record index, identical to \cs{dbuse}|{id}| \\ - \cs{dbarabic} & Show the counter of query set as digits. \\ - \cs{dbalph} & Show the counter of query set as lowercase letters. \\ - \cs{dbAlph} & Show the counter of query set as uppercase letters. \\ - \cs{dbroman} & Show the counter of query set as lowercase roman numerals. \\ - \cs{dbroman} & Show the counter of query set as uppercase roman numerals. \\ - \end{tblr} -\end{function} - -\section{Example of Flaw Sweeper Template} -\label{sec:example} - -\changes{1.1}{2022-01-07}{Update doc}{improve example} - -\begin{tcblisting}{enhanced jigsaw,lower separated=false, - leftlower=0pt,rightlower=0pt, - colframe=red!50!black,colback=yellow!10!white, - listing options={style=tcblatex,texcsstyle=*\color{red!70!black}}, - listing and comment, - pdf comment,freeze pdf, - compilable listing, - breakable, - run pdflatex -} -\documentclass{article} -\usepackage{amsmath, physics} -\usepackage{geometry} -\usepackage{dbshow} -\usepackage{tikz} -\usepackage{tcolorbox} -\tcbuselibrary{skins} -\usetikzlibrary{shadings} -\usepackage[hidelinks]{hyperref} - -\geometry{ - margin=2cm -} - -% #1 link node #2 target node #3 text to show -\NewDocumentCommand \linktarget { m m m } {% - \hyperlink{#1}{#3}% - \raisebox{1em}{\hypertarget{#2}{}}% -} - -% question box -\tcbset{ - base/.style={ - empty, - frame engine=path, - colframe=yellow!10, - coltitle=red!70, - fonttitle=\bfseries\sffamily, - sharp corners, - left=4pt, - right=4pt, - drop fuzzy shadow, - drop fuzzy shadow, - borderline west={3pt}{-3pt}{red!80}, - } -} - -\newtcolorbox{mybox}[1]{% - base, title = {#1} -} - -\dbNewReviewPoints{review}{1, 3, 7, 15, 30, 60} - -\dbNewDatabase{ques-book}{ - ques = tl, - answer = tl, - count = int|1, - labels = clist, - date = date, -} - -\begin{dbFilters}{ques-book} - \dbNewConditional{hard}{labels}{hard} - \dbNewConditional{bad}{count}{\dbval > 1} - \dbNewConditional*{review}{date}{review|2022/01/07} - \dbNewConditional{after}{date}{\dbval > 2022/01/02} -\end{dbFilters} - -% show all questions with hyperlink to answers -\dbNewStyle{ques}{ques-book}{ - before-code = {\section{Questions}}, - item-code = { - \begin{mybox}{% - \linktarget{answer_\dbIndex}{ques_\dbIndex}{% - Question \dbarabic% - \hspace{2em}\dbuse{date}% - \hspace{2em}\dbuse{labels}% - \hfill\dbuse{count}% - }% - } - \dbuse{ques}% - \end{mybox} - }, - labels/sep = /, -} - -% show all questions and answers with hyperlink to questions -\dbNewStyle{answer}{ques-book}{ - before-code = {\section{Questions and Answers}}, - item-code = { - \begin{mybox}{% - \linktarget{ques_\dbIndex}{answer_\dbIndex}{% - Question \dbarabic% - \hspace{2em}\dbuse{date}% - \hspace{2em}\dbuse{labels}% - \hfill\dbuse{count}% - }% - } - \dbuse{ques}\tcbsubtitle{Answer}\dbuse{answer}% - \end{mybox} - }, - labels/sep = /, -} - -% show all hard questions with hyperlink to answers -\dbNewStyle{hard}{ques-book}{ - before-code = {\section{Hard Questions}}, - item-code = { - \begin{mybox}{% - \hyperlink{answer_\dbIndex}{% - Question \dbarabic% - \hspace{2em}\dbuse{date}% - \hspace{2em}\dbuse{labels}% - \hfill\dbuse{count}% - }% - } - \dbuse{ques}% - \end{mybox} - }, - raw-filter = hard, - labels/sep = /, -} - -% show all hard questions that have been answered incorrectly for more than -% one time with hyperlink to answers -\dbNewStyle[hard]{bad}{ques-book}{ - before-code = {\section{Bad Questions}}, - raw-filter = {bad && hard}, -} -% show all questions that plan to be reviewed on 2022/01/07 with hyperlink to -% answers -\dbNewStyle[hard]{review}{ques-book}{ - before-code = {\section{Questions to be Reviewed}}, - raw-filter = {review}, -} -% show all questions that is record after 2022/01/02 with hyperlink to answers -\dbNewStyle[hard]{after}{ques-book}{ - before-code = {\section{Questions after 2022/01/02}}, - raw-filter = {after}, -} - -\AtEndDocument{ - \dbshow{review}{ques-book} - \dbshow{hard}{ques-book} - \dbshow{bad}{ques-book} - \dbshow{after}{ques-book} - \dbshow{ques}{ques-book} - \dbshow{answer}{ques-book} -} - -\begin{document} - -\begin{dbitem}{ques-book}[ - date=2022/01/01, - labels={math, equation, easy}, - count=2 - ] - \dbsave{ques}{% - Solve the linear equation: $x + 16 = 31$. - } - \dbsave{answer}{% - $x = 31 - 16 = 15$ - } -\end{dbitem} - -\begin{dbitem}{ques-book}[ - date=2022/01/01, - labels={math, equation, hard}, - count=3 - ] - \dbsave{ques}{% - Solve the linear equation: $2y = 16$. - } - \dbsave{answer}{% - $y = 16 / 2 = 8$ - } -\end{dbitem} - -\begin{dbitem}{ques-book}[ - date=2022/01/04, - labels={math, integral, hard}, - count=1 - ] - \dbsave{ques}{% - Find the indefinite integral: $\int 2x \dd x$. - } - \dbsave{answer}{% - $\int 2x \dd x = x^2$ - } -\end{dbitem} - -\end{document} -\end{tcblisting} - -\end{documentation} -\end{document} diff --git a/macros/latex/contrib/dbshow/dbshow.dtx b/macros/latex/contrib/dbshow/dbshow.dtx new file mode 100644 index 0000000000..a2af27d922 --- /dev/null +++ b/macros/latex/contrib/dbshow/dbshow.dtx @@ -0,0 +1,3740 @@ +% \iffalse meta-comment +%<*internal> +\iffalse +%</internal> +%<*readme> +Package dbshow +============== + +Introduction +------------ + +The package provides four core functions: + +1. data storage +2. data filtering +3. data sorting +4. data display + +All data is saved once and then you can display these data with custom filters, +orders and styles. The package can be used, for example, to record and +display something you'd like to review, maybe the question you always answered +incorrectly or some forgettable knowledge. But obviously, the package is much +more powerful and extensible for more interesting tasks depending on the +individual. + +Install +------- + +If you are using TeX Live, install `dbshow` by `tlmgr` package manager + + tlmgr update --self --all + tlmgr install dbshow + +You can also download the zip file from +[CTAN](https://ctan.org/pkg/dbshow) or +[GitHub](https://github.com/ZhiyuanLck/dbshow/releases/latest). + +The zip file should contain the file `dbshow.dtx`, and you can extract +`dbshow.sty` from it by + + tex dbshow.dtx + +Compile Document +---------------- + +Use following commands to compile the document: + + git clone https://github.com/ZhiyuanLck/dbshow.git + cd dbshow + latexmk dbshow.dtx + +Copyright and License +--------------------- + + Copyright (C) 2022- by Changkai Li <lichangkai225@qq.com> + -------------------------------------------------------------------------- + + This work may be distributed and/or modified under the + conditions of the LaTeX Project Public License, either + version 1.3c of this license or (at your option) any later + version. This version of this license is in + http://www.latex-project.org/lppl/lppl-1-3c.txt + and 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 Changkai Li. + + This package consists of the file dbshow.dtx, + and the derived files dbshow.pdf, + dbshow.sty, + dbshow.ins and + README.md (this file). +%</readme> +%<*internal> +\fi +\begingroup + \def\temp{LaTeX2e} +\expandafter\endgroup\ifx\temp\fmtname\else +\csname fi\endcsname +%</internal> +%<*install> + +\input l3docstrip.tex +\keepsilent +\askforoverwritefalse +\preamble + + Copyright (C) 2022- by Changkai Li <lichangkai225@qq.com> + -------------------------------------------------------------------------- + + This work may be distributed and/or modified under the + conditions of the LaTeX Project Public License, either + version 1.3c of this license or (at your option) any later + version. This version of this license is in + http://www.latex-project.org/lppl/lppl-1-3c.txt + and 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 Changkai Li. + + This package consists of the file dbshow.dtx, + and the derived files dbshow.pdf, + dbshow.sty, + dbshow.ins and + README.md. + -------------------------------------------------------------------------- + +\endpreamble +\postamble + + -------------------------------------------------------------------------- + This package consists of the file dbshow.dtx, + and the derived files dbshow.pdf, + dbshow.sty, + dbshow.ins and + README.md. +\endpostamble + +\generate{ +%</install> +%<*internal> + \usedir{source/latex/dbshow} + \file{dbshow.ins}{\from{\jobname.dtx}{install}} +%</internal> +%<*install> + \usedir{tex/latex/dbshow} + \file{dbshow.sty}{\from{\jobname.dtx}{package}} + \nopreamble\nopostamble + \usedir{doc/latex/dbshow} + \file{README.md} {\from{\jobname.dtx}{readme}} +} +\endbatchfile +%</install> +%<*internal> +\fi +%</internal> +%<package>\NeedsTeXFormat{LaTeX2e} +%<+package|config>\GetIdInfo$Id: dbshow.dtx 461d9bb 2022-01-14 02:50:24 +0800 Changkai Li <lichangkai225@qq.com> $ +%<package> {Database to store and display data} +%<package>\ProvidesExplPackage{\ExplFileName} +%<package|config> {\ExplFileDate}{1.4}{\ExplFileDescription} +%<*driver> +\documentclass[full]{l3doc} +\usepackage[scheme=plain, fontset=ubuntu]{ctex} +\usepackage{dbshow} +\usepackage{adjustbox} +\usepackage{zhlineskip} +\usepackage{enumitem} +\usepackage{indentfirst} +\usepackage{titling} +\usepackage{geometry} +\usepackage{tabularray} +\usepackage{xcolor} +\usepackage{tabularray} +\usepackage{zhnumber} + +\geometry{ + left=4.5cm, + right=2cm, + top=2cm, + bottom=2cm, +} +\hypersetup { + CJKbookmarks, + bookmarksopen, + bookmarksopenlevel=3, + pdfstartview=FitH, + pdfinfo = { + Title = The package 'dbshow' , + Subject = A LaTeX package , + Author = Li Changkai + } +} + +\IndexPrologue { + \part*{Index} + \markboth{Index}{Index} + \addcontentsline{toc}{part}{Index} + The~italic~numbers~denote~the~pages~where~the~ + corresponding~entry~is~described,~ + numbers~underlined~point~to~the~definition,~ + all~others~indicate~the~places~where~it~is~used. +} + +\GlossaryPrologue { + \part*{Change~History} + {\GlossaryParms\ttfamily\hyphenchar\font=`\-} + \markboth{Change~History}{Change~History} + \addcontentsline{toc}{part}{Change~History} +} + +\let\subsubitem\subitem + +\DoNotIndex{\begin, \end} +\setlength{\parskip}{\medskipamount} + +\newcommand\tikzmark[1]{\tikz \coordinate[overlay, remember picture] (#1);} +\def\levelchar{?} +\def\orbar{\textup{\textbar}} +\def\defaultval#1{\textbf{\textup{#1}}} +\def\TF{true\orbar false} +\def\TTF{\defaultval{true}\orbar false} +\def\TFF{true\orbar\defaultval{false}} +\def\zhbefore{\textbf{前}} +\def\zhafter{\textbf{后}} +\def\enbefore{\textbf{before}~} +\def\enafter{\textbf{after}~} +\DeclareDocumentEnvironment { note } { +b } { + \par\textbf{\textsf{NOTE:~}}#1\par +} {} + +\ExplSyntaxOn +\makeatletter + +\DeclareDocumentCommand { \csnot } { m } { + \group_begin:\ttfamily + \tl_set:Nn \l_csnot_tl { \c_backslash_str #1 } + \tl_replace_all:Nnn \l_csnot_tl { ~ } { \@xobeysp } + \l_csnot_tl + \group_end: +} + +\DeclareDocumentEnvironment{ arguments } { O{1} } { + \tl_set:Nx \l_tmpa_tl { + \int_case:nn {#1} { + { 1 } { \# } + { 2 } { \#\# } + { 3 } { \#\#\#\# } + } + } + \enumerate [ + nolistsep , + label = \texttt{\l_tmpa_tl\arabic*} ~ : , + labelsep = * , + labelwidth = !, + align=left, + ] +} { \endenumerate } + +\DoNotIndex{\begin, \end} + +\renewenvironment{theglossary}{ +\glossary@prologue\GlossaryParms \let\item\@idxitem \ignorespaces}{} + +\cs_gset_eq:NN \dbshowdocnull \use_none:n + +% #1 sort #2 group #3 date #4 type #5 desc +\cs_new_protected:Nn \dbshowdoc_changes:nnnnn { + \@bsphack\group_begin:\@sanitize + \catcode`\\\z@ \catcode`\ 10 \MakePercentIgnore + \exp_args:Nx \glossary { + \dbshowdocnull{#1}~ + \exp_not:N \textbf{#2} + \exp_not:n { \raisebox{1em}{\pdfbookmark[1]{#2}{#2}} } + \levelchar + \exp_not:N \textup{#3}\c_space_tl + \exp_not:N \textbf{#4}\c_colon_str\c_space_tl + \exp_not:n {#5} + } + \group_end:\@esphack +} +\cs_generate_variant:Nn \dbshowdoc_changes:nnnnn { xxnnn, VVnnn } + +\cs_new_protected:Nn \dbshowdoc_print_version:n { + v#1 + \int_compare:nNnT { \str_count:n {#1} } = { 3 } { \phantom{0} } + \c_space_tl +} +\cs_set_eq:NN \dbshowdocver \dbshowdoc_print_version:n + +% #1 ver #2 date #3 type #4 desc +\cs_new_protected:Nn \dbshowdoc_changes_what:nnnn { + \regex_extract_once:nnNT { doc|macro|bug|option } + {#3} \l_tmpa_seq { + \tl_set:Nx \l_tmpa_tl { + \str_case_e:nn { \seq_item:Nn \l_tmpa_seq { 1 } } { + { doc } { Documentation } + { macro } { Macro } + { bug } { Bug } + { option } { Option } + { logic } { Logic } + } + } + \dbshowdoc_changes:VVnnn \l_tmpa_tl \l_tmpa_tl + { \dbshowdocver{#1}#2 } {#3} {#4} + } +} + +% #1 ver #2 date #3 type #4 desc +\cs_new_protected:Nn \dbshowdoc_changes_how:nnnn { + \regex_extract_once:nnNT { Add|Update|Remove|Fix } + {#3} \l_tmpa_seq { + \dbshowdoc_changes:xxnnn + { \seq_item:Nn \l_tmpa_seq { 1 } } + { \seq_item:Nn \l_tmpa_seq { 1 } } + { \dbshowdocver{#1}#2 } {#3} {#4} + } +} + +\cs_new:Nn \dbshowdoc_fill_two:n { + \int_compare:nNnTF {#1} > { 9 } + {#1} { 0#1 } +} + +% #1 major number #2 minor number +\cs_new_protected:Npn \dbshowdoc_changes_ver:w #1.#2\dbshowdoc_stop { + \dbshowdoc_changes:xxnnn { #1.\dbshowdoc_fill_two:n {#2} } +} + +% #1 ver #2 date #3 type #4 desc +\DeclareDocumentCommand \changes { m m m m } { + \dbshowdoc_changes_ver:w #1\dbshowdoc_stop {#1} {#2} {#3} {#4} + \dbshowdoc_changes_what:nnnn {#1} {#2} {#3} {#4} + \dbshowdoc_changes_how:nnnn {#1} {#2} {#3} {#4} +} +\makeatother + +\DeclareDocumentEnvironment { Description } { o +b } { + \hbox_set:Nn \l_tmpa_box {#1} + \dim_set:Nn \l_tmpa_dim { \box_wd:N \l_tmpa_box } + \begin{itemize}[ + itemindent=0pt, + labelindent=0pt, + labelwidth=\l_tmpa_dim, + leftmargin=!, + align=left] + #2 + \end{itemize} +} {} + +\cs_new_protected:Nn \dbshowdoc_function_begin:N { + \cs_set_eq:NN \__codedoc_tmp_cs:nN \__codedoc_typeset_function_block:nN + \cs_set_protected:Npn \__codedoc_typeset_function_block:nN ##1##2 { + \__codedoc_function_label:xN {##1} ##2 + \hbox_set:Nn \l_tmpa_box {##1} + \int_compare:nTF { \str_count:n {##1} <= 22 } + {##1} { \adjustbox{width=.7\marginparwidth, height=\box_ht:N \l_tmpa_box}{##1} } + #1{##1} + \__codedoc_typeset_expandability: \\ + } +} +\cs_new_protected:Nn \dbshowdoc_function_end: { + \cs_set_eq:NN \__codedoc_typeset_function_block:nN \__codedoc_tmp_cs:nN +} +\DeclareDocumentEnvironment { option } { O{} +v } + { + \dbshowdoc_function_begin:N \SpecialOptionIndex + \__codedoc_function:nnw {#1} {#2} + } + { + \__codedoc_function_end: + \dbshowdoc_function_end: + } +\DeclareDocumentEnvironment { environment } { O{} +v } + { + \dbshowdoc_function_begin:N \SpecialEnvIndex + \__codedoc_function:nnw {#1} {#2} + } + { + \__codedoc_function_end: + \dbshowdoc_function_end: + } + +\DeclareDocumentCommand \opt { O{} m } + { \__codedoc_cmd:no {#1} {#2} } + +\NewDocumentCommand \linktarget { m m m } {% + \hyperlink{#1}{#3}% + \raisebox{1em}{\hypertarget{#2}{}}% +} + +\DeclareDocumentCommand \GetFileId { m } { + \GetFileInfo {#1} + \file_get:nnNTF { \c_sys_jobname_str .id } + { \int_set:Nn \tex_endlinechar:D { -1 } } \l__ctxdoc_tmp_tl + { \exp_after:wN \GetIdInfo \l__ctxdoc_tmp_tl } + { \GetIdInfo $Id$ } + { \fileinfo } +} +\ExplSyntaxOff + +\begin{document} +\DocInput{dbshow.dtx} +\newgeometry{ + left=2cm, + right=2cm, + top=2cm, + bottom=2cm +} +\changes{1.4}{2022-01-10}{Fix doc code}{wrong changes history sorting} +\PrintChanges +\PrintIndex +\end{document} +%</driver> +% \fi +% +% \CheckSum{882} +% \GetFileId{dbshow.sty} +% +% \ExplSyntaxOn +% \tl_set:Nx \cnfiledate{ \exp_args:NV \zhdate\filedate } +% \ExplSyntaxOff +% +% \title{ +% \pkg{dbshow} 宏包 \fileversion% +% \protect\footnote{% +% 代码仓库:\url{https://github.com/ZhiyuanLck/dbshow}, +% QQ群:788706534} +% \rlap{\makebox[4cm][r]{ +% \normalsize $\Longrightarrow$ \color{red} +% \linktarget{en}{zh}{English Version} +% }} +% } +% \author{\textit{李昌锴} \protect\path{<lichangkai225@qq.com>}} +% \date{\cnfiledate} +% \maketitle +% +% \tableofcontents +% +% \begin{documentation} +% +% \section{引言} +% 编写本宏包的动机来源于当前没有一个很好的错题本宏包,可以方便的根据各种条件对错 +% 题进行筛选、排序,然后以自定义的样式展示出来。\pkg{dbshow} 宏包实现了四个核心 +% 功能:数据存储和使用、数据筛选、数据排序、数据展示。 +% +% 数据只需要存储一次,就可以通过预定义的筛选、排序条件和样式展示部分或全部的数据。 +% 如上所述,本宏包其实实现了一个非常简单的数据库,复习错题的功能只是其中一个应用, +% 和其他数据库宏包比如 \pkg{datatool} 相比,\pkg{dbshow} 更专注于非图表类型的数 +% 据展示。 +% +% \changes{1.4}{2022-01-10}{Add check}{version of \pkg{l3kernel}} +% \pkg{dbshow} 依赖版本日期至少为 |2022-11-07| 的 \pkg{l3kernel}。 +% +% \changes{1.3}{2022-01-09}{Add doc}{descripton for expansion} +% \begin{itemize} +% \item 名字后带有 $\star$ 的命令是可以完全展开的(fully-expandable); +% \item 名字后带有 \ding{73} 的命令可以有限制地展开(restricted-expandable); +% \item 名字后不带有特殊字符的命令是不可展开的(non-expandable); +% \item 名字后带有 $\star$ 的选项不影响相关的代码的是否可展开; +% \item 名字后带有 \ding{73} 的选项是否影响相关代码的可展开性取决于选项的设置; +% \item 名字后不带有特殊字符的选项会使与之相关的代码变得不可展开。 +% \end{itemize} +% +% \subsection{数据类型} +% +% 宏包基于 \pkg{expl3} 的基础类型构建了6种类型: +% \begin{Description}[\texttt{clist}] +% \item[\texttt{date}] +% 日期类型,以 |yyyy/mm/dd| 形式存储,支持大小比较,排序(转 +% 换成字符串)。默认值为 \cs{dbtoday}。 +% \item[\texttt{str}] +% 字符串类型,支持正则匹配,英文排序。默认值为空。 +% \item[\texttt{tl}] +% \meta{token list}类型,支持正则匹配。默认值为空。 +% \item[\texttt{int}] +% 整数类型,支持大小比较,排序。默认值为0。 +% \item[\texttt{fp}] +% 浮点数类型,支持大小比较,排序。默认值为0。 +% \item[\texttt{clist}] +% 逗号分隔的列表类型。默认值为空列表。 +% \end{Description} +% +% \changes{1.3}{2022-01-08}{Remove dependency}{\pkg{datatime2}} +% 除了日期类型,所有类型都是 \pkg{expl3} 的内置类型。\pkg{dbshow} 构建了一个简单 +% 的 |date| 类型,支持转换成整数以及带样式的打印。 +% +% \subsection{与 \pkg{datatool} 的区别} +% +% \changes{1.2}{2022-01-07}{Add doc}{add comparison to \pkg{datatool}} +% +% 从核心功能上看,\pkg{dbshow} 和 \pkg{datatool} 实现了相同的功能。区别在于 +% \pkg{dbshow} 基于 \pkg{expl3} 实现,支持字符串的正则匹配,还支持多级排序。使用 +% 方式上更倾向于样式与内容分离,所有的样式都可以通过选项提前定义好并且可以复用。 +% \pkg{dbshow} 并没有实现从外部文件读取数据以及将数据持久化的功能,我认为这些应 +% 该是更专业的外部程序的工作而不应该在 \LaTeX 中设计这些功能。因此,\pkg{dbshow} +% 只提供了一个运行时的临时数据库,足够轻便且满足大部分正常需求。如果你想删除或修 +% 改数据库中某一条记录,请去对应的位置删除或修改掉对应的 \env{dbitem} 环境,而不 +% 是让宏包提供一个输出某一行记录的命令。某种意义上记录数据库的 \TeX 源文件本身就 +% 是数据的一种持久化。 +% +% \section{接口文档} +% +% \subsection{创建、展示和清空数据库} +% +% \changes{1.4}{2022-01-10}{Update macro}{change \orbar\ to \cs{dbshow_sep} in +% weird argument of \cs{dbshow_process_default_value:w}} +% \begin{function}[added=2022-01-05, updated=2022-01-10]{\dbNewDatabase, \dbNewDatabase*} +% \begin{syntax} +% \cs{dbNewDatabase} \oarg{base database} \marg{database} \{ \\ +% ~~\meta{attr1} = \meta{type spec1}, \\ +% ~~\meta{attr2} = \meta{type spec2}, \\ +% ~~\ldots{} \\ +% \} \\ +% \cs{dbNewDatabase}* \marg{database} \{ \\ +% ~~\meta{attr1} = \meta{type spec1}, \\ +% ~~\meta{attr2} = \meta{type spec2}, \\ +% ~~\ldots{} \\ +% \} \\ +% \end{syntax} +% +% \end{function} +% +% 新建一个数据库,不带星号的版本可以指定一个数据库来继承其属性设置,该版本总是 +% 会舍弃掉之前的定义。 +% +% 带星号的版本不会舍弃之前已有的定义,而是将新的选项添加到后面。 +% +% \meta{attr} 为属性名称,\meta{type spec} 负责声明属性类型和属性默认值: +% +% \noindent\begin{tblr}{ +% colspec = {ll}, +% column{1} = {font = \ttfamily} +% } +% \meta{attr} = \meta{type} & +% 将 \meta{attr} 声明为 \meta{type} 类型 \\ +% \meta{attr} = \meta{type}\orbar\meta{default} & +% 将 \meta{attr} 声明为 \meta{type} 类型,并且将默认值设置为 \meta{default}。 +% \\ +% \end{tblr} +% +% \begin{note} +% 每个数据库都有一个默认的属性 |id| 用来存储数据的索引。 +% \end{note} +% +% 下面是定义一个错题数据库的示例,|question| 和 |answer| 属性用来存储问题和答 +% 案,|date| 属性存储日期,|info| 属性存储额外信息,|labels| 存储题目标签。 +% \begin{verbatim} +% \dbNewDatabase{ques}{ +% question = tl, +% answer = tl, +% date = date, +% info = tl, +% labels = clist +% } +% \end{verbatim} +% +% \begin{function}[added=2022-01-05]{\dbshow} +% \begin{syntax} +% \cs{dbshow} \marg{style} \marg{database} +% \end{syntax} +% +% 使用 \meta{style} 样式来展示 \meta{database}。 +% \end{function} +% +% \changes{1.2}{2022-01-07}{Add macro}{\cs{dbclear}} +% \begin{function}[added=2022-01-07]{\dbclear} +% \begin{syntax} +% \cs{dbclear} \marg{database} +% \end{syntax} +% 清空 \meta{database} 里的所有内容。 +% \end{function} +% +% \subsection{\cs{dbNewStyle} 和样式选项} +% +% \begin{function}[added=2022-01-05]{\dbNewStyle} +% \begin{syntax} +% \cs{dbNewStyle} \oarg{base styles} \marg{style} \marg{database} \marg{opts} +% \end{syntax} +% +% 为 \meta{database} 定义一个新的样式 \meta{style},该样式可以基于已有的样式 +% \meta{base styles},比如 |\dbNewStyle[base1, base2]{new-style}{ques}{}|。 +% \end{function} +% +% \subsubsection{通用选项} +% +% \begin{option}[added=2022-01-05]{filter} +% \begin{syntax} +% filter = <filter> +% \end{syntax} +% +% 为当前样式设置由 \cs{dbCombineFilters} 所定义的过滤器 +% \end{option} +% +% \begin{option}[added=2022-01-06]{raw-filter} +% \begin{syntax} +% raw-filter = <conditional expression> +% \end{syntax} +% +% 使用条件表达式设置匿名过滤器,这里的条件指通过 \cs{dbNewConditional} 定义的 +% 条件。下面代码中两个示例的过滤器具有相同的功能。 +% \end{option} +% +% \changes{1.1}{2022-01-06}{Add option}{\opt{raw-filter}} +% +% \begin{verbatim} +% % method 1 +% \begin{dbFilters}{db} +% \dbNewConditional{cond1}{int-attr}{\rval > 1} +% \dbNewConditional*{cond2}{str-attr}{\d+} +% \end{dbFilters} +% \dbNewStyle{style}{db}{raw-filter={cond1 && cond2}} +% % method 2 +% \begin{dbFilters}{db} +% \dbNewConditional{cond1}{int-attr}{\rval > 1} +% \dbNewConditional*{cond2}{str-attr}{\d+} +% \dbCombineFilters{filter}{cond1 && cond2} +% \end{dbFilters} +% \dbNewStyle{style}{db}{filter=filter} +% \end{verbatim} +% +% \changes{1.2}{2022-01-08}{Fix bug}{string sorting bug} +% \begin{option}[added=2022-01-05]{sort} +% \begin{syntax} +% sort = \{ <attr spec1>, <attr spec2>, \ldots{} \} +% \end{syntax} +% +% 为当前样式设置排序规则。支持根据 |str|,|date|,|int|,|fp| 类型的数据进行排 +% 序,支持多级排序。\meta{attr} 表示增序,\meta{attr}* 表示降序。下面例子中, +% 使用 |sort-style| 展示数据时的顺序为先按 |level| 降序,|level| 相同的再按出 +% 生日期 |birth| 增序,以此类推。 +% \end{option} +% +% \begin{verbatim} +% \dbNewDatabase{sort-example}{ +% name = str, +% birth = date, +% level = int, +% weight = fp, +% } +% \dbNewStyle{sort-style}{sort-example}{ +% sort = { level*, birth, name, weight } +% } +% \end{verbatim} +% +% \begin{option}[added=2022-01-05, rEXP]{item-code} +% \begin{syntax} +% item-code = <code> +% \end{syntax} +% +% 该选项用来设置展示数据库中每条记录的代码。你可以使用 \cs{dbuse} 来展示属性的 +% 值。 +% \end{option} +% +% \changes{1.3}{2022-01-09}{Update option}{\opt{<attr>/sep}} +% \begin{option}[added=2022-01-05, updated=2022-01-08, rEXP]{<attr>/sep} +% \begin{syntax} +% <attr>/sep = <separator> \\ +% <attr>/sep = \{ \\ +% ~~\meta{separator between two}, \\ +% ~~\meta{separator between more than two}, \\ +% ~~\meta{separator between final two} \\ +% \} \\ +% <attr>/sep = \{ \\ +% ~~\meta{separator before year}, \\ +% ~~\meta{separator between year and month}, \\ +% ~~\meta{separator between month and day}, \\ +% ~~\meta{separator after day} \\ +% \} \\ +% \end{syntax} +% +% 该选项只适用于类型为 |clist| 或 |date| 的属性,用来设置列表间元素的间隔。参 +% 数为一个 \meta{separator} 时,所有元素间的分隔符被设置为 \meta{separator}。 +% \meta{separator before year} 和 \meta{separator after day} 被设置为空。 +% \end{option} +% +% 参数为3个元素的逗号分隔的列表时,此选项用来设置列表元素的分隔符,分别用来设 +% 置只有两个元素时的分隔符 \meta{separator between two},超过两个元素时的分隔 +% 符 \meta{separator between more than two},和最后两个元素之间的分隔符 +% \meta{separator between final two}。对于类型为 |clist| 的属性,设置此选项时 +% 如果参数列表数量不是1或者3会触发报错。 +% +% \begin{verbatim} +% % clist-attr is an attribute of database db +% % suppose the val of clist-attr is { 1, 2, 3 } +% \dbNewStyle{clist-sep}{db}{ +% clist-attr/sep = { ,~ }, % print 1, 2, 3 +% clist-attr/sep = { {,~}, {,~}, {and~} } % print 1, 2 and 3 +% } +% \end{verbatim} +% +% 参数为4个元素的逗号分隔的列表时,此选项用来设置日期的分隔符,分别用来设 +% 置 \meta{year} 之前的分隔符 \meta{separator before year} ,\meta{year} 和 +% \meta{month} 之间的分隔符 \meta{separator between year and month} , +% \meta{month} 和 \meta{day} 之间的分隔符,以及 \meta{day} 之后的分隔符。对于 +% 类型为 |date| 的属性,设置此选项时如果参数列表数量不是1或者4会触发报错。 +% +% \begin{verbatim} +% % date-attr is an attribute of database db +% % suppose the val of date-attr is 2022/01/01 +% \dbNewStyle{date-sep}{db}{ +% date-attr/sep = -, % print 2022-01-01 +% date-attr/sep = { |, -, -, | } % print |2022-01-01| +% } +% \end{verbatim} +% +% \changes{1.3}{2022-01-08}{Add option}{\opt{<attr>/zfill}} +% \begin{option}[added=2022-01-08, EXP]{<attr>/zfill} +% \begin{syntax} +% <attr>/zfill = <\TTF> +% \end{syntax} +% +% 该选项只适用于类型为 |date| 的属性。控制输出月份和天时是否补零。 +% \end{option} +% +% \changes{1.4}{2022-01-13}{Add macro}{\cs{dbdatesep}} +% \begin{function}[added=2022-01-13, EXP]{\dbdatesep} +% \begin{syntax} +% \cs{dbdatesep} \marg{separator} +% \end{syntax} +% +% 设置内部解析日期时的间隔符,默认为 |/|,即存储数据的格式为 |yyyy/mm/dd|。 +% \end{function} +% +% \subsubsection{装饰器} +% +% 下面这些选项在不同层次上装饰原有的展示代码,有些其实不必通过选项的形式来装饰, +% 但这样做的好处是可以进一步使样式与内容分离。下面的例子中,\meta{style1} 和 +% \meta{style2} 是相同的样式,都用 * 将 \meta{attr1} 包裹住了,但是如果你还想定 +% 义一个样式用 = 将 \meta{attr1} 包裹住,如果用 \meta{style1} 的方式,那就可能 +% 需要重复大片代码,用 \meta{style2} 的方式则可以很轻松的继承 \meta{style1} 中的 +% 代码。 +% +% \begin{verbatim} +% \dbNewStyle{style1}{db}{ +% item-code = {% +% *\rvuse{attr1}*\rvuse{attr2} +% % more code +% } +% } +% \dbNewStyle{base-style}{db}{ +% item-code = {% +% \rvuse{attr1}\rvuse{attr2} +% % more code +% } +% } +% \dbNewStyle[base-style]{style2}{db}{ +% attr1/before-code = { * }, +% attr1/after-code = { * }, +% } +% \dbNewStyle[base-style]{style3}{db}{ +% attr1/before-code = { = }, +% attr1/after-code = { = }, +% } +% \end{verbatim} +% +% \changes{1.3}{2022-01-08}{Add option}{\opt{<attr>/wrapper}} +% \begin{option}[added=2022-01-08, rEXP]{<attr>/wrapper} +% \begin{syntax} +% <attr>/wrapper = <control sequence> +% \end{syntax} +% +% 该选项只适用于类型为 |date| 的属性。\meta{control sequence} 只接收一个参数即 +% 日期,如果设置了此选项,则最后输出的日期为 +% \meta{control sequence}\marg{date}。 +% \end{option} +% +% \begin{option}[added=2022-01-05, rEXP]{before-code} +% \begin{syntax} +% before-code = <code> +% \end{syntax} +% +% 该选项用来设置在展示整个数据库之\zhbefore 需要执行的代码。 +% \end{option} +% +% \begin{option}[added=2022-01-05, rEXP]{after-code} +% \begin{syntax} +% after-code = <code> +% \end{syntax} +% +% 该选项用来设置在展示整个数据库之\zhafter 需要执行的代码。 +% \end{option} +% +% \changes{1.2}{2022-01-08}{Add options}{\opt{record-before-code}, +% \opt{record-after-code}} +% \begin{option}[added=2022-01-05, rEXP]{record-before-code} +% \begin{syntax} +% record-before-code = <code> +% \end{syntax} +% +% 该选项用来设置在展示当前记录之\zhbefore 需要执行的代码。 +% \end{option} +% +% \begin{option}[added=2022-01-05, rEXP]{record-after-code} +% \begin{syntax} +% record-after-code = <code> +% \end{syntax} +% +% 该选项用来设置在展示当前记录之\zhafter 需要执行的代码。 +% \end{option} +% +% \begin{option}[added=2022-01-05, rEXP]{<attr>/before-code} +% \begin{syntax} +% <attr>/before-code = <code> +% \end{syntax} +% +% 该选项用来设置展示数据库中属性 \meta{attr} 对应数据之\zhbefore 需要执行的代 +% 码。\cs{dbuse} 会在展示属性数据\zhbefore 执行此代码。 +% \end{option} +% +% \begin{option}[added=2022-01-05, rEXP]{<attr>/after-code} +% \begin{syntax} +% <attr>/after-code = <code> +% \end{syntax} +% +% 该选项用来设置展示数据库中属性 \meta{attr} 对应数据之\zhafter 需要执行的代码。 +% \cs{dbuse} 会在展示属性数据\zhafter 执行此代码。 +% \end{option} +% +% \begin{option}[added=2022-01-05, rEXP]{<attr>/item-before-code} +% \begin{syntax} +% <attr>/item-before-code = <code> +% \end{syntax} +% +% 该选项只适用于类型为 |clist| 的属性,用来设置展示列表每个元素\zhbefore 需要 +% 执行的代码。 +% \end{option} +% +% \begin{option}[added=2022-01-05, rEXP]{<attr>/item-after-code} +% \begin{syntax} +% <attr>/item-after-code = <code> +% \end{syntax} +% +% 该选项只适用于类型为 |clist| 的属性,用来设置展示列表每个元素\zhafter 需要执 +% 行的代码。 +% \end{option} +% +% \subsection{使用 \cs{dbNewReviewPoints} 定义复习点} +% +% \begin{function}[added=2022-01-05]{\dbNewReviewPoints} +% \begin{syntax} +% \cs{dbNewReviewPoints} \marg{name} \marg{points} +% \end{syntax} +% +% 定义名为 \meta{name} 的复习点。这是专门为错题本或复习所定制的功能, +% \meta{points}是一系列整数,现在假设每道错题你都将写错时的日期记录在了 |date| +% 属性中,并且你希望每隔2,5,15天复习一次。下面的代码给出了一个实现示例。 +% \end{function} +% +% \begin{verbatim} +% \dbNewReviewPoints{review-point}{2, 5, 15} % 定义复习点 +% \begin{dbFilters} +% \dbNewConditional{cond1}{date}{review-point|\Today} % 定义复习条件 +% \dbCombineConditionals{filter1}{cond1} % 定义过滤器 +% \end{dbFilters} +% \dbNewStyle{review-style}{ques}{filter=filter1} % 定义展示样式 +% \end{verbatim} +% +% \subsection{在 \env{dbFilters} 环境中定义过滤器} +% +% \begin{environment}[added=2022-01-05]{dbFilters} +% \begin{syntax} +% |\begin{dbFilters}|\marg{database} \\ +% ~~\meta{code} +% |\end{dbFilters}| \\ +% \end{syntax} +% +% \env{dbFilters}用来定义过滤器,此环境中定义了 \cs{dbNewConditional} 命令用来 +% 定义条件和 \cs{dbCombineConditionals} 命令用来组合条件定义过滤器。过滤器独立 +% 于每个 \meta{database},这意味着你可以在不同数据库中定义名称相同的过滤条件和 +% 过滤器。 +% \end{environment} +% +% \begin{function}[added=2022-01-05, updated=2022-01-08]{\dbNewConditional, \dbNewConditional*} +% \begin{syntax} +% \cs{dbNewConditional} \marg{name} \marg{attr} \marg{cond spec} \\ +% \cs{dbNewConditional}* \marg{name} \marg{attr} \marg{cond spec} \\[2pt] +% \cs{dbNewConditional} \marg{name} \marg{int/fp attr} \marg{expr} \\ +% \cs{dbNewConditional}* \marg{name} \marg{int/fp attr} \marg{expr} \\ +% \cs{dbNewConditional} \marg{name} \marg{str/tl attr} \marg{regex expr} \\ +% \cs{dbNewConditional}* \marg{name} \marg{str/tl attr} \marg{regex expr} \\ +% \cs{dbNewConditional} \marg{name} \marg{clist attr} \marg{val list} \\ +% \cs{dbNewConditional}* \marg{name} \marg{clist attr} \marg{val list} \\ +% \cs{dbNewConditional} \marg{name} \marg{date attr} \marg{expr} +% \cs{dbNewConditional}* \marg{name} \marg{date attr} \{\meta{review points}\orbar\meta{date}\} \\ +% \end{syntax} +% +% \cs{dbNewConditional} 用来定义名为 \meta{name} 的条件,\meta{attr} 指定条件 +% 所绑定的属性,在 \meta{cond spec} 中可以用 \cs{dbval} 指代属性的值。 +% \end{function} +% +% \changes{1.3}{2022-01-10}{Update doc}{truncated division} +% 对于类型为 |int| 和 |fp| 的属性,\meta{expr} 传递给 \cs{int_compare:nTF} 或 +% \cs{fp_compare:nTF} 处理。 +% \begin{note} +% |/| 为四舍五入除法,截断除法请用 \cs{dbIntDivTruncate}。 +% \end{note} +% +% 对于类型为 |str| 和 |tl| 的属性,\meta{regex} 为正则表达式, +% \cs{dbNewConditional} 表示部分匹配,\cs{dbNewConditional*} 表示整体匹配。 +% +% \begin{verbatim} +% \dbNewConditional {cond1}{str-attr}{abc} % 匹配 abc, abcd, 1abc, =abc= 等 +% \dbNewConditional*{cond2}{str-attr}{abc} % 只匹配 abc +% \end{verbatim} +% +% 对于类型为 |clist| 的属性,使用 \cs{dbNewConditional} 定义的条件只要 +% \meta{val list} 中的任意一个元素在属性值(列表)中则条件成立;使用 +% \cs{dbNewConditional*} 定义的条件只有 \meta{val list} 中每一个值都在属性值 +% (列表)中条件才成立。 +% +% \begin{verbatim} +% \dbNewConditional {cond1}{clist-attr}{a, b, c} % a, b, d 满足条件 +% \dbNewConditional*{cond2}{clist-attr}{a, b, c} % a, b, d 不满足条件 +% \end{verbatim} +% +% \changes{1.3}{2022-01-08}{Update logic}{swap definition of starred and +% unstarred conditionals of date} +% 对于类型为 |date| 的属性,\cs{dbNewConditional} 定义的条件后续处理中会将 +% \meta{expr} 中的所有日期转换成相对\textit{1971年1月1日}的一个整数值,然后将 +% 处理后的表达式传递给 \cs{int_compare:nTF} 做进一步处理; +% \cs{dbNewConditional*} 使用复习点来定义过滤条件,\meta{review points} 是 +% \cs{dbNewReviewPoints} 定义的复习点,\meta{date} 是用来比较的日期。 +% +% \begin{function}[added=2022-01-05]{\dbCombineConditionals} +% \begin{syntax} +% \cs{dbCombineConditionals} \marg{name} \marg{cond combination} \oarg{info} +% \end{syntax} +% +% \cs{dbCombineConditionals} 定义名为 \marg{name} 的过滤器,并将 +% \cs{dbNewConditional} 定义的条件组合起来,比如 +% \verb=\dbCombineConditionals{filter}{(cond1 && cond2) || !cond3}=。 +% \meta{cond combination} 中可以使用的关系操作符为 \verb=&&, ||, !=。 +% 可以将 \opt{filter} 选项设置为 \meta{name} 来应用过滤器。\meta{info} 为过滤 +% 器的相关信息,在展示数据库的时候可以用 \cs{dbFilterInfo} 指代。 +% \end{function} +% +% \subsection{使用 \env{dbitem} 环境存储数据} +% +% \changes{1.4}{2022-01-13}{Update env}{dbitem} +% \begin{environment}[added=2022-01-05, updated=2022-01-13]{dbitem} +% \begin{syntax} +% |\begin{dbitem}| \marg{database} \oarg{attr-val list} +% ~~\meta{code} \\ +% |\end{dbitem}| +% \end{syntax} +% +% \env{dbitem} 环境用来存储数据。有两种存储数据的方法,较短的数据可以在选项列 +% 表中通过键值对设置值,较长的数据可以在 \meta{code} 中使用 \cs{dbsave} 存储。 +% \meta{attr} = \meta{val} 等同于 \cs{dbsave}\marg{attr}\marg{val}, +% \meta{attr}* = \meta{val} 等同于 \cs{dbsave*}\marg{attr}\marg{val},数据在 +% |e| 或者 |x| 类型的参数中不可展开。\cs{dbsave}会覆盖选项中设置的值。没有设 +% 置的值将会被设置为全局默认值,下面给出一个存储示例。 +% \end{environment} +% +% \begin{verbatim} +% \begin{dbitem}[date = 2022-01-01, info = 测试] +% \dbsave{question}{这是一个测试问题} +% \dbsave{answer} {这是一个测试答案} +% \end{dbitem} +% \end{verbatim} +% +% \changes{1.4}{2022-01-13}{Add macro}{\cs{dbitemkv}} +% \begin{function}[added=2022-01-13]{\dbitemkv} +% \begin{syntax} +% \cs{dbitemkv} \marg{database} \oarg{attr-val list} +% \end{syntax} +% +% 只使用 \meta{attr-val list} 来存储数据。 +% \end{function} +% +% \subsection{\cs{dbsave} 和 \cs{dbuse}} +% +% \changes{1.3}{2022-01-08}{Add macro}{\cs{dbsave*}} +% \begin{function}[added=2022-01-05, updated=2022-01-08]{\dbsave, \dbsave*} +% \begin{syntax} +% \cs{dbsave} \marg{attr} \marg{data} \\ +% \cs{dbsave}* \marg{attr} \marg{data} +% \end{syntax} +% +% \cs{dbsave} 用来存储数据,只能在 \env{item} 环境中使用。使用 \cs{dbsave*} 存 +% 储的数据会被 \cs{exp_not:n} 包裹。 +% \end{function} +% +% \changes{1.2}{2022-01-08}{Update macro}{make \cs{dbuse} fully-expandable} +% \begin{function}[added=2022-01-05, updated=2022-01-08, EXP]{\dbuse} +% \begin{syntax} +% \cs{dbuse} \marg{attr} +% \end{syntax} +% +% \cs{dbuse} 用来展示数据,只能在 \opt{item-code} 选项中使用。\cs{dbuse} 是可 +% 展开的。 +% \end{function} +% +% \subsection{条件判别式} +% +% \begin{function}[added=2022-01-05, EXP]{\dbIfEmptyT, \dbIfEmptyF, \dbIfEmptyTF} +% \begin{syntax} +% \cs{dbIfEmptyTF} \marg{true code} \marg{false code} \\ +% \cs{dbIfEmptyT} \marg{true code} \\ +% \cs{dbIfEmptyF} \marg{false code} +% \end{syntax} +% +% 该判别式用来判断当前数据库是否为空。下面的示例展示了如何预防空的列表环境。 +% \end{function} +% +% \begin{verbatim} +% \dbNewStyle{style-cond1}{database-test}{ +% before-code = {\dbIfEmptyF{\begin{enumerate}}}, +% after-code = {\dbIfEmptyF{\end{enumerate}}}, +% item-code = {\item \dbuse{attr-test}} +% } +% \end{verbatim} +% +% \changes{1.2}{2022-01-08}{Remove macros}{\cs{dbItemIfEmpty(TF)}, \cs{dbClistItemIfEmpty(TF)}} +% +% \subsection{表达式函数} +% +% \changes{1.3}{2022-01-10}{Add macros}{expression function aliases} +% \begin{function}[added=2022-01-10, EXP]{ +% \dbIntAbs, \dbIntSign, \dbIntDivRound, \dbIntDivTruncate, \dbIntMax, +% \dbIntMin, \dbIntMod, \dbFpSign, +% } +% \begin{syntax} +% \cs{dbIntAbs} \Arg{intexpr} +% \cs{dbIntSign} \Arg{intexpr} +% \cs{dbIntDivRound} \Arg{intexpr_1} \marg{intexpr_2} +% \cs{dbIntDivTruncate} \Arg{intexpr_1} \marg{intexpr_2} +% \cs{dbIntMax} \Arg{intexpr_1} \marg{intexpr_2} +% \cs{dbIntMin} \Arg{intexpr_1} \marg{intexpr_2} +% \cs{dbIntMod} \Arg{intexpr_1} \marg{intexpr_2} +% \cs{dbFpSign} \Arg{fpexpr} +% \end{syntax} +% \cs{dbIntAbs} 等同于 \cs{int_abs:n} \\ +% \cs{dbIntSign} 等同于 \cs{int_sign:n} \\ +% \cs{dbIntDivRound} 等同于 \cs{int_div_round:nn} \\ +% \cs{dbIntDivTruncate} 等同于 \cs{int_div_truncate:nn} \\ +% \cs{dbIntMax} 等同于 \cs{int_max:nn} \\ +% \cs{dbIntMin} 等同于 \cs{int_min:nn} \\ +% \cs{dbIntMod} 等同于 \cs{int_mod:nn} \\ +% \cs{dbFpSign} 等同于 \cs{fp_sign:n} \\ +% 详细的文档见 \pkg{interface3} \\ +% \end{function} +% +% \subsection{特殊命令} +% +% \pkg{dbshow} 定义了一些特殊的命令,会根据语境展开为不同的内容。 +% +% \changes{1.1}{2022-01-05}{Add macro}{ +% \cs{dbarabic}, \cs{dbalph}, \cs{dbAlph}, \cs{dbroman}, +% \cs{dbRoman} +% } +% \changes{1.1}{2022-01-06}{Fix bug}{\cs{dbIndex} not defined} +% \begin{function}[added=2022-01-05, EXP]{ +% \dbval, \dbDatabase, \dbFilterName, \dbFilterInfo, +% \dbIndex, \dbarabic, \dbalph, \dbAlph, \dbroman, \dbRoman +% } +% \begin{tblr}{ll} +% \cs{dbval} & 当前属性的值 \\ +% \cs{dbDatabase} & 数据库名称 \\ +% \cs{dbFilterName} & 当前样式过滤器的名称 \\ +% \cs{dbFilterInfo} & 当前样式过滤器的相关信息 \\ +% \cs{dbIndex} & 数据索引,等同于 \cs{dbuse}|{id}| \\ +% \cs{dbarabic} & 用数字表示的查询集数据计数 \\ +% \cs{dbalph} & 用小写字母表示的查询集数据计数 \\ +% \cs{dbAlph} & 用大写字母表示的查询集数据计数 \\ +% \cs{dbroman} & 用小写罗马字母表示的查询集数据计数 \\ +% \cs{dbroman} & 用大写罗马字母表示的查询集数据计数 \\ +% \end{tblr} +% \end{function} +% +% \section{错题本示例} +% 见第 \ref{sec:example} 节。 +% +% \changes{1.1}{2022-01-07}{Update doc}{improve example} +% +% \title{ +% Package \pkg{dbshow} \fileversion% +% \protect\footnote{% +% Repository: \url{https://github.com/ZhiyuanLck/dbshow}, +% Telegram Group: \url{https://t.me/latex_dbshow}} +% \rlap{\makebox[4cm][r]{ +% \normalsize $\Longrightarrow$ \color{red} +% \linktarget{zh}{en}{中文版本} +% }} +% } +% \author{Changkai Li \protect\path{<lichangkai225@qq.com>}} +% \date{\filedate} +% \maketitle +% +% \section{Introduction} +% +% The initial motivation to write this package is that I want to write a +% template, which can collect questions you gave the wrong answer and can +% display those questions you would like to review by some conditionals, such as +% questions with certain label, questions you have answered uncorrectly for +% certain times or questions having not been reviewed for certain days. So this +% package provides a database to do such thing. +% +% The package provides four core functions: data storage and display, data +% filtering, data sorting and data display. All data is saved once and then you +% can display these data with custom filters, orders and styles. +% +% \changes{1.4}{2022-01-10}{Add check}{version of \pkg{l3kernel}} +% \pkg{dbshow} depends on \pkg{l3kernel} with version date after |2022-11-07|. +% +% \changes{1.3}{2022-01-09}{Add doc}{descripton for expansion} +% \begin{itemize} +% \item Macros with a $\star$ are fully-expandable; +% \item Macros with a \ding{73} are restricted-expandable; +% \item Macros without appending a special symbol are nonexpandable; +% \item Options with a $\star$ \textit{do not} affect the expandability of +% related macros; +% \item Options with a \ding{73} affect the expandability of related macros +% according to its value; +% \item Options without appending a special symbol make the related macros +% nonexpandable. +% \end{itemize} +% +% \subsection{Data Types} +% +% The package constructs 6 types based on the internal typed of \pkg{expl3}: +% \begin{Description}[\texttt{clist}] +% \item[\texttt{date}] +% date saved in |yyyy/mm/dd| format, supports comparison, sorting +% (converting to string), default \cs{dbtoday}. +% \item[\texttt{str}] +% string,supports regex match and sorting, default empty. +% \item[\texttt{tl}] +% token list, supports regex match, default empty. +% \item[\texttt{int}] +% integer, supports comparison and sorting, default 0. +% \item[\texttt{fp}] +% floating point, supports comparison and sorting, default 0. +% \item[\texttt{clist}] +% comma list, default empty. +% \end{Description} +% +% \changes{1.3}{2022-01-08}{Remove dependency}{\pkg{datatime2}} +% All types are internal types of \pkg{expl3} except |date| type, which provides +% by \pkg{dbshow} itself and supports converting to integer and printing with +% style. +% +% \subsection{Comparison to \pkg{datatool}} +% +% \changes{1.2}{2022-01-07}{Add doc}{add comparison to \pkg{datatool}} +% +% \pkg{dbshow} and \pkg{datatool} implement the same core functions. But +% \pkg{dbshow} is based on \pkg{expl3} and it supports string regex and +% multi-level sorting. \pkg{dbshow} tries to divide style from the contents +% (data in database): all styles are predefined and can be reused conveniently +% so that there can be only codes to save data and one-line code to show the +% database inside the \env{document} environment. You can hide the details in +% the preamble and focus on the data you want to display. \pkg{dbshow} provides +% a simple temporary runtime database, which means it can not input and output +% data from/to extern files (they should be responsible by some professional +% programming languages). When you need to delete or revise a record, just go to +% where it is recorded in the source code rather than use a macro to manipulate +% data after they are saved. In a sense, \TeX~file is also a kind of data +% persistence. +% +% \section{Interfaces} +% +% \subsection{Create, Display and Clear Database} +% +% \changes{1.4}{2022-01-10}{Update macro}{change \orbar\ to \cs{dbshow_sep} in +% weird argument of \cs{dbshow_process_default_value:w}} +% \begin{function}[added=2022-01-05, updated=2022-01-10]{\dbNewDatabase, \dbNewDatabase*} +% \begin{syntax} +% \cs{dbNewDatabase} \oarg{base database} \marg{database} \{ \\ +% ~~\meta{attr1} = \meta{type spec1}, \\ +% ~~\meta{attr2} = \meta{type spec2}, \\ +% ~~\ldots{} \\ +% \} \\ +% \cs{dbNewDatabase}* \marg{database} \{ \\ +% ~~\meta{attr1} = \meta{type spec1}, \\ +% ~~\meta{attr2} = \meta{type spec2}, \\ +% ~~\ldots{} \\ +% \} \\ +% \end{syntax} +% +% \end{function} +% +% Create a new database named \meta{database}, unstarred form provides the optional +% \meta{base database} from which current database inherit the attributes settings. +% The unstarred form always replace the old definition, while starred form +% appends the new options. +% +% \begin{syntax} +% \meta{attr} = \meta{type} \\ +% \meta{attr} = \meta{type}\orbar\meta{default} +% \end{syntax} +% +% The first form defines the \meta{attr} as \meta{type}, and the second also +% sets the default value. +% +% \begin{note} +% Every database has a default attribute |id| to store the index of the item. +% \end{note} +% +% The example below define a database named |ques|. +% \begin{verbatim} +% \dbNewDatabase{ques}{ +% question = tl, % store question +% answer = tl, % store corresponding answer +% date = date, % store the date when you were wrong +% info = tl, % store extra info +% labels = clist % store question labels +% } +% \end{verbatim} +% +% \begin{function}[added=2022-01-05]{\dbshow} +% \begin{syntax} +% \cs{dbshow} \marg{style} \marg{database} +% \end{syntax} +% +% Show the \meta{database} with \meta{style}. +% \end{function} +% +% \changes{1.2}{2022-01-07}{Add macro}{\cs{dbclear}} +% \begin{function}[added=2022-01-07]{\dbclear} +% \begin{syntax} +% \cs{dbclear} \marg{database} +% \end{syntax} +% +% Clear the content of \meta{database}. +% \end{function} +% +% \subsection{\cs{dbNewStyle} and Style Options} +% +% \begin{function}[added=2022-01-05]{\dbNewStyle} +% \begin{syntax} +% \cs{dbNewStyle} \oarg{base styles} \marg{style} \marg{database} \marg{opts} +% \end{syntax} +% +% Define a new \meta{style} that binds to \meta{database}. The style can +% inherit from a list of \meta{base styles} such as +% |\dbNewStyle[base1, base2]{new-style}{ques}{}|. +% \end{function} +% +% \subsubsection{General Options} +% +% \begin{option}[added=2022-01-05]{filter} +% \begin{syntax} +% filter = <filter> +% \end{syntax} +% +% Set the \meta{filter} defined by \cs{dbCombineFilters}. +% \end{option} +% +% \changes{1.1}{2022-01-06}{Add option}{\opt{raw-filter}} +% \begin{option}[added=2022-01-06]{raw-filter} +% \begin{syntax} +% raw-filter = <conditional expression> +% \end{syntax} +% +% Set anonymous with conditionals defined by \cs{dbNewConditional}. Two +% filters shows in the code below have the same meaning. +% \end{option} +% +% \begin{verbatim} +% % method 1 +% \begin{dbFilters}{db} +% \dbNewConditional{cond1}{int-attr}{\rval > 1} +% \dbNewConditional*{cond2}{str-attr}{\d+} +% \end{dbFilters} +% \dbNewStyle{style}{db}{raw-filter={cond1 && cond2}} +% % method 2 +% \begin{dbFilters}{db} +% \dbNewConditional{cond1}{int-attr}{\rval > 1} +% \dbNewConditional*{cond2}{str-attr}{\d+} +% \dbCombineFilters{filter}{cond1 && cond2} +% \end{dbFilters} +% \dbNewStyle{style}{db}{filter=filter} +% \end{verbatim} +% +% \changes{1.2}{2022-01-08}{Fix bug}{string sorting bug} +% \begin{option}[added=2022-01-05]{sort} +% \begin{syntax} +% sort = \{ <attr spec1>, <attr spec2>, \ldots{} \} +% \end{syntax} +% +% Set sorting rules. Attributes of type |str, date, int, fp| is supported to +% sort. Multi-level sort is allowed. \meta{attr} represents for ascending +% order, and \meta{attr}* represents for descending order. The example below +% use four fields to determine the order of the records. It sorts on |level| +% in descending order first and if two |levels| are same then sorts on |birth| +% in ascending order and so on. +% \end{option} +% +% \begin{verbatim} +% \dbNewDatabase{sort-example}{ +% name = str, +% birth = date, +% level = int, +% weight = fp, +% } +% \dbNewStyle{sort-style}{sort-example}{ +% sort = { level*, birth, name, weight } +% } +% \end{verbatim} +% +% \begin{option}[added=2022-01-05, rEXP]{item-code} +% \begin{syntax} +% item-code = <code> +% \end{syntax} +% +% Set the code that show a single record. You can use \cs{dbuse} to display +% certian attribute. +% \end{option} +% +% \changes{1.3}{2022-01-09}{Update option}{\opt{<attr>/sep}} +% \begin{option}[added=2022-01-05, updated=2022-01-08, rEXP]{<attr>/sep} +% \begin{syntax} +% <attr>/sep = <separator> \\ +% <attr>/sep = \{ \\ +% ~~\meta{separator between two}, \\ +% ~~\meta{separator between more than two}, \\ +% ~~\meta{separator between final two} \\ +% \} \\ +% <attr>/sep = \{ \\ +% ~~\meta{separator before year}, \\ +% ~~\meta{separator between year and month}, \\ +% ~~\meta{separator between month and day}, \\ +% ~~\meta{separator after day} \\ +% \} \\ +% \end{syntax} +% +% Only for attributes of type |clist| or |date|. Set the separator between +% items. If the argument is an one-item comma list, all separators are set to +% \meta{separator} but \meta{separator before year} and \meta{separator after +% day} is set empty. +% \end{option} +% +% If the argument is a comma list of 3 items, it is used to set the separator +% between items of the comma list. Following documentation is quoted from +% \pkg{interface3}: +% \begin{quote} +% If the comma list has more than two items, the \meta{separator between +% more than two} is placed between each pair of items except the last, for +% which the \meta{separator between final two} is used. If the comma list +% has exactly two items, then they are placed in the input stream separated +% by the \meta{separator between two}. If the comma list has a single item, +% it is placed in the input stream, and a comma list with no items produces +% no output. +% \end{quote} +% For attributes of type |clist|, incorrect number (numbers exclude 1 and 3) +% of items of the argument will raise an error. +% +% \begin{verbatim} +% % clist-attr is an attribute of database db +% % suppose the val of clist-attr is { 1, 2, 3 } +% \dbNewStyle{clist-sep}{db}{ +% clist-attr/sep = { ,~ }, % print 1, 2, 3 +% clist-attr/sep = { {,~}, {,~}, {and~} } % print 1, 2 and 3 +% } +% \end{verbatim} +% +% If the argument is a comma list of 4 items, it is used to set the separators +% of the date. For attributes of type |date|, incorrect number (numbers +% exclude 1 and 4) will raise an error. +% +% \begin{verbatim} +% % date-attr is an attribute of database db +% % suppose the val of date-attr is 2022/01/01 +% \dbNewStyle{date-sep}{db}{ +% date-attr/sep = -, % print 2022-01-01 +% date-attr/sep = { |, -, -, | } % print |2022-01-01| +% } +% \end{verbatim} +% +% \changes{1.3}{2022-01-08}{Add option}{\opt{<attr>/zfill}} +% \begin{option}[added=2022-01-08, EXP]{<attr>/zfill} +% \begin{syntax} +% <attr>/zfill = <\TTF> +% \end{syntax} +% +% Only for attributes of type |date|. Control whether to fill zero on the left +% of the month or day. +% \end{option} +% +% \changes{1.4}{2022-01-13}{Add macro}{\cs{dbdatesep}} +% \begin{function}[added=2022-01-13, EXP]{\dbdatesep} +% \begin{syntax} +% \cs{dbdatesep} \marg{separator} +% \end{syntax} +% +% Set the separator for internal date parsing. The default value is |/|, +% i.e. the date must be store in the format of |yyyy/mm/dd|. +% \end{function} +% +% \subsubsection{Decorators} +% +% The options below serves as decorators. In some cases, decorator can also be +% encoded directly into |item-code| or some other places, which is convenient +% sometimes. The benefit of defining decorators with options is that styles step +% further to be divided with contents. In the examples below, \meta{style1} and +% \meta{style2} is the same style, which wrap \meta{attr1} with *. When you want +% another style which wrap \meta{attr1} with =, if you choose the way of +% \meta{style1}, \meta{item code} are repeated, otherwise if you choose the way +% of \meta{style2}, \meta{item code} is inherited and you only need define the +% decorators. +% +% \begin{verbatim} +% \dbNewStyle{style1}{db}{ +% item-code = {% +% *\rvuse{attr1}*\rvuse{attr2} +% % more code +% } +% } +% \dbNewStyle{base-style}{db}{ +% item-code = {% +% \rvuse{attr1}\rvuse{attr2} +% % more code +% } +% } +% \dbNewStyle[base-style]{style2}{db}{ +% attr1/before-code = { * }, +% attr1/after-code = { * }, +% } +% \dbNewStyle[base-style]{style3}{db}{ +% attr1/before-code = { = }, +% attr1/after-code = { = }, +% } +% \end{verbatim} +% +% \changes{1.3}{2022-01-08}{Add option}{\opt{<attr>/wrapper}} +% \begin{option}[added=2022-01-08, rEXP]{<attr>/wrapper} +% \begin{syntax} +% <attr>/wrapper = <control sequence> +% \end{syntax} +% +% Only for attributes of type |date|. Output of \cs{dbuse}\marg{date attr} +% will be \meta{control sequence}\marg{date}. +% \end{option} +% +% \begin{option}[added=2022-01-05, rEXP]{before-code} +% \begin{syntax} +% before-code = <code> +% \end{syntax} +% +% Set the \meta{code} that is executed \enbefore displaying the database. +% \end{option} +% +% \begin{option}[added=2022-01-05, rEXP]{after-code} +% \begin{syntax} +% after-code = <code> +% \end{syntax} +% +% Set the \meta{code} that is executed \enafter displaying the database. +% \end{option} +% +% \changes{1.2}{2022-01-08}{Add options}{\opt{record-before-code}, +% \opt{record-after-code}} +% \begin{option}[added=2022-01-05, rEXP]{record-before-code} +% \begin{syntax} +% record-before-code = <code> +% \end{syntax} +% +% Set the \meta{code} that is executed \enbefore displaying a record. +% \end{option} +% +% \begin{option}[added=2022-01-05, rEXP]{record-after-code} +% \begin{syntax} +% record-after-code = <code> +% \end{syntax} +% +% Set the \meta{code} that is executed \enafter displaying the record. +% \end{option} +% +% \begin{option}[added=2022-01-05, rEXP]{<attr>/before-code} +% \begin{syntax} +% <attr>/before-code = <code> +% \end{syntax} +% +% Set the \meta{code} that is executed by \cs{dbuse} \enbefore displaying +% certain attribute. +% \end{option} +% +% \begin{option}[added=2022-01-05, rEXP]{<attr>/after-code} +% \begin{syntax} +% <attr>/after-code = <code> +% \end{syntax} +% +% Set the \meta{code} that is executed by \cs{dbuse} \enafter displaying +% certain attribute. +% \end{option} +% +% \begin{option}[added=2022-01-05, rEXP]{<attr>/item-before-code} +% \begin{syntax} +% <attr>/item-before-code = <code> +% \end{syntax} +% +% Only for attributes of type |clist|. Set the \meta{code} that is excuted +% \enbefore displaying the item of the comma list. +% \end{option} +% +% \begin{option}[added=2022-01-05, rEXP]{<attr>/item-after-code} +% \begin{syntax} +% <attr>/item-after-code = <code> +% \end{syntax} +% +% Only for attributes of type |clist|. Set the \meta{code} that is excuted +% \enafter displaying the item of the comma list. +% \end{option} +% +% \subsection{Use \cs{dbNewReviewPoints} to Define Review Points} +% +% \begin{function}[added=2022-01-05]{\dbNewReviewPoints} +% \begin{syntax} +% \cs{dbNewReviewPoints} \marg{name} \marg{points} +% \end{syntax} +% +% Define the new \meta{points} that is specially designed for reviewing +% something. \meta{points} is a list of integers. Suppose you record the date +% when you did not answer correctly and you plan to review every 2, 5 and 15 +% days. The following code give what you want. +% \end{function} +% +% \begin{verbatim} +% \dbNewReviewPoints{review-point}{2, 5, 15} % define points +% \begin{dbFilters} +% \dbNewConditional{cond1}{date}{review-point|\Today} % define conditional +% \dbCombineConditionals{filter1}{cond1} % define filter +% \end{dbFilters} +% \dbNewStyle{review-style}{ques}{filter=filter1} % define style +% \end{verbatim} +% +% \subsection{Define Filters inside \env{dbFilters} Environment} +% +% \begin{environment}[added=2022-01-05]{dbFilters} +% \begin{syntax} +% |\begin{dbFilters}|\marg{database} \\ +% ~~\meta{code} +% |\end{dbFilters}| \\ +% \end{syntax} +% +% Filters are defined inside \env{dbFilters} environment, inside which, +% \cs{dbNewConditional} is defined to declare conditionals and +% \cs{dbCombineConditionals} is defined to combine conditionals. Filters are +% independent in different databases, which means the same name of filters is +% allowed in different databases. +% \end{environment} +% +% \begin{function}[added=2022-01-05, updated=2022-01-08]{\dbNewConditional, \dbNewConditional*} +% \begin{syntax} +% \cs{dbNewConditional} \marg{name} \marg{attr} \marg{cond spec} \\ +% \cs{dbNewConditional}* \marg{name} \marg{attr} \marg{cond spec} \\[2pt] +% \cs{dbNewConditional} \marg{name} \marg{int/fp attr} \marg{expr} \\ +% \cs{dbNewConditional}* \marg{name} \marg{int/fp attr} \marg{expr} \\ +% \cs{dbNewConditional} \marg{name} \marg{str/tl attr} \marg{regex expr} \\ +% \cs{dbNewConditional}* \marg{name} \marg{str/tl attr} \marg{regex expr} \\ +% \cs{dbNewConditional} \marg{name} \marg{clist attr} \marg{val list} \\ +% \cs{dbNewConditional}* \marg{name} \marg{clist attr} \marg{val list} \\ +% \cs{dbNewConditional} \marg{name} \marg{date attr} \marg{expr} +% \cs{dbNewConditional}* \marg{name} \marg{date attr} \{\meta{review points}\orbar\meta{date}\} \\ +% \end{syntax} +% +% Define the conditional named \meta{name} that binds to \meta{attr}. \cs{dbval} +% is replaced with the real value of the attribute inside the \meta{cond spec}. +% \end{function} +% +% \changes{1.3}{2022-01-10}{Update doc}{truncated division} +% For attributes of type |int| and |fp|, \meta{expr} is passed to +% \cs{int_compare:nTF} or \cs{fp_compare:nTF}. +% \begin{note} +% Division using |/| rounds to the closest integer. Use \cs{dbIntDivTruncate} to rounds +% the result toward 0. +% \end{note} +% +% For attribute of type |str| and |tl|, unstarred form matches any part while +% starred form matches the whole part with the \meta{regex expr}. +% +% \begin{verbatim} +% \dbNewConditional {cond1}{str-attr}{abc} % match abc, abcd, 1abc, =abc=, etc +% \dbNewConditional*{cond2}{str-attr}{abc} % only match abc +% \end{verbatim} +% +% For attributes of type |clist|, the conditional defined by unstarred form is +% true if any item of \meta{val list} is in the comma list. While the +% conditional defined by starred form is true only if every item of \meta{val +% list} is in the comma list. As is showed below, for |cond1|, |a| is in +% |{a, b, d}| so |cond1| is true. While |c| is not in |{a, b, d}| so |cond2| +% is false. +% +% \begin{verbatim} +% \dbNewConditional {cond1}{clist-attr}{a, b, c} % {a, b, d} -> true +% \dbNewConditional*{cond2}{clist-attr}{a, b, c} % {a, b, d} -> false +% \end{verbatim} +% +% \changes{1.3}{2022-01-08}{Update logic}{swap definition of starred and +% unstarred conditionals of date} +% For attributes of type |date|, unstarred form replace each date with a +% integer representing for the days between \meta{date} and +% \textit{1971/01/01}, and the result is passed to \cs{int_compare:nTF}. +% Starred form defines the conditional with review points defined by +% \cs{dbNewRdbNewReviewPoints} and \meta{date} is the date to be compared. +% +% \begin{function}[added=2022-01-05]{\dbCombineConditionals} +% \begin{syntax} +% \cs{dbCombineConditionals} \marg{name} \marg{cond combination} \oarg{info} +% \end{syntax} +% +% Define the filter \meta{name}, which combine the conditionals and store the +% extra \meta{info} into \cs{dbFilterInfo}. So you can write something as\\ +% \verb=\dbCombineConditionals{filter}{(cond1 && cond2) || !cond3}=.\\ +% Supported operators are \verb=&&, ||, !=. You can set the option \opt{filter} +% to \meta{name} to apply the filter when you display the database. +% \end{function} +% +% \subsection{Store Data with \env{dbitem} Environment} +% +% \changes{1.4}{2022-01-13}{Update env}{dbitem} +% \begin{environment}[added=2022-01-05, updated=2022-01-13]{dbitem} +% \begin{syntax} +% |\begin{dbitem}| \marg{database} \oarg{attr-val list} +% ~~\meta{code} \\ +% |\end{dbitem}| +% \end{syntax} +% +% The data are stored with \env{dbitem} environment in two ways. Short data +% can be stored in \meta{attr-val list} and long data can be stored by +% \cs{dbsave}, which will suppress the value set by the option list. +% \meta{attr} = \meta{val} is equal to \cs{dbsave}\marg{attr}\marg{val}, and +% \meta{attr} = \meta{val} is equal to \cs{dbsave*}\marg{attr}\marg{val}, +% in which case, data will not be expanded in an |e| or |x|-type argument. +% An example code is showned below. +% \end{environment} +% +% \begin{verbatim} +% \begin{dbitem}[date=2022-01-01, info=test] +% \dbsave{question}{This is a test question.} +% \dbsave{answer} {This is a test answer.} +% \end{dbitem} +% \end{verbatim} +% +% \changes{1.4}{2022-01-13}{Add macro}{\cs{dbitemkv}} +% \begin{function}[added=2022-01-13]{\dbitemkv} +% \begin{syntax} +% \cs{dbitemkv} \marg{database} \oarg{attr-val list} +% \end{syntax} +% +% Store data with \meta{attr-val list}. +% \end{function} +% +% \subsection{\cs{dbsave} and \cs{dbuse}} +% +% \changes{1.3}{2022-01-08}{Add macro}{\cs{dbsave*}} +% \begin{function}[added=2022-01-05, updated=2022-01-08]{\dbsave, \dbsave*} +% \begin{syntax} +% \cs{dbsave} \marg{attr} \marg{data} \\ +% \cs{dbsave}* \marg{attr} \marg{data} +% \end{syntax} +% +% \cs{dbsave} save the \meta{data} to \meta{attr} of current record. +% \cs{dbsave} can be used only inside the \env{dbitem} environment. +% \meta{data} stored by \cs{dbsave*} is wrapped with \cs{exp_not:n} while +% \meta{data} stored by \cs{dbsave} keeps the same. +% \end{function} +% +% \changes{1.2}{2022-01-08}{Update macro}{make \cs{dbuse} fully-expandable} +% \begin{function}[added=2022-01-05, updated=2022-01-08, EXP]{\dbuse} +% \begin{syntax} +% \cs{dbuse} \marg{attr} +% \end{syntax} +% +% Display the value of \meta{attr} of current record. \cs{dbuse} is +% \textbf{expandable} and can be only used inside the option \opt{item-code}. +% \end{function} +% +% \subsection{Conditionals} +% +% \begin{function}[added=2022-01-05, EXP]{\dbIfEmptyT, \dbIfEmptyF, \dbIfEmptyTF} +% \begin{syntax} +% \cs{dbIfEmptyTF} \marg{true code} \marg{false code} \\ +% \cs{dbIfEmptyT} \marg{true code} \\ +% \cs{dbIfEmptyF} \marg{false code} +% \end{syntax} +% +% Test if the database is empty. The example below shows how to avoid an empty +% list environment. +% \end{function} +% +% \begin{verbatim} +% \dbNewStyle{style-cond1}{database-test}{ +% before-code = {\dbIfEmptyF{\begin{enumerate}}}, +% after-code = {\dbIfEmptyF{\end{enumerate}}}, +% item-code = {\item \dbuse{attr-test}} +% } +% \end{verbatim} +% +% \changes{1.2}{2022-01-08}{Remove macros}{\cs{dbItemIfEmpty(TF)}, \cs{dbClistItemIfEmpty(TF)}} +% +% \subsection{Expression Functions} +% +% \changes{1.3}{2022-01-10}{Add macros}{expression function aliases} +% \begin{function}[added=2022-01-10, EXP]{ +% \dbIntAbs, \dbIntSign, \dbIntDivRound, \dbIntDivTruncate, \dbIntMax, +% \dbIntMin, \dbIntMod, \dbFpSign, +% } +% \begin{syntax} +% \cs{dbIntAbs} \Arg{intexpr} +% \cs{dbIntSign} \Arg{intexpr} +% \cs{dbIntDivRound} \Arg{intexpr_1} \marg{intexpr_2} +% \cs{dbIntDivTruncate} \Arg{intexpr_1} \marg{intexpr_2} +% \cs{dbIntMax} \Arg{intexpr_1} \marg{intexpr_2} +% \cs{dbIntMin} \Arg{intexpr_1} \marg{intexpr_2} +% \cs{dbIntMod} \Arg{intexpr_1} \marg{intexpr_2} +% \cs{dbFpSign} \Arg{fpexpr} +% \end{syntax} +% \cs{dbIntAbs} is identical to \cs{int_abs:n} \\ +% \cs{dbIntSign} is identical to \cs{int_sign:n} \\ +% \cs{dbIntDivRound} is identical to \cs{int_div_round:nn} \\ +% \cs{dbIntDivTruncate} is identical to \cs{int_div_truncate:nn} \\ +% \cs{dbIntMax} is identical to \cs{int_max:nn} \\ +% \cs{dbIntMin} is identical to \cs{int_min:nn} \\ +% \cs{dbIntMod} is identical to \cs{int_mod:nn} \\ +% \cs{dbFpSign} is identical to \cs{fp_sign:n} \\ +% Detailed documentation see \pkg{interface3} \\ +% \end{function} +% +% \subsection{Special Macros} +% +% Some special macros are defined to expand to different contents according to context. +% +% \changes{1.1}{2022-01-05}{Add macro}{ +% \cs{dbarabic}, \cs{dbalph}, \cs{dbAlph}, \cs{dbroman}, +% \cs{dbRoman} +% } +% \changes{1.1}{2022-01-06}{Fix bug}{\cs{dbIndex} not defined} +% \begin{function}[added=2022-01-05, EXP]{ +% \dbval, \dbDatabase, \dbFilterName, \dbFilterInfo, +% \dbIndex, \dbarabic, \dbalph, \dbAlph, \dbroman, \dbRoman +% } +% \begin{tblr}{ll} +% \cs{dbval} & Attribute value, only according in \cs{dbNewConditional}. \\ +% \cs{dbDatabase} & Database name. \\ +% \cs{dbFilterName} & Filter name. \\ +% \cs{dbFilterInfo} & Filter information. \\ +% \cs{dbIndex} & Record index, identical to \cs{dbuse}|{id}| \\ +% \cs{dbarabic} & Show the counter of query set as digits. \\ +% \cs{dbalph} & Show the counter of query set as lowercase letters. \\ +% \cs{dbAlph} & Show the counter of query set as uppercase letters. \\ +% \cs{dbroman} & Show the counter of query set as lowercase roman numerals. \\ +% \cs{dbroman} & Show the counter of query set as uppercase roman numerals. \\ +% \end{tblr} +% \end{function} +% +% \section{Example of Flaw Sweeper Template} +% \label{sec:example} +% +% \changes{1.1}{2022-01-07}{Update doc}{improve example} +% +% \begin{verbatim} +% \documentclass{article} +% \usepackage{amsmath, physics} +% \usepackage{geometry} +% \usepackage{dbshow} +% \usepackage{tikz} +% \usepackage{tcolorbox} +% \tcbuselibrary{skins} +% \usetikzlibrary{shadings} +% \usepackage[hidelinks]{hyperref} +% +% \geometry{ +% margin=2cm +% } +% +% % #1 link node #2 target node #3 text to show +% \NewDocumentCommand \linktarget { m m m } {% +% \hyperlink{#1}{#3}% +% \raisebox{1em}{\hypertarget{#2}{}}% +% } +% +% % question box +% \tcbset{ +% base/.style={ +% empty, +% frame engine=path, +% colframe=yellow!10, +% coltitle=red!70, +% fonttitle=\bfseries\sffamily, +% sharp corners, +% left=4pt, +% right=4pt, +% drop fuzzy shadow, +% drop fuzzy shadow, +% borderline west={3pt}{-3pt}{red!80}, +% } +% } +% +% \newtcolorbox{mybox}[1]{% +% base, title = {#1} +% } +% +% \dbNewReviewPoints{review}{1, 3, 7, 15, 30, 60} +% +% \dbNewDatabase{ques-book}{ +% ques = tl, +% answer = tl, +% count = int|1, +% labels = clist, +% date = date, +% } +% +% \begin{dbFilters}{ques-book} +% \dbNewConditional{hard}{labels}{hard} +% \dbNewConditional{bad}{count}{\dbval > 1} +% \dbNewConditional*{review}{date}{review|2022/01/07} +% \dbNewConditional{after}{date}{\dbval > 2022/01/02} +% \end{dbFilters} +% +% % show all questions with hyperlink to answers +% \dbNewStyle{ques}{ques-book}{ +% before-code = {\section{Questions}}, +% item-code = { +% \begin{mybox}{% +% \linktarget{answer_\dbIndex}{ques_\dbIndex}{% +% Question \dbarabic% +% \hspace{2em}\dbuse{date}% +% \hspace{2em}\dbuse{labels}% +% \hfill\dbuse{count}% +% }% +% } +% \dbuse{ques}% +% \end{mybox} +% }, +% labels/sep = /, +% } +% +% % show all questions and answers with hyperlink to questions +% \dbNewStyle{answer}{ques-book}{ +% before-code = {\section{Questions and Answers}}, +% item-code = { +% \begin{mybox}{% +% \linktarget{ques_\dbIndex}{answer_\dbIndex}{% +% Question \dbarabic% +% \hspace{2em}\dbuse{date}% +% \hspace{2em}\dbuse{labels}% +% \hfill\dbuse{count}% +% }% +% } +% \dbuse{ques}\tcbsubtitle{Answer}\dbuse{answer}% +% \end{mybox} +% }, +% labels/sep = /, +% } +% +% % show all hard questions with hyperlink to answers +% \dbNewStyle{hard}{ques-book}{ +% before-code = {\section{Hard Questions}}, +% item-code = { +% \begin{mybox}{% +% \hyperlink{answer_\dbIndex}{% +% Question \dbarabic% +% \hspace{2em}\dbuse{date}% +% \hspace{2em}\dbuse{labels}% +% \hfill\dbuse{count}% +% }% +% } +% \dbuse{ques}% +% \end{mybox} +% }, +% raw-filter = hard, +% labels/sep = /, +% } +% +% % show all hard questions that have been answered incorrectly for more than +% % one time with hyperlink to answers +% \dbNewStyle[hard]{bad}{ques-book}{ +% before-code = {\section{Bad Questions}}, +% raw-filter = {bad && hard}, +% } +% % show all questions that plan to be reviewed on 2022/01/07 with hyperlink to +% % answers +% \dbNewStyle[hard]{review}{ques-book}{ +% before-code = {\section{Questions to be Reviewed}}, +% raw-filter = {review}, +% } +% % show all questions that is record after 2022/01/02 with hyperlink to answers +% \dbNewStyle[hard]{after}{ques-book}{ +% before-code = {\section{Questions after 2022/01/02}}, +% raw-filter = {after}, +% } +% +% \AtEndDocument{ +% \dbshow{review}{ques-book} +% \dbshow{hard}{ques-book} +% \dbshow{bad}{ques-book} +% \dbshow{after}{ques-book} +% \dbshow{ques}{ques-book} +% \dbshow{answer}{ques-book} +% } +% +% \begin{document} +% +% \begin{dbitem}{ques-book}[ +% date=2022/01/01, +% labels={math, equation, easy}, +% count=2 +% ] +% \dbsave{ques}{% +% Solve the linear equation: $x + 16 = 31$. +% } +% \dbsave{answer}{% +% $x = 31 - 16 = 15$ +% } +% \end{dbitem} +% +% \begin{dbitem}{ques-book}[ +% date=2022/01/01, +% labels={math, equation, hard}, +% count=3 +% ] +% \dbsave{ques}{% +% Solve the linear equation: $2y = 16$. +% } +% \dbsave{answer}{% +% $y = 16 / 2 = 8$ +% } +% \end{dbitem} +% +% \begin{dbitem}{ques-book}[ +% date=2022/01/04, +% labels={math, integral, hard}, +% count=1 +% ] +% \dbsave{ques}{% +% Find the indefinite integral: $\int 2x \dd x$. +% } +% \dbsave{answer}{% +% $\int 2x \dd x = x^2$ +% } +% \end{dbitem} +% +% \end{document} +% \end{verbatim} +% +% \end{documentation} +% +% \StopEventually{} +% +% \newgeometry{ +% left=5.5cm, +% right=2cm, +% top=2cm, +% bottom=2cm +% } +% +% \begin{implementation} +% +% \section{Implementation} +% +% \changes{1.4}{2022-01-13}{Update code}{merge code and doc into +% \pkg{dbshow.dtx}} +% +% \begin{macrocode} +%<*package> +%<@@=dbshow> +% \end{macrocode} +% +% Check version of \pkg{l3kernel}. +% \begin{macrocode} +% prop_concat, prop_gset_from_keyval +\__kernel_dependency_version_check:nn { 2021-11-07 } { l3prop } +% str_compare +\__kernel_dependency_version_check:nn { 2021-05-17 } { l3str } +% clist_map_tokens, clist_use +\__kernel_dependency_version_check:nn { 2021-05-10 } { l3clist } +% \end{macrocode} +% +% \subsection{Variants and Variables} +% +% \begin{macrocode} +\cs_generate_variant:Nn \msg_warning:nnnn { nnnx } +\cs_generate_variant:Nn \keys_set:nn { nv } +\cs_generate_variant:Nn \clist_use:nn { xx } +\cs_generate_variant:Nn \clist_use:nnnn { xxxx } +\cs_generate_variant:Nn \clist_map_inline:nn { Vn } +\cs_generate_variant:Nn \prop_get:NnN { cVN } +\cs_generate_variant:Nn \regex_extract_all:nnN { nVN } +\cs_generate_variant:Nn \regex_split:nnN { nVN } +\prg_generate_conditional_variant:Nnn \str_compare:nNn { VNV } { TF } +\prg_generate_conditional_variant:Nnn \int_compare:nNn { VNV } { TF } +\prg_generate_conditional_variant:Nnn \fp_compare:nNn { VNV } { TF } +\prg_generate_conditional_variant:Nnn \regex_match:nn { VV } { TF } +\prg_generate_conditional_variant:Nnn \clist_if_in:Nn { Nx } { TF } +% \end{macrocode} +% +% \begin{variable}{\c_@@_default_value_prop} +% Default default value of different types. +% \begin{macrocode} +\prop_const_from_keyval:Nn \c_@@_default_value_prop { + date = \dbtoday, + str = , + tl = , + clist = , + int = 0, + fp = 0 +} +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\@@_type_clist} +% Supported types by \pkg{dbshow}. +% \begin{macrocode} +\clist_const:Nn \@@_type_clist { date, str, tl, clist, int, fp } +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\g_@@_raw_filter_int} +% Counter of anonymous filter. +% \begin{macrocode} +\int_gzero_new:N \g_@@_raw_filter_int +% \end{macrocode} +% \end{variable} +% +% \subsection{Messages} +% +% \begin{arguments} +% \item \meta{database} +% \end{arguments} +% \begin{macrocode} +\msg_new:nnn { dbshow } { non-existent-database } { + Database~'#1'~does~not~exist~\msg_line_context:. +} +% \end{macrocode} +% +% \begin{macro}{\@@_check_database:n} +% Check if the database is valid. +% \begin{arguments} +% \item \meta{database} +% \end{arguments} +% \begin{macrocode} +\cs_new:Nn \@@_check_database:n { + \prop_if_exist:cF { g_@@_attr_type_prop_#1 } + { \msg_fatal:nnn { dbshow } { non-existent-database } {#1} } +} +% \end{macrocode} +% \end{macro} +% +% \begin{arguments} +% \item \meta{database} +% \item \meta{attr} +% \end{arguments} +% \begin{macrocode} +\msg_new:nnn { dbshow } { non-existent-attr } { + Attribute~'#2'~of~database~'#1'~does~not~exist~\msg_line_context:. +} +% \end{macrocode} +% +% \begin{macro}{\@@_check_attr:nn, \@@_check_attr:nV} +% Check if the attribute is valid. +% \begin{arguments} +% \item \meta{database} +% \item \meta{attr} +% \end{arguments} +% \begin{macrocode} +\cs_new:Nn \@@_check_attr:nn { + \prop_if_in:cnF { g_@@_attr_type_prop_#1 } {#2} + { \msg_fatal:nnnn { dbshow } { non-existent-attr } {#1} {#2} } +} +\cs_generate_variant:Nn \@@_check_attr:nn { nV } +% \end{macrocode} +% \end{macro} +% +% \begin{arguments} +% \item \meta{style} +% \item \meta{database} +% \end{arguments} +% \begin{macrocode} +\msg_new:nnn { dbshow } { non-existent-style } { + Style~'#1'~of~database~'#2'~does~not~exist~\msg_line_context:. +} +% \end{macrocode} +% +% \begin{macro}{\@@_check_style:nn} +% Check if the style is valid. +% \begin{arguments} +% \item \meta{style} +% \item \meta{database} +% \end{arguments} +% \begin{macrocode} +\cs_new:Nn \@@_check_style:nn { + \tl_if_exist:cF { g_@@_style_opts_tl_#1_#2 } + { \msg_warning:nnnn { dbshow } { non-existent-style } {#1} {#2} } +} +% \end{macrocode} +% \end{macro} +% +% \begin{arguments} +% \item \meta{database} +% \item \meta{cond} +% \end{arguments} +% \begin{macrocode} +\msg_new:nnn { dbshow } { non-existent-cond } { + Conditional~'#2'~of~database~'#1'~does~not~exist~\msg_line_context:. +} +% \end{macrocode} +% +% \begin{macro}{\@@_check_cond:nnn} +% Check if the conditional is valid. +% \begin{arguments} +% \item \meta{database} +% \item \meta{cond} +% \end{arguments} +% \begin{macrocode} +\cs_new:Nn \@@_check_cond:nnn { + \tl_if_exist:cF { g_@@_filter_attr_#1_#2 } + { \msg_fatal:nnnn { dbshow } { non-existent-cond } {#1} {#2} } +} +% \end{macrocode} +% \end{macro} +% +% \begin{arguments} +% \item \meta{database} +% \item \meta{filter} +% \end{arguments} +% \begin{macrocode} +\msg_new:nnn { dbshow } { non-existent-filter } { + Filter~'#2'~of~database~'#1'~does~not~exist~and~is~ignored~\msg_line_context:. +} +% \end{macrocode} +% +% \begin{macro}{\@@_check_filter:nn, \@@_check_filter:nv} +% Check if the filter is valid. Ignore the default filter |-none-|. +% \begin{arguments} +% \item \meta{database} +% \item \meta{filter} +% \end{arguments} +% \begin{macrocode} +\cs_new:Nn \@@_check_filter:nn { + \seq_if_exist:cF { g_@@_filter_run_seq_#1_#2 } { + \str_if_eq:eeF {#2} { -none- } { + \msg_warning:nnnx { dbshow } { non-existent-filter } {#1} {#2} + } + } +} +\cs_generate_variant:Nn \@@_check_filter:nn { nv } +% \end{macrocode} +% \end{macro} +% +% \begin{arguments} +% \item \meta{type} +% \end{arguments} +% \begin{macrocode} +\msg_new:nnn { dbshow } { non-existent-type } { + Type~'#1'~does~not~exist,~the~type~of~attribute~should~be~one~of~ + \{date,~str,~tl,~clist,~int,~fp\}~\msg_line_context:. +} +% \end{macrocode} +% +% \begin{macro}{\@@_check_type:n} +% Check if the type is valid. +% \begin{arguments} +% \item \meta{type} +% \end{arguments} +% \begin{macrocode} +\cs_new:Nn \@@_check_type:n { + \clist_if_in:NnF \@@_type_clist {#1} + { \msg_fatal:nnn { dbshow } { non-existent-type } {#1} } +} +% \end{macrocode} +% \end{macro} +% +% \begin{arguments} +% \item \meta{valid count} +% \item \meta{real count} +% \item \meta{value} +% \end{arguments} +% \begin{macrocode} +\msg_new:nnn { dbshow } { wrong-seperator } { + option~'sep'~should~contain~#1~items~but~only~#2~items~was~given,~ + sep~=~\{#3\}~\msg_line_context:. +} +% \end{macrocode} +% +% \begin{macro}{\@@_sep_error:nnn, \@@_sep_error:xxx} +% Check the value of \opt{<attr>/sep} is valid. +% \begin{arguments} +% \item \meta{valid count} +% \item \meta{real count} +% \item \meta{value} +% \end{arguments} +% \begin{macrocode} +\cs_new:Nn \@@_sep_error:nnn { + \msg_error:nnnnn { dbshow } { wrong-seperator } {#1} {#2} {#3} +} +\cs_generate_variant:Nn \@@_sep_error:nnn { xxx } +% \end{macrocode} +% \end{macro} +% +% \begin{arguments} +% \item \meta{type} +% \end{arguments} +% \begin{macrocode} +\msg_new:nnn { dbshow } { unsupported-sort-type } { + unsupported~sort~type:~'#1'~\msg_line_context:.~The~type~should~be~one~of~ + \{str,~date,~int,~fp\}. +} +% \end{macrocode} +% +% \subsection{Create Database} +% +% \begin{macro}{\@@_process_default_value:w} +% Create map from \meta{attr} to \meta{type} and map from \meta{attr} to +% \meta{default value}. +% \begin{arguments} +% \item \meta{database} +% \item \meta{attr} +% \item \meta{type} +% \item \meta{default value} +% \end{arguments} +% \begin{macrocode} +\cs_new:Npn \@@_process_default_value:w +#1\@@_sep#2\@@_sep#3|#4\@@_stop { + \@@_check_type:n {#3} + \prop_gput:cxx { g_@@_attr_type_prop_#1 } {#2} {#3} + \prop_gput:cxx { g_@@_default_map_#1 } {#2} {#4} +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_process_attr_type_prop:n} +% Parse default value from the value of the type map. If \meta{type spec} is +% \meta{type\orbar default value} then set the default value to \meta{default +% value}, otherwise if \meta{type spec} is \meta{type} then set the default +% value to the default value of the type. +% \begin{arguments} +% \item \meta{database} +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_process_attr_type_prop:n { + \prop_gclear_new:c { g_@@_default_map_#1 } +% \end{macrocode} +% \begin{arguments}[2] +% \item \meta{attr} +% \item \meta{type spec} +% \end{arguments} +% \begin{macrocode} + \prop_map_inline:cn { g_@@_attr_type_prop_#1 } { + \str_if_in:nnTF {##2} { | } { + \@@_process_default_value:w + #1\@@_sep##1\@@_sep##2\@@_stop + } { + \prop_get:NnN \c_@@_default_value_prop {##2} \l_@@_tmp_default + \@@_process_default_value:w + #1\@@_sep##1\@@_sep##2|\l_@@_tmp_default\@@_stop + } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_database_new:nn} +% Create a new \meta{database} with \meta{database spec}, which is a list of +% \meta{attr} = \meta{type spec}. This function initialize the index counter +% and save \meta{attr} = \meta{type spec} pairs to the type map. If +% \meta{database} has existed, the old definition is discarded. +% \begin{arguments} +% \item \meta{database} +% \item \meta{database spec} +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_database_new:nn { + \int_gzero_new:c { g_@@_counter_#1 } + \prop_gset_from_keyval:cn { g_@@_attr_type_prop_#1 } {#2} +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_database_new_append:nn} +% Create a new \meta{database} with \meta{database spec}, which is a list of +% \meta{attr} = \meta{type spec}. This function initialize the index counter +% and save \meta{attr} = \meta{type spec} pairs to the type map. If +% \meta{database} has existed, the old definition is merged into the new +% definition that has a higher priority. +% \begin{arguments} +% \item \meta{database} +% \item \meta{database spec} +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_database_new_append:nn { + \int_gzero_new:c { g_@@_counter_#1 } + \prop_if_exist:cF { g_@@_attr_type_prop_#1 } + { \prop_new:c { g_@@_attr_type_prop_#1 } } + \prop_gset_from_keyval:Nn \l_tmpa_prop {#2} + \prop_concat:ccc { g_@@_attr_type_prop_#1 } + { g_@@_attr_type_prop_#1 } { l_tmpa_prop } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_database_new_inherit:nnn} +% Create a new \meta{database} with \meta{database spec}, which is a list of +% \meta{attr} = \meta{type spec}. The new \meta{database} is based on +% \meta{base database}. If \meta{database} is equal to \meta{base database}, +% \cs{@@_database_new_append:nn} is called, otherwise the index counter is +% initialized and the definition is merged with the definition of \meta{base +% dadatabase}. +% \begin{arguments} +% \item \meta{database} +% \item \meta{base database} +% \item \meta{database spec} +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_database_new_inherit:nnn { + \@@_check_database:n {#2} + \str_if_eq:nnTF {#1} {#2} { + \@@_database_new_append:nn {#1} {#3} + } { + \int_gzero_new:c { g_@@_counter_#1 } + \prop_gset_from_keyval:cn { g_@@_attr_type_prop_#1 } {#3} + \prop_concat:ccc { g_@@_attr_type_prop_#1 } + { g_@@_attr_type_prop_#2 } { g_@@_attr_type_prop_#1 } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\dbNewDatabase} +% User interface to create a new \meta{database}. Internal attribute |id| is +% added to \meta{database}. After attributes are settle down, default values +% are parsed by \cs{@@_process_attr_type_prop:n}, and keys serving to save data of +% \meta{database} are defined. At last, we define the |default| style as its +% name implies. +% \begin{arguments} +% \item \meta{star} that indicates append or not +% \item \meta{base database} +% \item \meta{database} +% \item \meta{database spec} +% \end{arguments} +% \begin{macrocode} +\NewDocumentCommand { \dbNewDatabase } { s o m m } { + \IfNoValueTF {#2} { + \IfBooleanTF {#1} + { \@@_database_new_append:nn {#3} {#4} } + { \@@_database_new:nn {#3} {#4} } + } { \@@_database_new_inherit:nnn {#3} {#2} {#4} } + \@@_database_new_append:nn {#3} { id=int } + \@@_process_attr_type_prop:n {#3} + \@@_set_database_keys:n {#3} + \dbNewStyle{default}{#3}{} +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_set_database_keys:n} +% Set keys of \meta{database} to make it able to save data with key-value +% pairs. +% \begin{arguments} +% \item \meta{database} +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_set_database_keys:n { +% \end{macrocode} +% \begin{arguments}[2] +% \item \meta{type} +% \end{arguments} +% \begin{macrocode} + \prop_map_inline:cn { g_@@_attr_type_prop_#1 } { + \keys_define:nn { dbshow/database/#1 } { +% \end{macrocode} +% \begin{arguments}[3] +% \item \meta{data} +% \end{arguments} +% \begin{macrocode} + ##1 .code:n = \@@_save_data:nnn {#1} {##1} {####1}, + ##1* .code:n = { + \@@_save_data:nnn {#1} {##1} { \exp_not:n {####1} }, + }, + } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_get_type:nn, \@@_get_type:nV} +% Convenient function to get the \meta{type} of \meta{attr} of \meta{database}. +% \begin{arguments} +% \item \meta{database} +% \item \meta{attr} +% \end{arguments} +% \begin{macrocode} +\cs_new:Nn \@@_get_type:nn { + \prop_item:cn { g_@@_attr_type_prop_#1 } {#2} +} +\cs_generate_variant:Nn \@@_get_type:nn { nV } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_get_counter:n} +% Convenient function to get the value of the index counter. +% \begin{arguments} +% \item \meta{database} +% \end{arguments} +% \begin{macrocode} +\cs_new:Nn \@@_get_counter:n { + \int_use:c { g_@@_counter_#1 } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_step_counter:n} +% Convenient function to step the index counter. +% \begin{arguments} +% \item \meta{database} +% \end{arguments} +% \begin{macrocode} +\cs_new:Nn \@@_step_counter:n { + \int_gincr:c { g_@@_counter_#1 } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\dbclear} +% User interface to clear the \meta{database}. The index counter is set to +% zero and data is not really wiped. +% \begin{arguments} +% \item \meta{database} +% \end{arguments} +% \begin{macrocode} +\NewDocumentCommand { \dbclear } { m } { + \int_gzero:c { g_@@_counter_#1 } +} +% \end{macrocode} +% \end{macro} +% +% \subsection{Store Data} +% +% \begin{macro}{\@@_save_data:nnn, \@@_save_data:nnx} +% Internal function to store data into +% \csnot{g_@@_data_\meta{database}_\meta{attr}_\meta{index}}. +% \begin{arguments} +% \item \meta{database} +% \item \meta{attr} +% \item \meta{data} +% \end{arguments} +% \begin{macrocode} +\cs_new:Nn \@@_save_data:nnn { + \@@_check_attr:nn {#1} {#2} + \str_case_e:nn { \@@_get_type:nn {#1} {#2} } { + { str } { \str_clear_new:c } + { tl } { \tl_gclear_new:c } + { clist } { \clist_gclear_new:c } + { int } { \int_gzero_new:c } + { fp } { \fp_gzero_new:c } + { date } { \__dbdate_gclear_new:x } + } { g_@@_data_#1_#2_\@@_get_counter:n {#1} } + \str_case_e:nn { \@@_get_type:nn {#1} {#2} } { + { str } { \str_gset:cn } + { tl } { \tl_gset:cn } + { clist } { \clist_gset:cn } + { int } { \int_gset:cn } + { fp } { \fp_gset:cn } + { date } { \__dbdate_gset:xx } + } { g_@@_data_#1_#2_\@@_get_counter:n {#1} } {#3} +} +\cs_generate_variant:Nn \@@_save_data:nnn { nnx } +% \end{macrocode} +% \end{macro} +% +% \changes{1.4}{2022-01-14}{Fix bug}{data cannot contain \cs{par}} +% \begin{macro}{dbitem, \@@_set_default:nn, \dbsave, \dbsave*} +% Environment \env{dbitem} is the user interface to save data with \meta{attr} +% = \meta{data} pairs or using \cs{dbsave}. First we step the index counter +% and set the default value for each attribute. Then we set the value by +% \meta{attr-value list} and the index is also stored to default attribute +% |id|. +% \begin{arguments} +% \item \meta{database} +% \item \meta{attr-value list} +% \end{arguments} +% \begin{macrocode} +\NewDocumentEnvironment { dbitem } { m +O{} } { + \@@_check_database:n {#1} + \@@_step_counter:n {#1} +% \end{macrocode} +% This function is used to set the default values of each attribute. +% \begin{arguments} +% \item \meta{attr} +% \end{arguments} +% \begin{macrocode} + \cs_set:Nn \@@_set_default:nn { + \@@_save_data:nnx {#1} {##1} { + \prop_item:cn { g_@@_default_map_#1 } {##1} + } + } + \prop_map_function:cN { g_@@_attr_type_prop_#1 } \@@_set_default:nn + \@@_save_data:nnx {#1} { id } { \@@_get_counter:n {#1} } + \keys_set:nn { dbshow/database/#1 } {#2} +% \end{macrocode} +% \begin{arguments} +% \item \meta{star} that indicates whether to use \cs{exp_not:n} +% \item \meta{attr} +% \item \meta{data} +% \end{arguments} +% \begin{macrocode} + \NewDocumentCommand { \dbsave } { s m +m } { + \IfBooleanTF {##1} { + \@@_save_data:nnn {#1} {##2} { \exp_not:n {##3} } + } { + \@@_save_data:nnn {#1} {##2} {##3} + } + } +} {} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\dbitemkv} +% Store data with \meta{attr-value list} +% \begin{arguments} +% \item \meta{database} +% \item \meta{attr-value list} +% \end{arguments} +% \begin{macrocode} +\NewDocumentCommand { \dbitemkv } { m +m } { + \begin{dbitem}{#1}[#2] + \end{dbitem} +} +% \end{macrocode} +% \end{macro} +% +% \subsection{Filter} +% +% Following functions have the same argument specifications: +% \begin{arguments} +% \item \meta{star boolean} +% \item \meta{expr} specified by \cs{dbNewConditional} +% \item \meta{current value}, i.e. \cs{dbval} +% \item \meta{true code} to set filter boolean to true +% \item \meta{false code} to set filter boolean to false +% \end{arguments} +% These functions aim to filter \meta{attr} of certain type with \meta{expr} +% in every epoch of iteration. The basic idea is to save the filter result +% into a boolean variable corresponding to each conditional. +% +% \begin{macro}{\@@_filter_int:NNNnn, \@@_filter_int:cccnn} +% Filter integers. +% \begin{arguments} +% \item \meta{star boolean} +% \item \meta{expr} specified by \cs{dbNewConditional} +% \item \meta{current value}, i.e. \cs{dbval} +% \item \meta{true code} to set filter boolean to true +% \item \meta{false code} to set filter boolean to false +% \end{arguments} +% \begin{macrocode} +\cs_new:Nn \@@_filter_int:NNNnn { + \int_compare:nTF {#2} {#4} {#5} +} +\cs_generate_variant:Nn \@@_filter_int:NNNnn { cccnn } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_filter_fp:NNNnn, \@@_filter_fp:cccnn} +% Filter floating point values. +% \begin{arguments} +% \item \meta{star boolean} +% \item \meta{expr} specified by \cs{dbNewConditional} +% \item \meta{current value}, i.e. \cs{dbval} +% \item \meta{true code} to set filter boolean to true +% \item \meta{false code} to set filter boolean to false +% \end{arguments} +% \begin{macrocode} +\cs_new:Nn \@@_filter_fp:NNNnn { + \int_compare:nTF {#2} {#4} {#5} +} +\cs_generate_variant:Nn \@@_filter_fp:NNNnn { cccnn } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_filter_clist:NNNnn, \@@_filter_clist:cccnn} +% Filter comma lists. If \meta{star bool} is true, all values specified by +% \meta{conditional} should be contained in current list. Otherwise, condition +% is met if any value specified by \meta{conditional} appears in current list. +% \begin{arguments} +% \item \meta{star boolean} +% \item \meta{expr} specified by \cs{dbNewConditional} +% \item \meta{current value}, i.e. \cs{dbval} +% \item \meta{true code} to set filter boolean to true +% \item \meta{false code} to set filter boolean to false +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_filter_clist:NNNnn { +% \end{macrocode} +% Initial filter boolean of starred conditional is true. And then we check +% every value in \meta{conditional}. If there is some value that does not +% appear in current list, the result is set to false and the loop is broken. +% \begin{macrocode} + \bool_if:NTF #1 { + #4 \clist_map_inline:Vn #2 + { \clist_if_in:NnF #3 {##1} { #5 \clist_map_break: } } + } { +% \end{macrocode} +% Initial filter boolean of unstarred conditional is false. And then we check +% every value in \meta{conditional}. If there is some value that does appear +% in current list, the result is set to true and the loop is broken. +% \begin{macrocode} + #5 \clist_map_inline:Vn #2 + { \clist_if_in:NnT #3 {##1} { #4 \clist_map_break: } } + } +} +\cs_generate_variant:Nn \@@_filter_clist:NNNnn { cccnn } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_filter_str:NNNnn, \@@_filter_str:cccnn} +% Filter strings with regex expression. Starred filter matches the whole +% string while unstarred matches part of the string. +% \begin{arguments} +% \item \meta{star boolean} +% \item \meta{expr} specified by \cs{dbNewConditional} +% \item \meta{current value}, i.e. \cs{dbval} +% \item \meta{true code} to set filter boolean to true +% \item \meta{false code} to set filter boolean to false +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_filter_str:NNNnn { + \bool_if:NT #1 { + \tl_put_left:Nn #2 { \A } + \tl_put_right:Nn #2 { \Z } + } + \regex_match:VVTF #2 #3 {#4} {#5} +} +\cs_generate_variant:Nn \@@_filter_str:NNNnn { cccnn } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_filter_tl:NNNnn, \@@_filter_tl:cccnn} +% Filter token list with regex expression. It is the same with string. +% \begin{macrocode} +\cs_set_eq:NN \@@_filter_tl:NNNnn \@@_filter_str:NNNnn +\cs_generate_variant:Nn \@@_filter_tl:NNNnn { cccnn } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_parse_date_cond:NNw} +% Help function to parse \meta{review points} and \meta{date} and store them +% in \meta{clist var} and \meta{tl var}. +% \begin{arguments} +% \item \meta{clist var} to store \meta{review points} +% \item \meta{tl var} to store \meta{date} +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_date_cond:NNw #1#2#3|#4\@@_stop { + \clist_set_eq:Nc #1 { g__review_points_#3 } + \tl_set:Nn #2 {#4} +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_filter_date:NNNnn, \@@_filter_date:cccnn} +% Filter dates by \meta{review points} or \meta{expr}. +% \begin{arguments} +% \item \meta{star boolean} +% \item \meta{expr} specified by \cs{dbNewConditional} +% \item \meta{current value}, i.e. \cs{dbval} +% \item \meta{true code} to set filter boolean to true +% \item \meta{false code} to set filter boolean to false +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_filter_date:NNNnn { +% \end{macrocode} +% For starred \meta{conditional}, calculate the days between current day, i.e. +% \cs{dbval} and the date to be compared, i.e. \cs{l_@@_filter_tmp_tl} to see +% if the result appears in the \meta{review points}. +% \begin{macrocode} + \bool_if:NTF #1 { + \int_zero_new:N \l_@@_filter_diff_int + \exp_last_unbraced:NNNV \@@_parse_date_cond:NNw + \l_@@_filter_tmp_clist \l_@@_filter_tmp_tl {#2} \@@_stop + \__dbdate_clear_new:n { tmp_day1 } + \__dbdate_clear_new:n { tmp_day2 } + \__dbdate_set:xx { tmp_day1 } { \l_@@_filter_tmp_tl } + \__dbdate_set:xx { tmp_day2 } {#3} + \__dbdate_sub:nnN { tmp_day1 } { tmp_day2 } \l_@@_filter_diff_int + \clist_if_in:NxTF \l_@@_filter_tmp_clist + { \int_use:N \l_@@_filter_diff_int } {#4} {#5} + } { +% \end{macrocode} +% For unstarred \meta{conditional} which parses \meta{expr}. We first replace +% each date to an absolute integer. We did not use \cs{regex_replace_all:nnN} +% because \cs{_dbdate_to_int:nN} is nonexpandable. So the code seems a little +% complicated and unsightly, but it worked. Note that \meta{expr} should be +% updated locally. +% \begin{macrocode} + \int_zero_new:N \l_@@_filter_tmpa_int + \int_zero_new:N \l_@@_filter_tmpb_int + \tl_set:Nx \l_@@_expr_tl {#2} + \regex_extract_all:nVN { \d{4}/\d+/\d+ } + \l_@@_expr_tl \l_@@_filter_date_seq + \regex_split:nVN { \d{4}/\d+/\d+ } + \l_@@_expr_tl \l_@@_filter_other_seq + \tl_clear:N \l_@@_expr_tl + \int_set:Nn \l_@@_filter_tmpa_int + { \seq_count:N \l_@@_filter_date_seq } + \int_step_inline:nn { \l_@@_filter_tmpa_int } { + \tl_put_right:Nx \l_@@_expr_tl + { \seq_item:Nn \l_@@_filter_other_seq {##1} } + \__dbdate_clear_new:n { date-tmp } + \__dbdate_set:xx { date-tmp } + { \seq_item:Nn \l_@@_filter_date_seq {##1} } + \__dbdate_to_int:nN { date-tmp } \l_@@_filter_tmpb_int + \tl_put_right:Nx \l_@@_expr_tl + { \int_use:N \l_@@_filter_tmpb_int } + } + \tl_put_right:Nx \l_@@_expr_tl { + \seq_item:Nn \l_@@_filter_other_seq + { \l_@@_filter_tmpa_int + 1 } + } + \int_compare:nTF { \l_@@_expr_tl } {#4} {#5} + } +} +\cs_generate_variant:Nn \@@_filter_date:NNNnn { cccnn } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_filter:nnn} +% Filter records with \meta{conditional} +% \begin{arguments} +% \item \meta{database} +% \item \meta{conditional} +% \item \meta{index} +% \end{arguments} +% \begin{macrocode} +\cs_set:Nn \@@_filter:nnn { + \tl_set_eq:Nc \l_@@_attr_tl { g_@@_filter_attr_tl_#1_#2 } + \cs_set_eq:Nc \dbval { g_@@_data_#1_\l_@@_attr_tl _#3 } + \use:c + { @@_filter_\@@_get_type:nV {#1} \l_@@_attr_tl :cccnn } + { g_@@_cond_star_bool_#1_#2 } + { g_@@_filter_expr_tl_#1_#2 } + { dbval } + { \bool_gset_true:c { g_@@_filter_bool_#1_#2 } } + { \bool_gset_false:c { g_@@_filter_bool_#1_#2 } } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_new_conditional:nnnnn} +% For a \meta{conditional} of \meta{attr}, map \meta{conditional} to +% \meta{attr} and map \meta{conditional} to {expr}. The \meta{boolean var} is +% created to store the filter result. An hook function is defined and the +% \meta{conditional} is recorded in the sequence. +% \begin{arguments} +% \item \meta{database} +% \item \meta{conditional} +% \item \meta{attr} +% \item \meta{expr} +% \item \meta{star} +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_new_conditional:nnnnn { + \tl_gset:cn { g_@@_filter_attr_tl_#1_#2 } {#3} + \tl_gset:cn { g_@@_filter_expr_tl_#1_#2 } {#4} + \bool_if_exist:cF { g_@@_filter_bool_#1_#2 } + { \bool_new:c { g_@@_filter_bool_#1_#2 } } + \bool_if_exist:cF { g_@@_cond_star_bool_#1_#2 } + { \bool_new:c { g_@@_cond_star_bool_#1_#2 } } + \IfBooleanTF {#5} + { \bool_gset_true:c { g_@@_cond_star_bool_#1_#2 } } + { \bool_gset_false:c { g_@@_cond_star_bool_#1_#2 } } +% \end{macrocode} +% Filter hook function. +% \begin{arguments}[2] +% \item \meta{index} +% \end{arguments} +% \begin{macrocode} + \cs_gset:cn { g_@@_filter_hook_#1_#2:n } { + \@@_filter:nnn {#1} {#2} {##1} + } + \seq_gput_right:cn { g_@@_cond_seq_#1 } {#2} +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_combine_conditional:nnn, \@@_combine_conditional:nVn} +% First extract all the \meta{conditional} in \meta{conditional expr} and for +% every \meta{conditional} in the record sequence, if it is in +% \meta{conditional expr}, then add the corresponding hook function to running +% sequence. Then replace all the \meta{conditional} in \meta{conditional expr} +% with corresponding boolean variable and save the result in the filter +% boolean variable. +% \begin{arguments} +% \item \meta{database} +% \item \meta{filter} +% \item \meta{conditional expr} +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_combine_conditional:nnn { + \tl_gset_eq:cN { g_@@_filter_bool_tl_#1_#2 } \c_true_bool + \seq_gclear_new:c { g_@@_filter_run_seq_#1_#2 } + \regex_extract_all:nnN { \w+ } {#3} \l_@@_cond_seq +% \end{macrocode} +% \begin{arguments}[2] +% \item \meta{conditional} +% \end{arguments} +% \begin{macrocode} + \seq_map_inline:Nn \l_@@_cond_seq { + \seq_if_in:cnT { g_@@_cond_seq_#1 } {##1} { + \seq_gput_right:cn { g_@@_filter_run_seq_#1_#2 } + { g_@@_filter_hook_#1_##1:n } + } + } + \tl_set:Nn \l_@@_cond_expr_tl {#3} + \regex_replace_all:nnN + { \w+ } { \c{ g_@@_filter_bool_#1_\0 } } + \l_@@_cond_expr_tl + \tl_gset_eq:cN + { g_@@_filter_bool_tl_#1_#2 } \l_@@_cond_expr_tl +} +\cs_generate_variant:Nn \@@_combine_conditional:nnn { nVn } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{dbFilters, \dbNewConditional, \dbCombineConditionals} +% Environment to define conditionals and filters. +% \begin{arguments} +% \item \meta{database} +% \end{arguments} +% \begin{macrocode} +\NewDocumentEnvironment { dbFilters } { m } { + \seq_gclear_new:c { g_@@_cond_seq_#1 } +% \end{macrocode} +% \begin{arguments}[2] +% \item \meta{star} +% \item \meta{conditional} +% \item \meta{attr} +% \item \meta{expr} +% \end{arguments} +% \begin{macrocode} + \DeclareDocumentCommand { \dbNewConditional } { s m m m } { + \@@_new_conditional:nnnnn + {#1} {##2} {##3} {##4} {##1} + } +% \end{macrocode} +% \begin{arguments}[2] +% \item \meta{filter} +% \item \meta{conditional expr} +% \item \meta{filter info} +% \end{arguments} +% \begin{macrocode} + \DeclareDocumentCommand { \dbCombineConditionals } { m m O{} } { + \tl_gset:cn { g_@@_filter_info_tl_#1_##1 } {##3} + \@@_combine_conditional:nnn {#1} {##1} {##2} + } +} {} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\dbNewReviewPoints} +% User interface to define \meta{review points}. +% \begin{arguments} +% \item \meta{name} +% \item \meta{points} +% \end{arguments} +% \begin{macrocode} +\NewDocumentCommand { \dbNewReviewPoints } { m m } { + \clist_set:cn { g__review_points_#1 } {#2} +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\dbIntAbs, \dbIntSign, \dbIntDivRound, \dbIntDivTruncate, +% \dbIntMax, \dbIntMin, \dbIntMod, \dbFpSign} +% Function aliases to support more operations of integer and floating points. +% \begin{macrocode} +\cs_set_eq:NN \dbIntAbs \int_abs:n +\cs_set_eq:NN \dbIntSign \int_sign:n +\cs_set_eq:NN \dbIntDivRound \int_div_round:nn +\cs_set_eq:NN \dbIntDivTruncate \int_div_truncate:nn +\cs_set_eq:NN \dbIntMax \int_max:nn +\cs_set_eq:NN \dbIntMin \int_min:nn +\cs_set_eq:NN \dbIntMod \int_mod:nn +\cs_set_eq:NN \dbFpSign \fp_sign:n +% \end{macrocode} +% \end{macro} +% +% \subsection{Style and Options} +% +% \begin{macro}{\@@_identity:n} +% Does nothing and keep things unchanged. +% \begin{macrocode} +\cs_new:Nn \@@_identity:n {#1} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_new_attr_style:nnn} +% Define style keys for each attribute. +% \begin{arguments} +% \item \meta{style} +% \item \meta{database} +% \item \meta{attr} +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_new_attr_style:nnn { + \@@_check_attr:nn {#2} {#3} + \keys_define:nn { dbshow/style/#1/#3 } { + before-code .tl_gset:c = { + g_@@_style_attr_before_tl_#1_#2_#3 + }, + before-code .initial:n = , + after-code .tl_gset:c = { + g_@@_style_attr_after_tl_#1_#2_#3 + }, + after-code .initial:n = , +% \end{macrocode} +% For comma list and date. +% \begin{macrocode} + sep .clist_gset:c = { + g_@@_style_attr_sep_#1_#2_#3 + }, +% \end{macrocode} +% Only for comma list. +% \begin{macrocode} + item-before-code .tl_gset:c = { + g_@@_style_attr_item_before_tl_#1_#2_#3 + }, + item-before-code .initial:n = , + item-after-code .tl_gset:c = { + g_@@_style_attr_item_after_tl_#1_#2_#3 + }, + item-after-code .initial:n = , +% \end{macrocode} +% Only for date. +% \begin{macrocode} + zfill .bool_gset:c = { + g_@@_style_attr_zfill_bool_#1_#2_#3 + }, + zfill .initial:n = true, + zfill .default:n = true, + wrapper .tl_gset:c = { + g_@@_style_attr_wrapper_#1_#2_#3 + }, + wrapper .initial:n = { \@@_identity:n }, + } + \str_case_e:nn { \@@_get_type:nn {#2} {#3} } { + { clist } + { \keys_set:nn { dbshow/style/#1/#3 } { sep = { { ,~ } } } } + { date } + { \keys_set:nn { dbshow/style/#1/#3 } { sep = { { / } } } } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_new_database_style:nn} +% Define style keys. +% \begin{arguments} +% \item \meta{style} +% \item \meta{database} +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_new_database_style:nn { + \@@_check_database:n {#2} + \keys_define:nn { dbshow/style/#1 } { + raw-filter .code:n = { + \int_gincr:N \g_@@_raw_filter_int + \str_set:Nx \l_@@_raw_filter_str + { -raw\int_use:N \g_@@_raw_filter_int - } + \tl_gset:cV { g_@@_filter_#1_#2 } \l_@@_raw_filter_str + \@@_combine_conditional:nnn {#2} \l_@@_raw_filter_str {##1} + }, + filter .tl_gset:c = { g_@@_filter_#1_#2 }, + filter .initial:n = -none-, + sort .clist_gset:c = { g_@@_sort_clist_#1_#2 }, + before-code .tl_gset:c = { g_@@_style_before_tl_#1_#2 }, + before-code .initial:n = , + item-code .tl_gset:c = { g_@@_style_database_item_tl_#1_#2 }, + item-code .initial:n = , + after-code .tl_gset:c = { g_@@_style_after_tl_#1_#2 }, + after-code .initial:n = , + record-before-code .tl_gset:c = { g_@@_style_record_before_tl_#1_#2 }, + record-before-code .initial:n = , + record-after-code .tl_gset:c = { g_@@_style_record_after_tl_#1_#2 }, + record-after-code .initial:n = , + } + \prop_map_inline:cn { g_@@_attr_type_prop_#2 } + { \@@_new_attr_style:nnn {#1} {#2} {##1} } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\dbNewStyle} +% Set style options based on \meta{base style}. +% \begin{arguments} +% \item \meta{base style clist} +% \item \meta{style} +% \item \meta{database} +% \item \meta{options} +% \end{arguments} +% \begin{macrocode} +\NewDocumentCommand { \dbNewStyle } { o m m +m } { + \tl_gset:cn { g_@@_style_opts_tl_#2_#3 } { #4, } + \IfValueT {#1} { + \tl_clear_new:N \l_@@_style_tmp_tl +% \end{macrocode} +% \begin{arguments}[2] +% \item \meta{base style} +% \end{arguments} +% \begin{macrocode} + \clist_map_inline:nn {#1} { + \@@_check_style:nn {##1} {#3} + \tl_if_exist:cT { g_@@_style_opts_tl_##1_#3 } { + \tl_concat:ccc { l_@@_style_tmp_tl } + { l_@@_style_tmp_tl } { g_@@_style_opts_tl_##1_#3 } + } + } + \tl_gconcat:ccc { g_@@_style_opts_tl_#2_#3 } + { l_@@_style_tmp_tl } { g_@@_style_opts_tl_#2_#3 } + } + \@@_new_database_style:nn {#2} {#3} + \keys_set:nv { dbshow/style/#2 } { g_@@_style_opts_tl_#2_#3 } +} +% \end{macrocode} +% \end{macro} +% +% \subsection{Sort} +% +% \begin{macro}{\@@_sort_parse_star:NNNw} +% Parse descending sorting rule. +% \begin{arguments} +% \item \meta{tl var} representing for relation to keep order the same +% \item \meta{tl var} representing for relation to swap the order +% \item \meta{tl var} to store the \meta{attr} +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Npn \@@_sort_parse_star:NNNw #1#2#3#4* { + \tl_set:Nn #1 { > } + \tl_set:Nn #2 { < } + \tl_set:Nn #3 {#4} +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_sort:nNn} +% Sort the records. +% \begin{arguments} +% \item \meta{database} +% \item \meta{index clist} +% \item \meta{style} +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_sort:nNn { + \int_zero_new:N \l_@@_sort_len_int + \int_zero_new:N \l_@@_sort_tmp_int + \int_set:Nn \l_@@_sort_len_int + { \clist_count:c { g_@@_sort_clist_#3_#1 } } +% \end{macrocode} +% Sort recursively. +% \begin{macrocode} + \clist_sort:Nn #2 { + \int_zero:N \l_@@_sort_tmp_int +% \end{macrocode} +% Sort single attribute. +% \begin{macrocode} + \cs_set:Nn \@@_sort_single: { + \int_incr:N \l_@@_sort_tmp_int + \str_set:Nx \l_@@_sort_attr_str { + \clist_item:cn + { g_@@_sort_clist_#3_#1 } + { \l_@@_sort_tmp_int } + } +% \end{macrocode} +% Parse \meta{attr} and corresponding \meta{type} and set compare operators. +% \begin{macrocode} + \str_if_in:NnTF \l_@@_sort_attr_str { * } { + \exp_after:wN \@@_sort_parse_star:NNNw + \exp_after:wN \l_@@_sort_same_op_tl + \exp_after:wN \l_@@_sort_swap_op_tl + \exp_after:wN \l_@@_sort_attr_str + \l_@@_sort_attr_str + } { + \tl_set:Nn \l_@@_sort_same_op_tl { < } + \tl_set:Nn \l_@@_sort_swap_op_tl { > } + } +% \end{macrocode} +% Check if type is valid and transform date to string. +% \begin{macrocode} + \@@_check_attr:nV {#1} \l_@@_sort_attr_str + \tl_set:Nx \l_@@_sort_type_tl + { \@@_get_type:nV {#1} \l_@@_sort_attr_str } + \clist_if_in:nVF + { str, int, date, fp } { \l_@@_sort_type_tl } { + \msg_error:nnx { dbshow } { unsupported-sort-type } + { \l_@@_sort_type_tl } + } + \str_if_eq:eeT { \l_@@_sort_type_tl } { date } + { \tl_set:Nn \l_@@_sort_type_tl { str } } +% \end{macrocode} +% Set operands and compare function. +% \begin{macrocode} + \cs_set_eq:Nc \l_@@_sort_tmpa_tl + { g_@@_data_#1_\l_@@_sort_attr_str _##1 } + \cs_set_eq:Nc \l_@@_sort_tmpb_tl + { g_@@_data_#1_\l_@@_sort_attr_str _##2 } + \cs_set_eq:Nc \@@_compare + { \l_@@_sort_type_tl _compare:VNVTF } +% \end{macrocode} +% Compare two operands and if they are equal, compare the next attribute. +% \begin{macrocode} + \@@_compare \l_@@_sort_tmpa_tl + \l_@@_sort_same_op_tl \l_@@_sort_tmpb_tl + { \sort_return_same: } + { + \@@_compare \l_@@_sort_tmpa_tl + \l_@@_sort_swap_op_tl \l_@@_sort_tmpb_tl + { \sort_return_swapped: } + { + \int_compare:nTF + { \l_@@_sort_len_int = \l_@@_sort_tmp_int } + { \sort_return_same: } + { \@@_sort_single: } + } + } + } + \@@_sort_single: + } +} +% \end{macrocode} +% \end{macro} +% +% \subsection{Display Data} +% +% \begin{macro}{\@@_clist_wrapper:NNn} +% Wrap the clist item with \meta{before code} and \meta{after code}. +% \begin{arguments} +% \item \meta{before code tl} +% \item \meta{after code tl} +% \item \meta{item} +% \end{arguments} +% \begin{macrocode} +\cs_new:Nn \@@_clist_wrapper:NNn { + \exp_not:n { { #1#3#2 }, } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_clist_use:NNNN, \@@_clist_use:cccc} +% Display a comma list. +% \begin{arguments} +% \item \meta{data clist} +% \item \meta{separator clist} +% \item \meta{before code tl} +% \item \meta{after code tl} +% \end{arguments} +% \begin{macrocode} +\cs_new:Nn \@@_clist_use:NNNN { + \int_case:nnF { \clist_count:N #2 } { + { 1 } { + \clist_use:xx + { \clist_map_tokens:Nn #1 { \@@_clist_wrapper:NNn #3 #4 } } + { \clist_item:Nn #2 { 1 } } + } + { 3 } { + \clist_use:xxxx + { \clist_map_tokens:Nn #1 { \@@_clist_wrapper:NNn #3 #4 } } + { \clist_item:Nn #2 { 1 } } + { \clist_item:Nn #2 { 2 } } + { \clist_item:Nn #2 { 3 } } + } + } { + \@@_sep_error:xxx + { 1~or~3 } + { \clist_count:N #2 } + { \clist_use:Nn #2 { ,~ } } + } +} +\cs_generate_variant:Nn \@@_clist_use:NNNN { cccc } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_date_use:nNN, \@@_date_use:ncc} +% Display date. +% \begin{arguments} +% \item \meta{data} +% \item \meta{separator clist} +% \item \meta{zfill boolean} +% \end{arguments} +% \begin{macrocode} +\cs_new:Nn \@@_date_use:nNN { + \int_case:nnF { \clist_count:N #2 } { + { 1 } { + \bool_if:NTF {#3} + { \__dbdate_use_zfill:nf } + { \__dbdate_use:nf } + {#1} + { \clist_item:Nn #2 { 1 } } + } + { 4 } { + \bool_if:NTF {#3} + { \__dbdate_use_zfill:nffff } + { \__dbdate_use:nffff } + {#1} + { \clist_item:Nn #2 { 1 } } + { \clist_item:Nn #2 { 2 } } + { \clist_item:Nn #2 { 3 } } + { \clist_item:Nn #2 { 4 } } + } + } { + \@@_sep_error:xxx + { 1~or~4 } + { \clist_count:N #2 } + { \clist_use:Nn #2 { ,~ } } + } +} +\cs_generate_variant:Nn \@@_date_use:nNN { ncc } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_use_data:nnnn} +% Display Data. +% \begin{arguments} +% \item \meta{database} +% \item \meta{attr} +% \item \meta{index} +% \item \meta{style} +% \end{arguments} +% \begin{macrocode} +% #1 database #2 attr #3 index #4 style +\cs_new:Nn \@@_use_data:nnnn { + \str_case_e:nn + { \prop_item:cn { g_@@_attr_type_prop_#1 } {#2} } { + { str } { \str_use:c { g_@@_data_#1_#2_#3 } } + { tl } { \tl_use:c { g_@@_data_#1_#2_#3 } } + { int } { \int_use:c { g_@@_data_#1_#2_#3 } } + { fp } { \fp_use:c { g_@@_data_#1_#2_#3 } } + { clist } { + \@@_clist_use:cccc { g_@@_data_#1_#2_#3 } + { g_@@_style_attr_sep_#4_#1_#2 } + { g_@@_style_attr_item_before_tl_#4_#1_#2 } + { g_@@_style_attr_item_after_tl_#4_#1_#2 } + } + { date } { + \exp_args:Nnx + \tl_use:c { g_@@_style_attr_wrapper_#4_#1_#2 } { + \@@_date_use:ncc { g_@@_data_#1_#2_#3 } + { g_@@_style_attr_sep_#4_#1_#2 } + { g_@@_style_attr_zfill_bool_#4_#1_#2 } + } + } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\dbDatabase, \dbFilterName, \dbFilterInfo} +% Define context macros. +% \begin{arguments} +% \item \meta{database} +% \item \meta{filter} +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_show_set_macro:nn { + \tl_set:Nn \dbDatabase {#1} + \tl_set:Nn \dbFilterName {#2} + \tl_set_eq:Nc \dbFilterInfo { g_@@_filter_info_tl_#1_#2 } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_show_filter:nn} +% Filter records by executing the hook function in the running sequence and +% then testing the result boolean. +% \begin{arguments} +% \item \meta{database} +% \item \meta{filter} +% \item \meta{index clist} +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_show_filter:nnN { +% \end{macrocode} +% \begin{arguments}[2] +% \item \meta{index} +% \end{arguments} +% \begin{macrocode} + \int_step_inline:nn { \@@_get_counter:n {#1} } { + \seq_if_exist:cTF { g_@@_filter_run_seq_#1_#2 } { +% \end{macrocode} +% \begin{arguments}[3] +% \item \meta{hook} +% \end{arguments} +% \begin{macrocode} + \seq_map_inline:cn { g_@@_filter_run_seq_#1_#2 } { + \use:c {####1} {##1} + } + \exp_args:Nv + \bool_if:nT { g_@@_filter_bool_tl_#1_#2 } + { \clist_put_right:Nn #3 {##1} } + } { \clist_put_right:Nn #3 {##1} } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_show_set_counter:N, \dbalph, \dbAlph, \dbarabic, \dbroman, +% \dbRoman} +% Define macros to display counter. +% \begin{arguments} +% \item \meta{int var} +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_show_set_counter:N { + \tl_set:Nx \dbalph { \int_to_alph:n {#1} } + \tl_set:Nx \dbAlph { \int_to_Alph:n {#1} } + \tl_set:Nx \dbarabic { \int_to_arabic:n {#1} } + \tl_set:Nx \dbRoman { \int_to_Roman:n {#1} } + \tl_set:Nx \dbroman { \int_to_roman:n {#1} } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_show_item:nn, \dbIndex, \dbuse} +% Display single record. +% \begin{arguments} +% \item \meta{style} +% \item \meta{database} +% \item \meta{index clist} +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_show_item:nnN { + \int_zero_new:N \l_@@_show_int +% \end{macrocode} +% \begin{arguments}[2] +% \item \meta{index} +% \end{arguments} +% \begin{macrocode} + \clist_map_inline:Nn #3 { + \int_incr:N \l_@@_show_int + \@@_show_set_counter:N \l_@@_show_int + \tl_set:Nn \dbIndex {##1} +% \end{macrocode} +% \begin{arguments}[3] +% \item \meta{attr} +% \end{arguments} +% \begin{macrocode} + \cs_set:Npn \dbuse ####1 { + \@@_check_attr:nn {#2} {####1} + \tl_use:c { g_@@_style_attr_before_tl_#1_#2_####1 } + \@@_use_data:nnnn {#2} {####1} {##1} {#1} + \tl_use:c { g_@@_style_attr_after_tl_#1_#2_####1 } + } + \tl_use:c { g_@@_style_record_before_tl_#1_#2 } + \tl_use:c { g_@@_style_database_item_tl_#1_#2 } + \tl_use:c { g_@@_style_record_after_tl_#1_#2 } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_show_set_cond:N, \dbIfEmptyT, \dbIfEmptyF, \dbIfEmptyTF} +% Define conditional to test if the number of records to show is zero. +% \begin{arguments} +% \item \meta{index clist} +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_show_set_cond:N { + \prg_set_conditional:Nnn \@@_if_empty: { T, F, TF } { + \clist_if_empty:NTF #1 + { \prg_return_true: } + { \prg_return_false: } + } + \cs_set_eq:NN \dbIfEmptyT \@@_if_empty:T + \cs_set_eq:NN \dbIfEmptyF \@@_if_empty:F + \cs_set_eq:NN \dbIfEmptyTF \@@_if_empty:TF +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_show:nnn, \@@_show:nnv} +% First filter records and sort them if needed and display at last. +% \begin{macrocode} +\cs_new_protected:Nn \@@_show:nnn { + \@@_show_set_macro:nn {#2} {#3} + \clist_clear_new:N \l_@@_show_index_clist + \@@_show_filter:nnN {#2} {#3} \l_@@_show_index_clist + \clist_if_empty:cF { g_@@_sort_clist_#1_#2 } + { \@@_sort:nNn {#2} \l_@@_show_index_clist {#1} } + \tl_use:c { g_@@_style_before_tl_#1_#2 } + \@@_show_item:nnN {#1} {#2} \l_@@_show_index_clist + \tl_use:c { g_@@_style_after_tl_#1_#2 } +} +\cs_generate_variant:Nn \@@_show:nnn { nnv } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\dbshow} +% User insterface to display the \meta{database} with \meta{style}. +% \begin{arguments} +% \item \meta{style} +% \item \meta{database} +% \end{arguments} +% \begin{macrocode} +\NewDocumentCommand { \dbshow } { m m } { + \@@_check_database:n {#2} + \@@_check_filter:nv {#2} { g_@@_filter_#1_#2 } + \@@_show:nnv {#1} {#2} { g_@@_filter_#1_#2 } +} +% \end{macrocode} +% \end{macro} +% +% \subsection{Date Type} +% +% \begin{macrocode} +%<@@=dbdate> +% \end{macrocode} +% +% \begin{macro}[pTF]{\@@_if_leap:n} +% Check if the year is leap. +% \begin{arguments} +% \item \meta{year} +% \end{arguments} +% \begin{macrocode} +\prg_new_conditional:Nnn \@@_if_leap:n { T, F, TF, p } { + \bool_if:nTF { + \int_compare_p:nNn { \int_mod:nn {#1} { 400 } } = { 0 } || + (!\int_compare_p:nNn { \int_mod:nn {#1} { 100 } } = { 0 } && + \int_compare_p:nNn { \int_mod:nn {#1} { 4 } } = { 0 }) + } { \prg_return_true: } { \prg_return_false: } +} +% \end{macrocode} +% \end{macro} +% +% \begin{variable}{\c_@@_month_clist} +% Number of days of every month. +% \begin{macrocode} +\clist_const:Nn \c_@@_month_clist + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_to_int:nnnN} +% Transform date to integer relative to |1971-01-01|. +% \begin{arguments} +% \item \meta{year} +% \item \meta{month} +% \item \meta{day} +% \item \meta{int var} to store the result +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_to_int:nnnN { + \int_zero_new:N \l_@@_ans_int + \int_zero_new:N \l_@@_tmpa_int + \int_zero_new:N \l_@@_tmpb_int + \int_set:Nn \l_@@_ans_int { #3 - 1 } + \int_step_inline:nn { #2 - 1 } { + \int_add:Nn \l_@@_ans_int { + \clist_item:Nn \c_@@_month_clist {##1} + } + \bool_if:nT { + \int_compare_p:nNn {##1} = { 2 } && + \@@_if_leap_p:n {#1} + } { \int_incr:N \l_@@_ans_int } + } + \int_add:Nn \l_@@_ans_int { 365 * (#1 - 1971) } + \int_add:Nn \l_@@_ans_int { + \int_div_truncate:nn { #1 - 1 } { 4 } - + \int_div_truncate:nn { 1971 } { 4 } + } + \int_sub:Nn \l_@@_ans_int { + \int_div_truncate:nn { #1 - 1 } { 100 } - + \int_div_truncate:nn { 1971 } { 100 } + } + \int_add:Nn \l_@@_ans_int { + \int_div_truncate:nn { #1 - 1 } { 400 } - + \int_div_truncate:nn { 1971 } { 400 } + } + \int_set_eq:NN #4 \l_@@_ans_int +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_to_int:NNNN, \@@_to_int:cccN} +% Transform date to integer relative to |1971-01-01|. +% \begin{arguments} +% \item \meta{year int var} +% \item \meta{month int var} +% \item \meta{day int var} +% \item \meta{int var} to store the result +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_to_int:NNNN { + \@@_to_int:nnnN {#1} {#2} {#3} #4 +} +\cs_generate_variant:Nn \@@_to_int:NNNN { cccN } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_to_int:nN} +% Transform date to integer relative to |1971-01-01|. +% \begin{arguments} +% \item \meta{date var} +% \item \meta{int var} to store the result +% \end{arguments} +% \begin{macrocode} +\cs_new:Nn \@@_to_int:nN { + \@@_to_int:cccN + { @@_year_#1 } + { @@_month_#1 } + { @@_day_#1 } + #2 +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_set_val:n, \@@_gset_val:n} +% Set the value of \meta{data var} to |yyyy/mm/dd|. +% \begin{arguments} +% \item \meta{date var} +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_set_val:n { + \tl_set:cx {#1} { \@@_use_zfill:nn {#1} { \g_@@_sep_tl } } +} +\cs_new_protected:Nn \@@_gset_val:n { + \tl_gset:cx {#1} { \@@_use_zfill:nn {#1} { \g_@@_sep_tl } } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_init:n, \@@_ginit:n} +% Initialize \meta{date var}. +% \begin{arguments} +% \item \meta{date var} +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_init:n { + \@@_set:nnnn {#1} { 1971 } { 1 } { 1 } + \@@_set_val:n {#1} +} +\cs_new_protected:Nn \@@_ginit:n { + \@@_gset:nnnn {#1} { 1971 } { 1 } { 1 } + \@@_gset_val:n {#1} +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_new:n, \@@_new:x} +% Create a new date variable. +% \begin{arguments} +% \item \meta{date var} +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_new:n { + \int_new:c { @@_year_#1 } + \int_new:c { @@_month_#1 } + \int_new:c { @@_day_#1 } + \@@_ginit:n {#1} +} +\cs_generate_variant:Nn \@@_new:n { x } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_clear_new:n, \@@_gclear_new:n, \@@_clear_new:x, +% \@@_gclear_new:x} +% Clear or create a new date variable. +% \begin{arguments} +% \item \meta{date var} +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_clear_new:n { + \int_zero_new:c { @@_year_#1 } + \int_zero_new:c { @@_month_#1 } + \int_zero_new:c { @@_day_#1 } + \@@_init:n {#1} +} +\cs_generate_variant:Nn \@@_clear_new:n { x } +\cs_new_protected:Nn \@@_gclear_new:n { + \int_gzero_new:c { @@_year_#1 } + \int_gzero_new:c { @@_month_#1 } + \int_gzero_new:c { @@_day_#1 } + \@@_ginit:n {#1} +} +\cs_generate_variant:Nn \@@_gclear_new:n { x } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_set:nnnn, \@@_gset:nnnn} +% Set the value of \meta{date var}. +% \begin{arguments} +% \item \meta{date var} +% \item \meta{year} +% \item \meta{month} +% \item \meta{day} +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_set:nnnn { + \int_set:cn { @@_year_#1 } {#2} + \int_set:cn { @@_month_#1 } {#3} + \int_set:cn { @@_day_#1 } {#4} + \@@_set_val:n {#1} +} +\cs_new_protected:Nn \@@_gset:nnnn { + \int_gset:cn { @@_year_#1 } {#2} + \int_gset:cn { @@_month_#1 } {#3} + \int_gset:cn { @@_day_#1 } {#4} + \@@_gset_val:n {#1} +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_set_sep:n, \@@_set:w, \@@_gset:w, \dbdatesep} +% Set internal date separator. Default is |/|. +% \begin{arguments} +% \item \meta{separator} +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_set_sep:n { + \tl_gset:Nn \g_@@_sep_tl { #1 } +% \end{macrocode} +% Set the value of \meta{date var}. +% \begin{arguments}[2] +% \item \meta{date var} +% \item \meta{year} +% \item \meta{month} +% \item \meta{day} +% \end{arguments} +% \begin{macrocode} + \cs_gset_protected:Npn \@@_set:w ##1\@@_sep##2#1##3#1##4\@@_stop { + \@@_clear_new:n {##1} + \@@_set:nnnn {##1} {##2} {##3} {##4} + } + \cs_gset_protected:Npn \@@_gset:w ##1\@@_sep##2#1##3#1##4\@@_stop { + \@@_gclear_new:n {##1} + \@@_gset:nnnn {##1} {##2} {##3} {##4} + } +} +\cs_gset_eq:NN \dbdatesep \@@_set_sep:n +\dbdatesep{/} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_set:nn, \@@_set:xx, \@@_gset:nn, \@@_gset:xx} +% Set the value of \meta{date var}. +% \begin{arguments} +% \item \meta{date var} +% \item \meta{date} +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_set:nn { + \@@_set:w #1\@@_sep#2\@@_stop +} +\cs_generate_variant:Nn \@@_set:nn { xx } +\cs_new_protected:Nn \@@_gset:nn { + \@@_gset:w #1\@@_sep#2\@@_stop +} +\cs_generate_variant:Nn \@@_gset:nn { xx } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_sub:nnN} +% Calculate the number of days between \meta{date var2} and \meta{date var1}. +% \begin{arguments} +% \item \meta{date var1} +% \item \meta{date var2} +% \item \meta{int var} to store the result +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_sub:nnN { + \int_zero_new:N \l_@@_sub_tmpa_int + \int_zero_new:N \l_@@_sub_tmpb_int + \@@_to_int:nN {#1} \l_@@_sub_tmpa_int + \@@_to_int:nN {#2} \l_@@_sub_tmpb_int + \int_set:Nn #3 { \l_@@_sub_tmpa_int - \l_@@_sub_tmpb_int } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_show_two:N, \@@_show_two:c} +% Prepend 0 to single digit. +% \begin{macrocode} +\cs_new:Nn \@@_show_two:N { + \int_compare:nNnTF {#1} > { 9 } + { \int_use:N #1 } { 0\int_use:N #1 } +} +\cs_generate_variant:Nn \@@_show_two:N { c } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_use:nnnnn, \@@_use:nffff, \@@_use_zfill:nnnnn, +% \@@_use_zfill:nffff} +% Display date. +% \begin{arguments} +% \item \meta{date var} +% \item \meta{separator 1} +% \item \meta{separator 2} +% \item \meta{separator 3} +% \item \meta{separator 4} +% \end{arguments} +% \begin{macrocode} +\cs_new:Nn \@@_use:nnnnn { + #2\int_use:c { @@_year_#1 } + #3\int_use:c { @@_month_#1 } + #4\int_use:c { @@_day_#1 }#5 +} +\cs_generate_variant:Nn \@@_use:nnnnn { nffff } +\cs_new:Nn \@@_use_zfill:nnnnn { + #2\int_use:c { @@_year_#1 } + #3\@@_show_two:c { @@_month_#1 } + #4\@@_show_two:c { @@_day_#1 }#5 +} +\cs_generate_variant:Nn \@@_use_zfill:nnnnn { nffff } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_use:nn, \@@_use:nf, \@@_use_zfill:nn, \@@_use_zfill:nf} +% Display date with the same separator. +% \begin{macrocode} +\cs_new:Nn \@@_use:nn { + \@@_use:nnnnn {#1} {} {#2} {#2} {} +} +\cs_generate_variant:Nn \@@_use:nn { nf } +\cs_new:Nn \@@_use_zfill:nn { + \@@_use_zfill:nnnnn {#1} {} {#2} {#2} {} +} +\cs_generate_variant:Nn \@@_use_zfill:nn { nf } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_show:n} +% Show date in terminal. +% \begin{arguments} +% \item \meta{date var} +% \end{arguments} +% \begin{macrocode} +\cs_new_protected:Nn \@@_show:n { + \exp_args:Nx \tl_show:n { >#1~=~\@@_use:nn {#1} { - } } +} +% \end{macrocode} +% \end{macro} +% +% \begin{variable}{\dbtoday} +% Display date of today in |yyyy/mm/dd|. +% \begin{macrocode} +\tl_set:Nn \dbtoday { + \int_use:N \c_sys_year_int \g_@@_sep_tl + \int_use:N \c_sys_month_int \g_@@_sep_tl + \int_use:N \c_sys_day_int +} +% \end{macrocode} +% \end{variable} +% +% \begin{macrocode} +\endinput +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \Finale +% +\endinput diff --git a/macros/latex/contrib/dbshow/dbshow.ins b/macros/latex/contrib/dbshow/dbshow.ins new file mode 100644 index 0000000000..ebc4b55794 --- /dev/null +++ b/macros/latex/contrib/dbshow/dbshow.ins @@ -0,0 +1,90 @@ +%% +%% This is file `dbshow.ins', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% dbshow.dtx (with options: `install') +%% +%% Copyright (C) 2022- by Changkai Li <lichangkai225@qq.com> +%% -------------------------------------------------------------------------- +%% +%% This work may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either +%% version 1.3c of this license or (at your option) any later +%% version. This version of this license is in +%% http://www.latex-project.org/lppl/lppl-1-3c.txt +%% and 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 Changkai Li. +%% +%% This package consists of the file dbshow.dtx, +%% and the derived files dbshow.pdf, +%% dbshow.sty, +%% dbshow.ins and +%% README.md. +%% -------------------------------------------------------------------------- +%% + +\input l3docstrip.tex +\keepsilent +\askforoverwritefalse +\preamble + + Copyright (C) 2022- by Changkai Li <lichangkai225@qq.com> + -------------------------------------------------------------------------- + + This work may be distributed and/or modified under the + conditions of the LaTeX Project Public License, either + version 1.3c of this license or (at your option) any later + version. This version of this license is in + http://www.latex-project.org/lppl/lppl-1-3c.txt + and 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 Changkai Li. + + This package consists of the file dbshow.dtx, + and the derived files dbshow.pdf, + dbshow.sty, + dbshow.ins and + README.md. + -------------------------------------------------------------------------- + +\endpreamble +\postamble + + -------------------------------------------------------------------------- + This package consists of the file dbshow.dtx, + and the derived files dbshow.pdf, + dbshow.sty, + dbshow.ins and + README.md. +\endpostamble + +\generate{ + \usedir{tex/latex/dbshow} + \file{dbshow.sty}{\from{\jobname.dtx}{package}} + \nopreamble\nopostamble + \usedir{doc/latex/dbshow} + \file{README.md} {\from{\jobname.dtx}{readme}} +} +\endbatchfile +%% +%% -------------------------------------------------------------------------- +%% This package consists of the file dbshow.dtx, +%% and the derived files dbshow.pdf, +%% dbshow.sty, +%% dbshow.ins and +%% README.md. +%% +%% End of file `dbshow.ins'. diff --git a/macros/latex/contrib/dbshow/dbshow.pdf b/macros/latex/contrib/dbshow/dbshow.pdf Binary files differnew file mode 100644 index 0000000000..8d7c4d1bc2 --- /dev/null +++ b/macros/latex/contrib/dbshow/dbshow.pdf diff --git a/macros/latex/contrib/dbshow/dbshow.sty b/macros/latex/contrib/dbshow/dbshow.sty deleted file mode 100644 index d60c993db1..0000000000 --- a/macros/latex/contrib/dbshow/dbshow.sty +++ /dev/null @@ -1,906 +0,0 @@ -%% dbshow.sty -%% Copyright 2022 Li Changkai <lichangkai225@qq.com> -% -% 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 Li Changkai. -% -% This work consists of the files dbshow.sty, dbshow-doc.tex. -\def\myfileversion{v1.3} -\def\myfiledate{2022/01/10} -\RequirePackage{expl3, xparse} -\ProvidesExplPackage - {dbshow} - {\myfiledate} - {\myfileversion} - {database to store and show data} - -\msg_new:nnn { dbshow } { non-existent-database } { - Database~'#1'~does~not~exist~\msg_line_context:. -} - -% #1 database -\cs_new:Nn \dbshow_check_database:n { - \prop_if_exist:cF { g__dbshow_type_map_#1 } - { \msg_fatal:nnn { dbshow } { non-existent-database } { #1 } } -} - -\msg_new:nnn { dbshow } { non-existent-attr } { - Attribute~'#2'~of~database~'#1'~does~not~exist~\msg_line_context:. -} - -% #1 database #2 attr -\cs_new:Nn \dbshow_check_attr:nn { - \prop_if_in:cnF { g__dbshow_type_map_#1 } { #2 } - { \msg_fatal:nnnn { dbshow } { non-existent-attr } { #1 } { #2 } } -} - -\msg_new:nnn { dbshow } { non-existent-style } { - Style~'#1'~of~database~'#2'~does~not~exist~\msg_line_context:. -} - -% #1 style #2 database -\cs_new:Nn \dbshow_check_style:nn { - \tl_if_exist:cF { g__dbshow_style_opts_#1_#2 } - { \msg_warning:nnnn { dbshow } { non-existent-style } { #1 } { #2 } } -} - -\msg_new:nnn { dbshow } { non-existent-cond } { - Conditional~'#2'~of~database~'#1'~does~not~exist~\msg_line_context:. -} - -% #1 database #2 cond -\cs_new:Nn \dbshow_check_cond:nnn { - \tl_if_exist:cF { g__dbshow_filter_attr_#1_#2 } - { \msg_fatal:nnnn { dbshow } { non-existent-cond } { #1 } { #2 } } -} - -\msg_new:nnn { dbshow } { non-existent-filter } { - Filter~'#2'~of~database~'#1'~does~not~exist~and~is~ignored~\msg_line_context:. -} - -\cs_generate_variant:Nn \msg_warning:nnnn { nnnx } -% #1 database #2 filter -\cs_new:Nn \dbshow_check_filter:nn { - \seq_if_exist:cF { g__dbshow_filter_run_seq_#1_#2 } { - \str_if_eq:eeF { #2 } { -none- } { - \msg_warning:nnnx { dbshow } { non-existent-filter } { #1 } { #2 } - } - } -} - -\msg_new:nnn { dbshow } { non-existent-type } { - Type~'#1'~does~not~exist,~the~type~of~attribute~should~be~one~of~ - \{date,~str,~tl,~clist,~int,~fp\}~\msg_line_context:. -} - -% #1 type -\cs_new:Nn \dbshow_check_type:n { - \clist_if_in:NnF \dbshow_type_clist { #1 } - { \msg_fatal:nnn { dbshow } { non-existent-type } { #1 } } -} - -% #1 valid count #2 real count #3 content -\msg_new:nnn { dbshow } { wrong-seperator } { - option~'sep'~should~contain~#1~items~but~only~#2~items~was~given,~ - sep~=~\{#3\}~\msg_line_context:. -} - -% #1 valid count #2 real count #3 content -\cs_new:Nn \dbshow_sep_error:nnn { - \msg_error:nnnnn { dbshow } { wrong-seperator } { #1 } { #2 } { #3 } -} -\cs_generate_variant:Nn \dbshow_sep_error:nnn { xxx } - -\msg_new:nnn { dbshow } { unsupported-sort-type } { - unsupported~sort~type:~'#1'~\msg_line_context:.~The~type~should~be~one~of~ - \{str,~date,~int,~fp\}. -} - -\msg_new:nnn { dbshow } { invalid-relation } { - invalid~relation:~'#1'. -} - -\clist_const:Nn \dbshow_type_clist { date, str, tl, clist, int, fp } - -\prop_const_from_keyval:Nn \dbshow_default_value { - date = \dbtoday, - str = , - tl = , - clist = , - int = 0, - fp = 0 -} - -\cs_generate_variant:Nn \clist_use:nn { xx } -\cs_generate_variant:Nn \clist_use:nnnn { xxxx } -\cs_generate_variant:Nn \prop_get:NnN { cVN } -\cs_generate_variant:Nn \regex_extract_all:nnN { nVN } -\cs_generate_variant:Nn \regex_split:nnN { nVN } -\prg_generate_conditional_variant:Nnn \str_compare:nNn { VNV } { TF } -\prg_generate_conditional_variant:Nnn \int_compare:nNn { VNV } { TF } -\prg_generate_conditional_variant:Nnn \fp_compare:nNn { VNV } { TF } -\prg_generate_conditional_variant:Nnn \regex_match:nn { VV } { TF } -\prg_generate_conditional_variant:Nnn \clist_if_in:Nn { Nx } { TF } - -% #1 database #2 attr #3 type #4 default value -\cs_new:Npn \dbshow_process_default_value:w #1|#2=#3|#4\scan_stop { - \dbshow_check_type:n { #3 } - \prop_gput:cxx { g__dbshow_type_map_#1 } { #2 } { #3 } - \prop_gput:cxx { g__dbshow_default_map_#1 } { #2 } { #4 } -} - -\cs_new_protected:Nn \dbshow_process_type_map:n { - \prop_gclear_new:c { g__dbshow_default_map_#1 } - \prop_map_inline:cn { g__dbshow_type_map_#1 } { - \str_if_in:nnTF { ##2 } { | } - { \dbshow_process_default_value:w #1|##1=##2\scan_stop } - { - \prop_get:NnN \dbshow_default_value { ##2 } \l_tmp_default - \dbshow_process_default_value:w #1|##1=##2|\l_tmp_default\scan_stop - } - } -} - -% #1 database_name, #2 clist, attr=type -\cs_new_protected:Nn \dbshow_database_new:nn { - \int_gzero_new:c { g__dbshow_counter_#1 } - \prop_gset_from_keyval:cn { g__dbshow_type_map_#1 } { #2 } -} - -% #1 database_name, #2 clist -\cs_new_protected:Nn \dbshow_database_new_append:nn { - \int_gzero_new:c { g__dbshow_counter_#1 } - \prop_if_exist:cF { g__dbshow_type_map_#1 } - { \prop_new:c { g__dbshow_type_map_#1 } } - \prop_gset_from_keyval:Nn \l_tmpa_prop { #2 } - \prop_concat:ccc { g__dbshow_type_map_#1 } { g__dbshow_type_map_#1 } { l_tmpa_prop } -} - -% #1 database_name, #2 database inherit from #3 clist -\cs_new_protected:Nn \dbshow_database_new_inherit:nnn { - \dbshow_check_database:n { #2 } - \str_if_eq:nnTF { #1 } { #2 } { - \dbshow_database_new_append:nn { #1 } { #3 } - } { - \int_gzero_new:c { g__dbshow_counter_#1 } - \prop_gset_from_keyval:cn { g__dbshow_type_map_#1 } { #3 } - \prop_concat:ccc { g__dbshow_type_map_#1 } { g__dbshow_type_map_#2 } { g__dbshow_type_map_#1 } - } -} - -% #1 database_name, #2 attr -\cs_new:Nn \dbshow_get_type:nn { - \prop_item:cn { g__dbshow_type_map_#1 } { #2 } -} - -% #1 database_name -\cs_new:Nn \dbshow_get_counter:n { - \int_use:c { g__dbshow_counter_#1 } -} - -% #1 database_name -\cs_new:Nn \dbshow_step_counter:n { - \int_gincr:c { g__dbshow_counter_#1 } -} - -\NewDocumentCommand { \dbclear } { m } { - \int_gzero:c { g__dbshow_counter_#1 } -} - -% #1 database #2 attr #3 content -\cs_new:Nn \dbshow_save_data:nnn { - \dbshow_check_attr:nn { #1 } { #2 } - \use:c { - \str_case_e:nn { \prop_item:cn { g__dbshow_type_map_#1 } { #2 } } { - { str } { str_clear_new:c } - { tl } { tl_gclear_new:c } - { clist } { clist_gclear_new:c } - { int } { int_gzero_new:c } - { fp } { fp_gzero_new:c } - { date } { dbshow_date_gclear_new:n } - } - } { g__dbshow_data_#1_#2_\int_use:c { g__dbshow_counter_#1 } } - \use:c { - \str_case_e:nn { \prop_item:cn { g__dbshow_type_map_#1 } { #2 } } { - { str } { str_gset:cn } - { tl } { tl_gset:cn } - { clist } { clist_gset:cn } - { int } { int_gset:cn } - { fp } { fp_gset:cn } - { date } { dbshow_date_gset:nx } - } - } { g__dbshow_data_#1_#2_\int_use:c { g__dbshow_counter_#1 } } { #3 } -} -\cs_generate_variant:Nn \dbshow_save_data:nnn { nnx } - -% #1 before code tl #2 after code tl #3 item -\cs_new:Nn \dbshow_clist_wrapper:NNn { - \exp_not:n { { #1#3#2 }, } -} - -% #1 clist #2 sep #3 before code tl #4 after code tl -\cs_new:Nn \dbshow_clist_use:NNNN { - \int_case:nnF { \clist_count:N #2 } { - { 1 } { - \clist_use:xx - { \clist_map_tokens:Nn #1 { \dbshow_clist_wrapper:NNn #3 #4 } } - { \clist_item:Nn #2 { 1 } } - } - { 3 } { - \clist_use:xxxx - { \clist_map_tokens:Nn #1 { \dbshow_clist_wrapper:NNn #3 #4 } } - { \clist_item:Nn #2 { 1 } } - { \clist_item:Nn #2 { 2 } } - { \clist_item:Nn #2 { 3 } } - } - } { - \dbshow_sep_error:xxx - { 1~or~3 } - { \clist_count:N #2 } - { \clist_use:Nn #2 { ,~ } } - } -} -\cs_generate_variant:Nn \dbshow_clist_use:NNNN { cccc } - -% #1 date #2 sep #3 zfill bool -\cs_new:Nn \dbshow_date_use:nNN { - \int_case:nnF { \clist_count:N #2 } { - { 1 } { - \bool_if:NTF { #3 } - { \dbshow_date_use_zfill:nf } - { \dbshow_date_use:nf } - { #1 } - { \clist_item:Nn #2 { 1 } } - } - { 4 } { - \bool_if:NTF { #3 } - { \dbshow_date_use_zfill:nffff } - { \dbshow_date_use:nffff } - { #1 } - { \clist_item:Nn #2 { 1 } } - { \clist_item:Nn #2 { 2 } } - { \clist_item:Nn #2 { 3 } } - { \clist_item:Nn #2 { 4 } } - } - } { - \dbshow_sep_error:xxx - { 1~or~4 } - { \clist_count:N #2 } - { \clist_use:Nn #2 { ,~ } } - } -} -\cs_generate_variant:Nn \dbshow_date_use:nNN { ncc } - -% #1 database #2 attr #3 index #4 style -\cs_new:Nn \dbshow_use_data:nnnn { - \str_case_e:nn { \prop_item:cn { g__dbshow_type_map_#1 } { #2 } } { - { str } { \str_use:c { g__dbshow_data_#1_#2_#3 } } - { tl } { \tl_use:c { g__dbshow_data_#1_#2_#3 } } - { int } { \int_use:c { g__dbshow_data_#1_#2_#3 } } - { fp } { \fp_use:c { g__dbshow_data_#1_#2_#3 } } - { clist } { - \dbshow_clist_use:cccc { g__dbshow_data_#1_#2_#3 } - { g__dbshow_style_attr_sep_#4_#1_#2 } - { g__dbshow_style_attr_item_before_#4_#1_#2 } - { g__dbshow_style_attr_item_after_#4_#1_#2 } - } - { date } { - \exp_args:Nnx - \tl_use:c { g__dbshow_style_attr_wrapper_#4_#1_#2 } { - \dbshow_date_use:ncc { g__dbshow_data_#1_#2_#3 } - { g__dbshow_style_attr_sep_#4_#1_#2 } - { g__dbshow_style_attr_zfill_#4_#1_#2 } - } - } - } -} - -% #1 database -\cs_new_protected:Nn \dbshow_set_database_keys:n { - \prop_map_inline:cn { g__dbshow_type_map_#1 } { - \keys_define:nn { dbshow/database/#1 } { - ##1 .code:n = \dbshow_save_data:nnn { #1 } { ##1 } { ####1 }, - } - } -} - -% #1 append or not #2 inherit #3 database #4 attrs -\NewDocumentCommand { \dbNewDatabase } { s o m m } { - \IfNoValueTF { #2 } { - \IfBooleanTF { #1 } - { \dbshow_database_new_append:nn { #3 } { #4 } } - { \dbshow_database_new:nn { #3 } { #4 } } - } { \dbshow_database_new_inherit:nnn { #3 } { #2 } { #4 } } - \dbshow_database_new_append:nn { #3 } { id=int } - \dbshow_process_type_map:n { #3 } - \dbshow_set_database_keys:n { #3 } - \dbNewStyle{default}{#3}{} -} - -% #1 database #2 attr-content map -\NewDocumentEnvironment { dbitem } { m O{} +b } { - \dbshow_check_database:n { #1 } - \dbshow_step_counter:n { #1 } - \cs_set:Nn \dbshow_set_default:nn { - \dbshow_save_data:nnx { #1 } { ##1 } { - \prop_item:cn { g__dbshow_default_map_#1 } { ##1 } - } - } - \prop_map_function:cN { g__dbshow_type_map_#1 } \dbshow_set_default:nn - \dbshow_save_data:nnx { #1 } { id } { \dbshow_get_counter:n { #1 } } - \keys_set:nn { dbshow/database/#1 } { #2 } - % ##1 exp or not ##2 attr ##3 content - \NewDocumentCommand { \dbsave } { s m m } { - \IfBooleanTF { ##1 } { - \dbshow_save_data:nnn { #1 } { ##2 } { \exp_not:n { ##3 } } - } { - \dbshow_save_data:nnn { #1 } { ##2 } { ##3 } - } - } -} { #3 } - -\cs_new:Nn \dbshow_if_int: { - \int_compare:nTF { \l_dbshow_rela } - { \dbshow_set_true: } - { \dbshow_set_false: } -} - -\cs_new:Nn \dbshow_if_fp: { - \fp_compare:nTF { \l_dbshow_rela } - { \dbshow_set_true: } - { \dbshow_set_false: } -} - -% star: all in -% no star: one in -\cs_new:Nn \dbshow_if_clist: { - \bool_if:NTF \l_star_bool { % and - \dbshow_set_true: - \exp_args:Nx - \clist_map_inline:nn { \l_dbshow_rela } { - \clist_if_in:NnF \dbval { ##1 } { - \dbshow_set_false: - \clist_map_break: - } - } - } - { % or - \dbshow_set_false: - \exp_args:Nx - \clist_map_inline:nn { \l_dbshow_rela } { - \clist_if_in:NnT \dbval { ##1 } { - \dbshow_set_true: - \clist_map_break: - } - } - } -} - -% star: match full -% no star: match part -\cs_new:Nn \dbshow_if_str: { - \bool_if:NT \l_star_bool { - \tl_put_left:Nn \l_dbshow_rela { \A } - \tl_put_right:Nn \l_dbshow_rela { \Z } - } - \regex_match:VVTF \l_dbshow_rela \dbval - { \dbshow_set_true: } - { \dbshow_set_false: } -} -\cs_set_eq:NN \dbshow_if_tl: \dbshow_if_str: - -\cs_new:Npn \dbshow_parse_date:w #1|#2\dbshow_stop { - \clist_set_eq:Nc \l_point_clist { g__review_points_#1 } - \tl_set:Nn \l_date_tl { #2 } -} - -\cs_new_protected:Nn \dbshow_if_date: { - \int_zero_new:N \l__dbshow_if_tmpa_int - \int_zero_new:N \l__dbshow_if_tmpb_int - \int_zero_new:N \l__dbshow_if_diff_int - \bool_if:NTF \l_star_bool { % review points - \exp_after:wN \dbshow_parse_date:w \l_dbshow_rela\dbshow_stop - \dbshow_date_clear_new:n { tmp_day1 } - \dbshow_date_clear_new:n { tmp_day2 } - \dbshow_date_set:nx { tmp_day1 } { \l_date_tl } - \dbshow_date_set:nx { tmp_day2 } { \dbval } - \dbshow_date_sub:nnN { tmp_day1 } { tmp_day2 } \l__dbshow_if_diff_int - \clist_if_in:NxTF \l_point_clist { \int_use:N \l__dbshow_if_diff_int } - { \dbshow_set_true: } - { \dbshow_set_false: } - } - { % rela - \tl_set:Nx \l_dbshow_rela { \l_dbshow_rela } - \regex_extract_all:nVN { \d{4}/\d+/\d+ } \l_dbshow_rela \l_date_seq - \regex_split:nVN { \d{4}/\d+/\d+ } \l_dbshow_rela \l_other_seq - \tl_clear:N \l_dbshow_rela - \int_set:Nn \l__dbshow_if_tmpa_int { \seq_count:N \l_date_seq } - \int_step_inline:nn { \l__dbshow_if_tmpa_int } { - \tl_put_right:Nx \l_dbshow_rela { \seq_item:Nn \l_other_seq { ##1 } } - \dbshow_date_clear_new:n { rela-tmp } - \dbshow_date_set:nx { rela-tmp } { \seq_item:Nn \l_date_seq { ##1 } } - \dbshow_date_to_int:nN { rela-tmp } \l__dbshow_if_tmpb_int - \tl_put_right:Nx \l_dbshow_rela { \int_use:N \l__dbshow_if_tmpb_int } - } - \tl_put_right:Nx \l_dbshow_rela { - \seq_item:Nn \l_other_seq { \l__dbshow_if_tmpa_int + 1 } - } - \int_compare:nTF { \l_dbshow_rela } - { \dbshow_set_true: } - { \dbshow_set_false: } - } -} - -% #1 database name #2 cond name #3 index -\cs_set:Nn \dbshow_if:nnn { - \tl_set_eq:Nc \l_dbshow_attr { g__dbshow_filter_attr_#1_#2 } - \tl_set_eq:Nc \l_dbshow_rela { g__dbshow_filter_rela_#1_#2 } - \prop_get:cVN { g__dbshow_type_map_#1 } \l_dbshow_attr \l_tmp_type - \cs_set_eq:Nc \dbval { g__dbshow_data_#1_\l_dbshow_attr _#3 } - \cs_set:Nn \dbshow_set_true: - { \bool_gset_true:c { g__dbshow_filter_bool_#1_#2 } } - \cs_set:Nn \dbshow_set_false: - { \bool_gset_false:c { g__dbshow_filter_bool_#1_#2 } } - \bool_set_eq:Nc \l_star_bool { g__dbshow_cond_star_#1_#2 } - \use:c { dbshow_if_\l_tmp_type : } -} - -% 将cond->attr, cond->rela, cond->bool关联起来 -% #1 database name #2 cond name #3 attr #4 rela #5 star -\cs_new_protected:Nn \dbshow_new_conditional:nnnnn { - \tl_gset:cn { g__dbshow_filter_attr_#1_#2 } { #3 } - \tl_gset:cn { g__dbshow_filter_rela_#1_#2 } { #4 } - \bool_if_exist:cF { g__dbshow_filter_bool_#1_#2 } - { \bool_new:c { g__dbshow_filter_bool_#1_#2 } } - \bool_if_exist:cF { g__dbshow_cond_star_#1_#2 } - { \bool_new:c { g__dbshow_cond_star_#1_#2 } } - \IfBooleanTF { #5 } - { \bool_gset_true:c { g__dbshow_cond_star_#1_#2 } } - { \bool_gset_false:c { g__dbshow_cond_star_#1_#2 } } - \cs_gset:cn { g__dbshow_filter_cs_#1_#2:n } { - \dbshow_if:nnn { #1 } { #2 } { ##1 } - } - \seq_gput_right:cn { g__dbshow_cond_list_#1 } { #2 } -} - -% 将组合条件cond1, cond2, ..., 替换成cond1->bool, cond2->bool, ... -% #1 database name #2 filter name #3 filters -\cs_new_protected:Nn \dbshow_combine_conditional:nnn { - \tl_gset_eq:cN { g__dbshow_filter_bool_tl_#1_#2 } \c_true_bool - \seq_gclear_new:c { g__dbshow_filter_run_seq_#1_#2 } - \regex_extract_all:nnN { \w+ } { #3 } \l_tmpa_seq - \seq_map_inline:Nn \l_tmpa_seq { - % ##1 cond name - \seq_if_in:cnT { g__dbshow_cond_list_#1 } { ##1 } { - \seq_gput_right:cn { g__dbshow_filter_run_seq_#1_#2 } - { g__dbshow_filter_cs_#1_##1:n } - } - } - \tl_set:Nn \l_tmpa_tl { #3 } - \regex_replace_all:nnN - { \w+ } { \c{ g__dbshow_filter_bool_#1_\0 } } - \l_tmpa_tl - \tl_gset_eq:cN { g__dbshow_filter_bool_tl_#1_#2 } \l_tmpa_tl -} - -% #1 database #2 content -\NewDocumentEnvironment { dbFilters } { m +b } { - \seq_gclear_new:c { g__dbshow_cond_list_#1 } - % #1 star #2 cond name #3 attr #4 rela - \DeclareDocumentCommand { \dbNewConditional } { s m m m } { - \dbshow_new_conditional:nnnnn - { #1 } { ##2 } { ##3 } { ##4 } { ##1 } - } - % ##1 filter name ##2 filters ##3 info - \DeclareDocumentCommand { \dbCombineConditionals } { m m O{} } { - \tl_gset:cn { g__dbshow_filter_info_#1_##1 } { ##3 } - \dbshow_combine_conditional:nnn { #1 } { ##1 } { ##2 } - } - #2 -} { } - -% #1 name #2 points -\NewDocumentCommand { \dbNewReviewPoints } { m m } { - \clist_set:cn { g__review_points_#1 } { #2 } -} - -\cs_new:Nn \dbshow_identity:n { #1 } - -% #1 style name #2 database name #3 attr -\cs_new_protected:Nn \dbshow_new_attr_style:nnn { - \dbshow_check_attr:nn { #2 } { #3 } - \keys_define:nn { dbshow/style/#1/#3 } { - before-code .tl_gset:c = { g__dbshow_style_attr_before_#1_#2_#3 }, - before-code .initial:n = , - after-code .tl_gset:c = { g__dbshow_style_attr_after_#1_#2_#3 }, - after-code .initial:n = , - % for date and clist - sep .clist_gset:c = { g__dbshow_style_attr_sep_#1_#2_#3 }, - % only for clist - item-before-code .tl_gset:c = { g__dbshow_style_attr_item_before_#1_#2_#3 }, - item-before-code .initial:n = , - item-after-code .tl_gset:c = { g__dbshow_style_attr_item_after_#1_#2_#3 }, - item-after-code .initial:n = , - % only for date - zfill .bool_gset:c = { g__dbshow_style_attr_zfill_#1_#2_#3 }, - zfill .initial:n = true, - zfill .default:n = true, - wrapper .tl_gset:c = { g__dbshow_style_attr_wrapper_#1_#2_#3 }, - wrapper .initial:n = { \dbshow_identity:n }, - } - \str_case_e:nn { \prop_item:cn { g__dbshow_type_map_#2 } { #3 } } { - { clist } { \keys_set:nn { dbshow/style/#1/#3 } { sep = { { ,~ } } } } - { date } { \keys_set:nn { dbshow/style/#1/#3 } { sep = { { / } } } } - } -} - -\int_gzero_new:N \g__dbshow_raw_filter_int -% #1 style name #2 database name -\cs_new_protected:Nn \dbshow_new_database_style:nn { - \dbshow_check_database:n { #2 } - \keys_define:nn { dbshow/style/#1 } { - filter .tl_gset:c = { g__dbshow_filter_#1_#2 }, - filter .initial:n = -none-, - raw-filter .code:n = { - \int_gincr:N \g__dbshow_raw_filter_int - \str_set:Nx \l_tmpa_str { -raw\int_use:N \g__dbshow_raw_filter_int - } - \exp_args:NnV \tl_gset:cn { g__dbshow_filter_#1_#2 } \l_tmpa_str - \exp_args:NnV \dbshow_combine_conditional:nnn { #2 } \l_tmpa_str { ##1 } - }, - sort .clist_gset:c = { g__dbshow_sort_#1_#2 }, - before-code .tl_gset:c = { g__dbshow_style_before_#1_#2 }, - before-code .initial:n = , - item-code .tl_gset:c = { g__dbshow_style_database_item_#1_#2 }, - item-code .initial:n = , - after-code .tl_gset:c = { g__dbshow_style_after_#1_#2 }, - after-code .initial:n = , - record-before-code .tl_gset:c = { g__dbshow_style_record_before_#1_#2 }, - record-before-code .initial:n = , - record-after-code .tl_gset:c = { g__dbshow_style_record_after_#1_#2 }, - record-after-code .initial:n = , - } - \prop_map_inline:cn { g__dbshow_type_map_#2 } { - \dbshow_new_attr_style:nnn { #1 } { #2 } { ##1 } - } -} - -% #1 base style #2 style #3 database #4 opt -\NewDocumentCommand { \dbNewStyle } { o m m +m } { - \tl_gset:cn { g__dbshow_style_opts_#2_#3 } { #4, } - \IfValueT { #1 } { - \tl_gclear:N \g_tmpa_tl - \clist_map_inline:nn { #1 } { - \dbshow_check_style:nn { ##1 } { #3 } - \tl_if_exist:cT { g__dbshow_style_opts_##1_#3 } { - \tl_gconcat:ccc { g_tmpa_tl } - { g_tmpa_tl } { g__dbshow_style_opts_##1_#3 } - } - } - \tl_gconcat:ccc { g__dbshow_style_opts_#2_#3 } - { g_tmpa_tl } { g__dbshow_style_opts_#2_#3 } - } - \dbshow_new_database_style:nn { #2 } { #3 } - \exp_args:Nnv - \keys_set:nn { dbshow/style/#2 } { g__dbshow_style_opts_#2_#3 } -} - -\cs_new:Npn \dbshow_sort_parse_star:w #1* { - \tl_set:Nx \l_op_same { > } - \tl_set:Nx \l_op_swap { < } - \str_set:Nn \l_tmpa_str { #1 } -} - -% #1 database #2 index #3 style -\cs_new:Nn \dbshow_sort:nNn { - \int_set:Nn \l_tmpb_int { \clist_count:c { g__dbshow_sort_#3_#1 } } - \clist_sort:Nn #2 { - \int_zero:N \l_tmpa_int - \cs_set:Nn \dbshow_sort_single: { - \int_incr:N \l_tmpa_int - \str_set:Nx \l_tmpa_str % attr - { \clist_item:cn { g__dbshow_sort_#3_#1 } { \l_tmpa_int } } - \str_if_in:NnTF \l_tmpa_str { * } { - \exp_after:wN \dbshow_sort_parse_star:w \l_tmpa_str - } - { - \tl_set:Nx \l_op_same { < } - \tl_set:Nx \l_op_swap { > } - } - \exp_args:NnV \dbshow_check_attr:nn { #1 } \l_tmpa_str - - \prop_get:cVN { g__dbshow_type_map_#1 } \l_tmpa_str \l_tmp_type - \clist_if_in:nVF { str, int, date, fp } \l_tmp_type { - \msg_error:nnx { dbshow } { unsupported-sort-type } { \l_tmp_type } - } - - \str_if_eq:eeT { \l_tmp_type } { date } { - \str_set:Nn \l_tmp_type { str } - } - - \cs_set_eq:Nc \l_tmpa_tl { g__dbshow_data_#1_\l_tmpa_str _##1 } - \cs_set_eq:Nc \l_tmpb_tl { g__dbshow_data_#1_\l_tmpa_str _##2 } - \cs_set_eq:Nc \dbshow_compare { \l_tmp_type _compare:VNVTF } - - \dbshow_compare \l_tmpa_tl \l_op_same \l_tmpb_tl - { \sort_return_same: } - { - \dbshow_compare { \l_tmpa_tl } \l_op_swap { \l_tmpb_tl } - { \sort_return_swapped: } - { - \int_compare:nTF { \l_tmpa_int = \l_tmpb_int } - { \sort_return_same: } - { \dbshow_sort_single: } - } - } - } - \dbshow_sort_single: - } -} - -% #1 style #2 database #3 filter -\cs_new_protected:Nn \dbshow_init_iterator:nnn { - \tl_set:Nn \dbDatabase { #2 } - \tl_set:Nx \dbFilterName { #3 } - \tl_set_eq:Nc \dbFilterInfo { g__dbshow_filter_info_#2_#3 } - - \clist_clear_new:N \l_index - %% run filters - % ##1 index - \cs_set:Nn \dbshow_filter:n { - \seq_if_exist:cTF { g__dbshow_filter_run_seq_#2_#3 } { - \seq_map_inline:cn { g__dbshow_filter_run_seq_#2_#3 } { - \use:c { ####1 } { ##1 } - } - \exp_args:Nv - \bool_if:nT { g__dbshow_filter_bool_tl_#2_#3 } - { \clist_put_right:Nn \l_index { ##1 } } - } { \clist_put_right:Nn \l_index { ##1 } } - } - \int_step_function:nN { \dbshow_get_counter:n { #2 } } \dbshow_filter:n - \clist_if_empty:cF { g__dbshow_sort_#1_#2 } - { \dbshow_sort:nNn { #2 } \l_index { #1 } } - - % ##1 index - \int_zero_new:N \l_counter_int - \cs_set:Nn \dbshow_iter:n { - \int_incr:N \l_counter_int - \tl_set:Nx \dbalph { \int_to_alph:n { \l_counter_int } } - \tl_set:Nx \dbAlph { \int_to_Alph:n { \l_counter_int } } - \tl_set:Nx \dbarabic { \int_to_arabic:n { \l_counter_int } } - \tl_set:Nx \dbRoman { \int_to_Roman:n { \l_counter_int } } - \tl_set:Nx \dbroman { \int_to_roman:n { \l_counter_int } } - \tl_set:Nn \dbIndex { ##1 } - - % ####1 attr - \DeclareExpandableDocumentCommand { \dbuse } { m } { - \dbshow_check_attr:nn { #2 } { ####1 } - \tl_use:c { g__dbshow_style_attr_before_#1_#2_####1 } - \dbshow_use_data:nnnn { #2 } { ####1 } { ##1 } { #1 } - \tl_use:c { g__dbshow_style_attr_after_#1_#2_####1 } - } - \tl_use:c { g__dbshow_style_record_before_#1_#2 } - \tl_use:c { g__dbshow_style_database_item_#1_#2 } - \tl_use:c { g__dbshow_style_record_after_#1_#2 } - } - \prg_set_conditional:Nnn \dbshow_if_empty: { T, F, TF } { - \clist_if_empty:NTF \l_index - { \prg_return_true: } - { \prg_return_false: } - } - \cs_set_eq:NN \dbIfEmptyT\dbshow_if_empty:T - \cs_set_eq:NN \dbIfEmptyF\dbshow_if_empty:F - \cs_set_eq:NN \dbIfEmptyTF\dbshow_if_empty:TF - - \tl_use:c { g__dbshow_style_before_#1_#2 } - \clist_map_function:NN \l_index \dbshow_iter:n - \tl_use:c { g__dbshow_style_after_#1_#2 } -} - -% #1 style #2 database -\NewDocumentCommand { \dbshow } { m m } { - \dbshow_check_database:n { #2 } - \tl_set_eq:Nc \l_dbshow_filter { g__dbshow_filter_#1_#2 } - \exp_args:Nnv \dbshow_check_filter:nn - { #2 } { g__dbshow_filter_#1_#2 } - \exp_args:Nnnv \dbshow_init_iterator:nnn - { #1 } { #2 } { g__dbshow_filter_#1_#2 } -} - -\cs_set_eq:NN \dbIntAbs \int_abs:n -\cs_set_eq:NN \dbIntSign \int_sign:n -\cs_set_eq:NN \dbIntDivRound \int_div_round:nn -\cs_set_eq:NN \dbIntDivTruncate \int_div_truncate:nn -\cs_set_eq:NN \dbIntMax \int_max:nn -\cs_set_eq:NN \dbIntMin \int_min:nn -\cs_set_eq:NN \dbIntMod \int_mod:nn -\cs_set_eq:NN \dbFpSign \fp_sign:n - -%%%%%%%%%%%%%%%%% date - -% #1 year -\prg_new_conditional:Nnn \dbshow_date_if_leap:n { T, F, TF, p } { - \bool_if:nTF { - \int_compare_p:nNn { \int_mod:nn { #1 } { 400 } } = { 0 } || - ( - !\int_compare_p:nNn { \int_mod:nn { #1 } { 100 } } = { 0 } && - \int_compare_p:nNn { \int_mod:nn { #1 } { 4 } } = { 0 } - ) - } - { \prg_return_true: } - { \prg_return_false: } -} - -\clist_const:Nn \dbshow_date_month_clist - { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } - -\int_new:N \l__date_ans_int -\int_new:N \l__date_tmpa_int -\int_new:N \l__date_tmpb_int - -% #1 year #2 month #3 day #4 token to save the result -\cs_new_protected:Nn \dbshow_date_to_int:nnnN { - \int_set:Nn \l__date_ans_int { #3 - 1 } - \int_step_inline:nn { #2 - 1 } { - \int_add:Nn \l__date_ans_int { - \clist_item:Nn \dbshow_date_month_clist { ##1 } - } - \bool_if:nT { - \int_compare_p:nNn { ##1 } = { 2 } && - \dbshow_date_if_leap_p:n { #1 } - } { \int_incr:N \l__date_ans_int } - } - \int_add:Nn \l__date_ans_int { 365 * (#1 - 1971) } - \int_add:Nn \l__date_ans_int { - \int_div_truncate:nn { #1 - 1 } { 4 } - - \int_div_truncate:nn { 1971 } { 4 } - } - \int_sub:Nn \l__date_ans_int { - \int_div_truncate:nn { #1 - 1 } { 100 } - - \int_div_truncate:nn { 1971 } { 100 } - } - \int_add:Nn \l__date_ans_int { - \int_div_truncate:nn { #1 - 1 } { 400 } - - \int_div_truncate:nn { 1971 } { 400 } - } - \int_set_eq:NN #4 \l__date_ans_int -} - -\cs_new_protected:Nn \dbshow_date_to_int:NNNN { - \dbshow_date_to_int:nnnN { #1 } { #2 } { #3 } #4 -} -\cs_generate_variant:Nn \dbshow_date_to_int:NNNN { cccN } - -% #1 date #2 int -\cs_new:Nn \dbshow_date_to_int:nN { - \dbshow_date_to_int:cccN - { dbshow_date_year_#1 } - { dbshow_date_month_#1 } - { dbshow_date_day_#1 } - #2 -} - -\cs_new_protected:Nn \dbshow_date_set_val:n { - \tl_set:cx { #1 } { \dbshow_date_use_zfill:nn { #1 } { / } } -} -\cs_new_protected:Nn \dbshow_date_gset_val:n { - \tl_gset:cx { #1 } { \dbshow_date_use_zfill:nn { #1 } { / } } -} - -\cs_new_protected:Nn \dbshow_date_init:n { - \dbshow_date_set:nnnn { #1 } { 1971 } { 1 } { 1 } - \dbshow_date_set_val:n { #1 } -} -\cs_new_protected:Nn \dbshow_date_ginit:n { - \dbshow_date_gset:nnnn { #1 } { 1971 } { 1 } { 1 } - \dbshow_date_gset_val:n { #1 } -} - -\cs_new_protected:Nn \dbshow_date_new:n { - \int_new:c { dbshow_date_year_#1 } - \int_new:c { dbshow_date_month_#1 } - \int_new:c { dbshow_date_day_#1 } - \dbshow_date_ginit:n { #1 } -} - -\cs_new_protected:Nn \dbshow_date_clear_new:n { - \int_zero_new:c { dbshow_date_year_#1 } - \int_zero_new:c { dbshow_date_month_#1 } - \int_zero_new:c { dbshow_date_day_#1 } - \dbshow_date_init:n { #1 } -} - -\cs_new_protected:Nn \dbshow_date_gclear_new:n { - \int_gzero_new:c { dbshow_date_year_#1 } - \int_gzero_new:c { dbshow_date_month_#1 } - \int_gzero_new:c { dbshow_date_day_#1 } - \dbshow_date_ginit:n { #1 } -} - -% #1 name #2 year #3 month #4 day -\cs_new_protected:Nn \dbshow_date_set:nnnn { - \int_set:cn { dbshow_date_year_#1 } { #2 } - \int_set:cn { dbshow_date_month_#1 } { #3 } - \int_set:cn { dbshow_date_day_#1 } { #4 } - \dbshow_date_set_val:n { #1 } -} - -% #1 name #2 year #3 month #4 day -\cs_new_protected:Nn \dbshow_date_gset:nnnn { - \int_gset:cn { dbshow_date_year_#1 } { #2 } - \int_gset:cn { dbshow_date_month_#1 } { #3 } - \int_gset:cn { dbshow_date_day_#1 } { #4 } - \dbshow_date_gset_val:n { #1 } -} - -\cs_new_protected:Npn \dbshow_date_set:w #1\dbshow_sep#2/#3/#4\dbshow_stop { - \dbshow_date_clear_new:n { #1 } - \dbshow_date_set:nnnn { #1 } { #2 } { #3 } { #4 } -} -\cs_new_protected:Npn \dbshow_date_gset:w #1\dbshow_sep#2/#3/#4\dbshow_stop { - \dbshow_date_gclear_new:n { #1 } - \dbshow_date_gset:nnnn { #1 } { #2 } { #3 } { #4 } -} - -% #1 date name #2 date -\cs_new_protected:Nn \dbshow_date_set:nn { - \dbshow_date_set:w #1\dbshow_sep#2\dbshow_stop -} -\cs_generate_variant:Nn \dbshow_date_set:nn { nx } -\cs_new_protected:Nn \dbshow_date_gset:nn { - \dbshow_date_gset:w #1\dbshow_sep#2\dbshow_stop -} -\cs_generate_variant:Nn \dbshow_date_gset:nn { nx } - -% #1 date 1 #2 date 2 #3 int token -\cs_new_protected:Nn \dbshow_date_sub:nnN { - \dbshow_date_to_int:nN { #1 } \l__date_tmpa_int - \dbshow_date_to_int:nN { #2 } \l__date_tmpb_int - \int_set:Nn #3 { \l__date_tmpa_int - \l__date_tmpb_int } -} - -\cs_new:Nn \dbshow_date_show_two:N { - \int_compare:nNnTF { #1 } > { 9 } - { \int_use:N #1 } { 0\int_use:N #1 } -} -\cs_generate_variant:Nn \dbshow_date_show_two:N { c } - -\cs_new:Nn \dbshow_date_use:nnnnn { - #2\int_use:c { dbshow_date_year_#1 } - #3\int_use:c { dbshow_date_month_#1 } - #4\int_use:c { dbshow_date_day_#1 }#5 -} -\cs_generate_variant:Nn \dbshow_date_use:nnnnn { nffff } - -\cs_new:Nn \dbshow_date_use_zfill:nnnnn { - #2\int_use:c { dbshow_date_year_#1 } - #3\dbshow_date_show_two:c { dbshow_date_month_#1 } - #4\dbshow_date_show_two:c { dbshow_date_day_#1 }#5 -} -\cs_generate_variant:Nn \dbshow_date_use_zfill:nnnnn { nffff } - -\cs_new:Nn \dbshow_date_use:nn { - \dbshow_date_use:nnnnn { #1 } { } { #2 } { #2 } { } -} -\cs_generate_variant:Nn \dbshow_date_use:nn { nf } - -\cs_new:Nn \dbshow_date_use_zfill:nn { - \dbshow_date_use_zfill:nnnnn { #1 } { } { #2 } { #2 } { } -} -\cs_generate_variant:Nn \dbshow_date_use_zfill:nn { nf } - -\tl_set:Nx \dbtoday { - \int_use:N \c_sys_year_int/ - \int_use:N \c_sys_month_int/ - \int_use:N \c_sys_day_int -} - -\endinput diff --git a/macros/latex/contrib/esami/README b/macros/latex/contrib/esami/README index 0703530247..c81c86eb43 100644 --- a/macros/latex/contrib/esami/README +++ b/macros/latex/contrib/esami/README @@ -1,6 +1,6 @@ -The esami package v. 2.6 +The esami package v. 2.7 For generation of texts and solutions of exams in LaTeX -2021/10/11 +2022/01/11 File: README Author: Grazia Messineo and Salvatore Vassallo @@ -14,7 +14,7 @@ varying in random order, with closed or open answer, matching, problems, and so of each group are randomly scrambled across the exam and variants of each exercise are chosen randomly from a file which contains them all and. -Copyright: (C) 2008--2021 Grazia Messineo & Salvatore Vassallo +Copyright: (C) 2008--2022 Grazia Messineo & Salvatore Vassallo Licence: LPPL FILES IN DISTRIBUTION diff --git a/macros/latex/contrib/esami/VERSION b/macros/latex/contrib/esami/VERSION index 655ad0fa4f..d312737d7e 100644 --- a/macros/latex/contrib/esami/VERSION +++ b/macros/latex/contrib/esami/VERSION @@ -1 +1 @@ -VERSION 2.6 DATE=October 11, 2021 +VERSION 2.7 DATE=January 11, 2022 diff --git a/macros/latex/contrib/esami/doc/esami-doc-en.pdf b/macros/latex/contrib/esami/doc/esami-doc-en.pdf Binary files differindex 017a1b28d8..d7dddc90ab 100644 --- a/macros/latex/contrib/esami/doc/esami-doc-en.pdf +++ b/macros/latex/contrib/esami/doc/esami-doc-en.pdf diff --git a/macros/latex/contrib/esami/doc/esami-doc-en.tex b/macros/latex/contrib/esami/doc/esami-doc-en.tex index 33e51db7cd..05788c147f 100644 --- a/macros/latex/contrib/esami/doc/esami-doc-en.tex +++ b/macros/latex/contrib/esami/doc/esami-doc-en.tex @@ -20,6 +20,7 @@ \usepackage{fancyvrb} \usepackage[lmargin=3.5cm,rmargin=3.5cm]{geometry} \usepackage[colorlinks=true,pdftex,hyperindex=true]{hyperref} + \newcounter{esempio} \newsavebox{\fcolbox} %\newlength{\fcolwidth} \newenvironment{esempio} @@ -78,6 +79,7 @@ \changes{Version 2.4}{2018/02/10}{Documentation corrected. } \changes{Version 2.5}{2018/05/06}{Corrected a misprint in the code. Improved the selection of random exercises.} \changes{Version 2.6}{2021/10/11}{Improved the spacing in \cmd{\FPsignpol}. Corrected the code to avoid some spourios spaces. } +\changes{Version 2.7}{2022/01/11}{Improved the spacing in \cmd{\sempli} and \cmd{\FPsignpol}. Corrected a misprint in the code.} %\IndexPrologue{\section*{Index} Numbers written in italic refer to the page where the item is described; underlined numebers refer to the line of code in which the item is described; other references are to the line of code where the item is used.} \GlossaryPrologue{\section*{Changelog}} @@ -87,8 +89,8 @@ \fontshape\updefault \footnotesize} \GetFileInfo{esami.sty} -\def\fileversion{versione 2.6} -\def\filedate{2021/10/11} +\def\fileversion{versione 2.7} +\def\filedate{2022/01/11} \title{Package esami\thanks{This document @@ -122,7 +124,7 @@ Package \pkgname{esami} depends on some other non standard packages\footnote{The \end{enumerate} Moreover following packages are optional, but recommended: \begin{enumerate} - \item \pkgname{ifluatex} and \pkgname{ifxetex} to compile with \Hologo{XeLaTeX} and \Hologo{LuaLaTeX} (here below we will refer only to the compilation with \hologo{pdfLaTeX})\nuovo{vers. 2.0}\footnote{At the moment the support for \Hologo{XeLaTeX} and \Hologo{LuaLaTeX} is only partial and it is not possibile to use some type of exercises.}. + \item \pkgname{ifluatex} and \pkgname{ifxetex} to compile with \Hologo{XeLaTeX} and \Hologo{LuaLaTeX} (here below we will refer only to the compilation with \hologo{pdfLaTeX})\nuovo{vers. 2.0}\footnote{At the moment the use of package with \Hologo{XeLaTeX} and \Hologo{LuaLaTeX}has not completely been tested and it is possibile that some type of exercises do not work as expected.}. \item \pkgname{lmodern} and \pkgname{amsfonts}: useful for a good pdf output; \item \pkgname{numprint}: to have a better output and different formats for numbers, depending on language; %\item \pkgname{icomma}: from \pkgname{ws} package, for a correct format of commas; @@ -307,7 +309,7 @@ The environment \envname{esdb}\marg{nome db} defines a virtual database of exerc The environment generates a file \texttt{nome db.tex} which contains the references to all the exercises chosen. When the environment is closed, exercises are automatically written with the command \cmd{\esercizidb}\marg{nome db} (not to be written). If more than one environment \envname{esdb} is used, each one must be given a different name. -Also this environment is a modified version of a similar environment in \pkgname{probsoln} and, at the moment, does not work nor with \hologo{XeLaTeX} nor with \hologo{LuaLaTeX}. +Also this environment is a modified version of a similar environment in \pkgname{probsoln}. In the file of the exercises, in @@ -459,7 +461,7 @@ The optional parameter \meta{type} defines the way in which the blank space is d If the answer contains mathematical expressions, it must be written between \$\ even if the command \cmd{\fillin} is already contained in a mathematical environment. -This kind of exercise cannot be used, at the moment, with \Hologo{XeLaTeX} or \Hologo{LuaLaTeX}. +%This kind of exercise cannot be used, at the moment, with \Hologo{XeLaTeX} or \Hologo{LuaLaTeX}. \paragraph{domanda:}\DescribeEnv{domanda} (the word ``domanda'' means ``question'' in Italian) this environment must contain the text of the exercise (not the solution). It is used in \envname{problem} and \envname{problem*} and with the package option \optname{solutionsonly} only the solution of the exercise is printed and not the text. In previous versions of this package (not released to CTAN) there was another environment in order to obtain this. \paragraph{risposta:}\DescribeEnv{risposta} This environment generates a ruled or boxed space in which the student has to write the answer of an exercise (``risposta'' is the Italian word for ``answer''). @@ -507,7 +509,7 @@ The two lists are shuffled and then printed with the command \cmd{\matching}. \end{esempio} The solutions show the correct matching. -Also this kind of exercise does not work with \Hologo{XeLaTeX} or \Hologo{LuaLaTeX}. +%Also this kind of exercise does not work with \Hologo{XeLaTeX} or \Hologo{LuaLaTeX}. \paragraph{tabella:}\DescribeEnv{tabella} (the word ``tabella'' means ``table'' in Italian) it is used to create exercises with many short open answers in column. The syntax is (the \cs{cr} at the end of the line is necessary): @@ -521,7 +523,7 @@ The syntax is (the \cs{cr} at the end of the line is necessary): The first parameter (default 2) is the number of columns of the table visible in the text of the exercise. The last column is invisible in the text and visible in the solutions. The second parameter gives the alignment of the visible columns (the same for all the columns) and the third one the alignment of the hidden column. -This kind of exercise works with \Hologo{XeLaTeX}, but not with \Hologo{LuaLaTeX}. +%This kind of exercise works with \Hologo{XeLaTeX}, but not with \Hologo{LuaLaTeX}. \begin{esempio} With the code \begin{verbatim} @@ -793,6 +795,7 @@ Inside this file you should use only one command, \cmd{\def \textbackslash eserc \item[Version 2.4 (2018/02/10)] Documentation corrected. \item[Version 2.5 (2018/05/06)] Corrected a misprint in the code. Improved the selection of random exercises. \item[Version 2.6 (2021/10/11)] Improved the spacing in \cmd{\FPsignpol}. Corrected the code to avoid some spourios spaces. + \item[Version 2.7 (2021/10/11)] Improved the spacing in \cmd{\sempli} and \cmd{\FPsignpol}. Corrected a misprint in the code \end{description} \bibliographystyle{plain} diff --git a/macros/latex/contrib/esami/doc/esami-doc-it.pdf b/macros/latex/contrib/esami/doc/esami-doc-it.pdf Binary files differindex 8b32737ca2..b706c809d3 100644 --- a/macros/latex/contrib/esami/doc/esami-doc-it.pdf +++ b/macros/latex/contrib/esami/doc/esami-doc-it.pdf diff --git a/macros/latex/contrib/esami/doc/esami-doc-it.tex b/macros/latex/contrib/esami/doc/esami-doc-it.tex index d8e8363ee8..3ac7495edb 100644 --- a/macros/latex/contrib/esami/doc/esami-doc-it.tex +++ b/macros/latex/contrib/esami/doc/esami-doc-it.tex @@ -77,6 +77,7 @@ \changes{Versione 2.4}{2018/02/10}{Corretta la documentazione .} \changes{Versione 2.5}{2018/05/06}{Corretto un errore di battitura nel codice. Migliorata la scelta aleatoria degli esercizi.} \changes{Versione 2.6}{2021/10/11}{Migliorata la spaziatura in \cmd{\FPsignpol}. Corretto il codice per eliminare alcuni spazi spuri.} +\changes{Versione 2.7}{2022/01/11}{Migliorata la spaziatura in \cmd{\sempli} e \cmd{\FPsignpol}. Corretto un errore nel codice} %\IndexPrologue{\section*{Indice} I numeri scritti in italico rimandano alla pagina dove è descritto l'item; i numeri sottolineati rimandano alla riga di codice in cui l'item è descritto; le altre referenze sono alla riga di codice dove l'item è usato.} \GlossaryPrologue{\section*{Changelog}} @@ -86,8 +87,8 @@ \fontshape\updefault \footnotesize} \GetFileInfo{esami.sty} -\def\fileversion{versione 2.6} -\def\filedate{2021/10/11} +\def\fileversion{versione 2.7} +\def\filedate{2022/01/11} \title{Il pacchetto esami\thanks{Questo documento @@ -121,7 +122,7 @@ Il pacchetto \pkgname{esami} dipende da alcuni altri pacchetti non standard\foot \end{enumerate} Inoltre i seguenti pacchetti sono opzionali, ma raccomandati: \begin{enumerate} - \item \pkgname{ifluatex} e \pkgname{ifxetex} per la compilazione con \Hologo{XeLaTeX} e \Hologo{LuaLaTeX} (nel seguito si farà riferimento solo alla compilazione con \hologo{pdfLaTeX})\nuovo{vers. 2.0}\footnote{Al momento il supporto per \Hologo{XeLaTeX} e \Hologo{LuaLaTeX} è molto parziale e alcune tipologie di esercizio non sono utilizzabili.}. + \item \pkgname{ifluatex} e \pkgname{ifxetex} per la compilazione con \Hologo{XeLaTeX} e \Hologo{LuaLaTeX} (nel seguito si farà riferimento solo alla compilazione con \hologo{pdfLaTeX})\nuovo{vers. 2.0}\footnote{Al momento l'utilizzo del pacchetto con \Hologo{XeLaTeX} e \Hologo{LuaLaTeX} non è stato del tutto testato e alcune tipologie di esercizio potrebbero non essere utilizzabili.}. \item \pkgname{lmodern} and \pkgname{amsfonts}: necessari per un buon output in pdf; \item \pkgname{numprint}: per un output migliore dei numeri e per avere formati numerici diversi a seconda del linguaggio; \item \pkgname{eurosym}: per usare la valuta; @@ -316,7 +317,7 @@ L'ambiente \envname{esdb}\marg{nome db} definisce un database virtuale di eserci L'ambiente genera un file \texttt{nome db.tex} che contiene i riferimenti agli esercizi scelti. Alla chiusura dell'ambiente gli esercizi vengono mandati automaticamente in output mediante il comando \cmd{\esercizidb}\marg{nome db} (da non dare esplicitamente). Ovviamente se si usano più ambienti \envname{esdb} ad ognuno deve essere assegnato un nome diverso. -Anche questo ambiente è una versione modificata di un analogo ambiente presente nel pacchetto \pkgname{probsoln} e, al momento non funziona né con \hologo{XeLaTeX} né con \hologo{LuaLaTeX}. +Anche questo ambiente è una versione modificata di un analogo ambiente presente nel pacchetto \pkgname{probsoln}. Nel file degli esercizi, la sintassi da usare all'interno di \cmd{\newproblem} è la seguente: @@ -476,7 +477,7 @@ Se la risposta contiene espressioni matematiche, deve essere inserita esplicitam %All'interno del comando \cmd{\fillin} (nello spazio per la risposta) non è possibile usare i comandi \cmd{\sempli} o \cmd{\semplix} (si veda la sezione \ref{sec:comandi}). -Questo tipo di esercizio non può al momento essere usato né con \Hologo{XeLaTeX} né con \Hologo{LuaLaTeX} +%Questo tipo di esercizio non può al momento essere usato né con \Hologo{XeLaTeX} né con \Hologo{LuaLaTeX} \paragraph{domanda:}\DescribeEnv{problema} questo ambiente deve contenere il testo dell'esercizio (non le soluzioni). Viene usato negli ambienti \envname{problema} e \envname{problema*}, con l'opzione \optname{solutionsonly} non viene stampato il testo degli esercizi, ma solo la soluzione. Nelle versioni precedenti del pacchetto per lo stesso scopo veniva usato un altro ambiente. \paragraph{risposta:}\DescribeEnv{risposta} serve per creare, in esercizi a risposta aperta lunga, lo spazio per inserire la risposta in un box o su righe. @@ -521,7 +522,7 @@ L'elenco dei nomi (mischiati in ordine casuale su ciascuna colonna) viene visual \end{esempio} Nelle soluzioni viene invece visualizzato l'abbinamento corretto. -Anche questo esercizio non funziona né con \Hologo{XeLaTeX} né con \Hologo{LuaLaTeX}. +%Anche questo esercizio non funziona né con \Hologo{XeLaTeX} né con \Hologo{LuaLaTeX}. \paragraph{tabella:}\DescribeEnv{tabella} serve per creare esercizi con più risposte aperte incolonnate. La sintassi è @@ -534,7 +535,7 @@ La sintassi è Il primo parametro (il cui valore di default è 2) indica il numero di colonne della tabella il cui contenuto deve essere visibile anche nel testo dell'esercizio (e non solo nella soluzione), mentre è possibile avere solo una colonna il cui contenuto è invisibile nel testo, ma appare nella soluzione. Il secondo parametro consente di scegliere l'allineamento delle colonne il cui contenuto è sempre visibile e il terzo l'allineamento della colonna invisibile. Come per le domande a risposta chiusa, le risposte che contengono il carattere di tabulazione \&\ devono essere racchiuse tra parentesi graffe. -Questo tipo di esercizio funziona con \Hologo{XeLaTeX}, ma non con \Hologo{LuaLaTeX}. +%Questo tipo di esercizio funziona con \Hologo{XeLaTeX}, ma non con \Hologo{LuaLaTeX}. \begin{esempio} Con il codice \begin{verbatim} @@ -793,8 +794,9 @@ Al suo interno si deve usare un solo comando, \cmd{\def \textbackslash esercizio \item[Versione 2.2 (2017/07/01)] Introdotta la possibilità di avere due semi diversi per la scelta degli esercizi (\cmd{\semeex}) e per le permutazioni e scelta dei parametri (\cmd{\seme}): di default sono uguali. Leggermente modificato il comando \cmd{\estrai} così da poter essere usato per estrarre parametri numerici da una lista. Integrata la documentazione. \item[Versione 2.3 (2017/09/18)] Corretto un errore di battitura nel codice. \item[Versione 2.4 (2018/02/10)] Corretta la documentazione . - \item[Versione 2.5 (2018/05/06)] Corretto un errore di battitura nel codice. Migliorata la scelta aleatoria degli esercizi. - \item[Versione 2.6 (2021/10/11)] Migliorata la spaziatura in \cmd{\FPsignpol}. Corretto il codice per eliminare alcuni spazi spuri. + \item[Versione 2.5 (2018/05/06)] Corretto un errore di battitura nel codice. Migliorata la scelta aleatoria degli esercizi. + \item[Versione 2.6 (2021/10/11)] Migliorata la spaziatura in \cmd{\FPsignpol}. Corretto il codice per eliminare alcuni spazi spuri. + \item[Versione 2.7 (2022/01/11)] Migliorata la spaziatura in \cmd{\sempli} e \cmd{\FPsignpol}. Corretto un errore nel codice \end{description} diff --git a/macros/latex/contrib/esami/doc/examples/problem2-tabella.tex b/macros/latex/contrib/esami/doc/examples/problem2-tabella.tex index 8929d2c84d..efb14edddf 100644 --- a/macros/latex/contrib/esami/doc/examples/problem2-tabella.tex +++ b/macros/latex/contrib/esami/doc/examples/problem2-tabella.tex @@ -4,6 +4,7 @@ \begin{problem}[4] Solve the following equations: +\begin{center} \begin{tabella}[1]{l}{r} Equation & Solution \cr \hline @@ -15,6 +16,7 @@ $x^2+\FPsv{a-b}x-\FPsv{a*b}=0$& $x=-\a;\; x=\b$ \cr \hline $x^2-\FPsv{a-b}x-\FPsv{a*b}=0$& $x=\a;\; x=-\b $\cr \end{tabella} +\end{center} \end{problem} } @@ -22,6 +24,7 @@ $x^2-\FPsv{a-b}x-\FPsv{a*b}=0$& $x=\a;\; x=-\b $\cr \begin{problem}[5] Complete the following table of derivatives: +\begin{center} \begin{tabella}[1]{l}{r} Function & Derivative \cr \hline @@ -31,5 +34,6 @@ $f(x)=\sin x$ & $f'(x)=\cos x$\cr \hline $f(x)=\cos x $& $f'(x)=-\sin x$\cr \end{tabella} +\end{center} \end{problem} } diff --git a/macros/latex/contrib/esami/doc/examples/problem3-matching.tex b/macros/latex/contrib/esami/doc/examples/problem3-matching.tex index ede6dddc74..58bc22d4e8 100644 --- a/macros/latex/contrib/esami/doc/examples/problem3-matching.tex +++ b/macros/latex/contrib/esami/doc/examples/problem3-matching.tex @@ -21,12 +21,12 @@ \FPsetpar{c}{2}{4} \FPsetpar{k}{3}{5} $a=\a$, $b=\b$, $c=\c$ - + \pair{$\FPsv{k*a}:\a$}{$\k$} \pair{$\k^{\c}$}{$\FPsv{k^c}$} \pair{$\a \times \b$}{$\FPsv{a*b}$} - +\pair{$\a \times \b$}{$\FPsv{a*b}$} +\pair{$\a \times \b$}{$\FPsv{a*b}$} \matching - \end{problem} } diff --git a/macros/latex/contrib/esami/doc/examples/test2.tex b/macros/latex/contrib/esami/doc/examples/test2.tex index ff3f0dee60..d0f07b16b4 100644 --- a/macros/latex/contrib/esami/doc/examples/test2.tex +++ b/macros/latex/contrib/esami/doc/examples/test2.tex @@ -4,9 +4,8 @@ \FPsetpar{c}{2}{8} \item \PTs{1} exercise 2a $a=\a$, $b=\b$, $c=\c$ -seme=\seme -semeex=\semeex + \begin{answers}{1}\bChoices[random] \Ans1 answer 1 correct\eAns \Ans0 answer 2 wrong\eAns @@ -22,9 +21,7 @@ semeex=\semeex \item \PTs{1} exercise 2b $a=\a$, $b=\b$, $c=\c$ -seme=\seme -semeex=\semeex \begin{answers}{1}\bChoices[random] \Ans1 answer 1 correct\eAns \Ans0 answer 2 wrong\eAns @@ -41,9 +38,7 @@ semeex=\semeex \item \PTs{1} exercise 2c $a=\a$, $b=\b$, $c=\c$ -seme=\seme -semeex=\semeex \begin{answers}{1}\bChoices[random] \Ans1 answer 1 correct\eAns \Ans0 answer 2 wrong\eAns diff --git a/macros/latex/contrib/esami/doc/examples/testA-luatex-sol.pdf b/macros/latex/contrib/esami/doc/examples/testA-luatex-sol.pdf Binary files differindex 74b27a1343..69ba6afe98 100644 --- a/macros/latex/contrib/esami/doc/examples/testA-luatex-sol.pdf +++ b/macros/latex/contrib/esami/doc/examples/testA-luatex-sol.pdf diff --git a/macros/latex/contrib/esami/doc/examples/testA-luatex-sol.tex b/macros/latex/contrib/esami/doc/examples/testA-luatex-sol.tex new file mode 100644 index 0000000000..3c4a9444c8 --- /dev/null +++ b/macros/latex/contrib/esami/doc/examples/testA-luatex-sol.tex @@ -0,0 +1,124 @@ +\documentclass[a4paper,italian]{article} + \usepackage{luatextra} % also loads fixltx2e, fontspec, xunicode + \usepackage[utf8]{luainputenc} + +\usepackage[shuffle,xyz,pointsonright,solutions,quizsolutions,twocolumns]{esami}%%%%% TEMA + +% +=============================+ +% | DEFINITIONS | +% +=============================+ + +\def\examname{The name of the exam} +\def\numcompiti{4}%%% The number of the versions +\date{2022/01/22}%%% THE DATE IN THE FORMAT YYYY/M/D or D/M/YYYY +\def\Data{\longdate}%%% or \shortdate: the date in the heading +%\def\cartella{pop}%%% The folder where are the exercises: by default the current folder% +%\def\Acapo{\newpage} +\usepackage{babel} + +\renewcommand{\checkpoints}{ } % So we don't check if the total points of an exercise is correct + +\begin{document} +\testversioni +\pagestyle{esame} + +\whiledo{\thevers<\numcompiti}{\stepvers +% +=============================+ +% | THE SEED | +% +=============================+ + +%\FPeval\seme{round((\thenomefile+(3*\thevers)):0)} +%%% OR SOME OTHER LIKE +\FPeval\seme{round(\thenomefile*(\thevers)+1-trunc(\thenomefile*(\thevers)/(2^31-1):0)*(2^31-1):0)} +%\FPeval\seme{round(1+abs(\thenomefile/(\thevers)+sin(\thevers)*(\thevers)^(2)):0)} +%\FPeval\semeex{round(\thenomefile+1-trunc(\thenomefile/(2^31-1):0)*(2^31-1):0)} +\randomi=\seme + +\permuta +% +=============================+ +% | STUFF DEFINED IN CFG FILE | +% +=============================+ + +\testa%%% the heading +\istruzionii%%% some instructions + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\section*{Part One} + + +\begin{test}[15] + \textsc{some exercises from 2 files} + + +\begin{questions} +%\ifluatex +%\esercizi{ +%test14, +%test1, +%test4, +%test9 +%} +%\else\ifxetex +%\esercizi{ +%test14, +%test1, +%test4, +%test9 +%} +%\else + + + +\begin{esdb}{mydb} %% some exercises from 2 files + \selectrandomlyn{3}{test2} + \selectrandomlyn{2}{test3} + \end{esdb} + +\esercizi{ +test14, +test1, +test4, +test9, +test5-fillin +} + +\textsc{All the problems of a file} + + +\selectallproblems[random]{test11} +%\fi\fi + +\end{questions} + +\textsc{Some other questions}\\[5mm] + + +\begin{questions} %% a new set of questions +\esercizi{test12, +test13 +} +\end{questions} +\end{test} + +\newpage +\section*{Part two} +\istruzioniii%%% Some other instructions + +\esercizi{problem1} +\newpage +An example of matching question. + +\esercizi{problem3-matching} + +\newpage +An example of ``tabella'' question. + +\esercizi{problem2-tabella} +\closevers +\newpage % + % +\setcounter{page}{1} %%% dvi +} + +\end{document} diff --git a/macros/latex/contrib/esami/doc/examples/testA-luatex.pdf b/macros/latex/contrib/esami/doc/examples/testA-luatex.pdf Binary files differindex 73b4e342a4..01b466cb05 100644 --- a/macros/latex/contrib/esami/doc/examples/testA-luatex.pdf +++ b/macros/latex/contrib/esami/doc/examples/testA-luatex.pdf diff --git a/macros/latex/contrib/esami/doc/examples/testA-luatex.tex b/macros/latex/contrib/esami/doc/examples/testA-luatex.tex new file mode 100644 index 0000000000..4f66e66f3d --- /dev/null +++ b/macros/latex/contrib/esami/doc/examples/testA-luatex.tex @@ -0,0 +1,123 @@ +\documentclass[a4paper,italian]{article} + \usepackage{luatextra} % also loads fixltx2e, fontspec, xunicode + \usepackage[utf8]{luainputenc} +\usepackage[shuffle,xyz,pointsonright,nosolutions,noquizsolutions,twocolumns]{esami} + +% +=============================+ +% | DEFINITIONS | +% +=============================+ + +\def\examname{The name of the exam} +\def\numcompiti{4}%%% The number of the versions +\date{2022/01/22}%%% THE DATE IN THE FORMAT YYYY/M/D or D/M/YYYY +\def\Data{\longdate}%%% or \shortdate: the date in the heading +%\def\cartella{pop}%%% The folder where are the exercises: by default the current folder% +%\def\Acapo{\newpage} +\usepackage{babel} + +\renewcommand{\checkpoints}{ } % So we don't check if the total points of an exercise is correct + +\begin{document} +\testversioni +\pagestyle{esame} + +\whiledo{\thevers<\numcompiti}{\stepvers +% +=============================+ +% | THE SEED | +% +=============================+ + +%\FPeval\seme{round((\thenomefile+(3*\thevers)):0)} +%%% OR SOME OTHER LIKE +\FPeval\seme{round(\thenomefile*(\thevers)+1-trunc(\thenomefile*(\thevers)/(2^31-1):0)*(2^31-1):0)} +%\FPeval\seme{round(1+abs(\thenomefile/(\thevers)+sin(\thevers)*(\thevers)^(2)):0)} +%\FPeval\semeex{round(\thenomefile+1-trunc(\thenomefile/(2^31-1):0)*(2^31-1):0)} +\randomi=\seme + +\permuta +% +=============================+ +% | STUFF DEFINED IN CFG FILE | +% +=============================+ + +\testa%%% the heading +\istruzionii%%% some instructions + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\section*{Part One} + + +\begin{test}[15] + \textsc{some exercises from 2 files} + + +\begin{questions} +%\ifluatex +%\esercizi{ +%test14, +%test1, +%test4, +%test9 +%} +%\else\ifxetex +%\esercizi{ +%test14, +%test1, +%test4, +%test9 +%} +%\else + + + +\begin{esdb}{mydb} %% some exercises from 2 files + \selectrandomlyn{3}{test2} + \selectrandomlyn{2}{test3} + \end{esdb} + +\esercizi{ +test14, +test1, +test4, +test9, +test5-fillin +} + +\textsc{All the problems of a file} + + +\selectallproblems[random]{test11} +%\fi\fi + +\end{questions} + +\textsc{Some other questions}\\[5mm] + + +\begin{questions} %% a new set of questions +\esercizi{test12, +test13 +} +\end{questions} +\end{test} + +\newpage +\section*{Part two} +\istruzioniii%%% Some other instructions + +\esercizi{problem1} +\newpage +An example of matching question. + +\esercizi{problem3-matching} + +\newpage +An example of ``tabella'' question. + +\esercizi{problem2-tabella} +\closevers +\newpage % + % +\setcounter{page}{1} %%% dvi +} + +\end{document} diff --git a/macros/latex/contrib/esami/doc/examples/testA-sol.pdf b/macros/latex/contrib/esami/doc/examples/testA-sol.pdf Binary files differindex 4970190095..634f2950b0 100644 --- a/macros/latex/contrib/esami/doc/examples/testA-sol.pdf +++ b/macros/latex/contrib/esami/doc/examples/testA-sol.pdf diff --git a/macros/latex/contrib/esami/doc/examples/testA-sol.tex b/macros/latex/contrib/esami/doc/examples/testA-sol.tex index f0d8d42076..5302238910 100644 --- a/macros/latex/contrib/esami/doc/examples/testA-sol.tex +++ b/macros/latex/contrib/esami/doc/examples/testA-sol.tex @@ -5,14 +5,11 @@ %\usepackage[shuffle,xyz,pointsonright,nosolutions,noquizsolutions,twocolumns]{esami}%%%%% TEMA \ifluatex \usepackage{luatextra} % also loads fixltx2e, fontspec, xunicode - \usepackage{unicode-math} - \setmathfont{Latin Modern Math} \usepackage[utf8]{luainputenc} \else\ifxetex \usepackage{fixltx2e} \usepackage{fontspec} - \usepackage{unicode-math} - \XeTeXinputencoding utf8 + \XeTeXinputencoding utf8 \else \usepackage{fixltx2e} \usepackage[T1]{fontenc} @@ -27,12 +24,14 @@ \def\examname{The name of the exam} \def\numcompiti{4}%%% The number of the versions -\date{2014/07/22}%%% THE DATE IN THE FORMAT YYYY/M/D or D/M/YYYY +\date{2022/01/22}%%% THE DATE IN THE FORMAT YYYY/M/D or D/M/YYYY \def\Data{\longdate}%%% or \shortdate: the date in the heading %\def\cartella{pop}%%% The folder where are the exercises: by default the current folder% %\def\Acapo{\newpage} \usepackage{babel} +\renewcommand{\checkpoints}{ } % So we don't check if the total points of an exercise is correct + \begin{document} \testversioni \pagestyle{esame} @@ -46,7 +45,7 @@ %%% OR SOME OTHER LIKE \FPeval\seme{round(\thenomefile*(\thevers)+1-trunc(\thenomefile*(\thevers)/(2^31-1):0)*(2^31-1):0)} %\FPeval\seme{round(1+abs(\thenomefile/(\thevers)+sin(\thevers)*(\thevers)^(2)):0)} - +%\FPeval\semeex{round(\thenomefile+1-trunc(\thenomefile/(2^31-1):0)*(2^31-1):0)} \randomi=\seme \permuta @@ -62,7 +61,10 @@ \section*{Part One} -\begin{test}[18] +\begin{test}[15] + \textsc{some exercises from 2 files} + + \begin{questions} %\ifluatex %\esercizi{ @@ -79,39 +81,54 @@ %test9 %} %\else + + + \begin{esdb}{mydb} %% some exercises from 2 files \selectrandomlyn{3}{test2} \selectrandomlyn{2}{test3} \end{esdb} \esercizi{ -%prova-colombia, test14, test1, test4, test9, -test5-fillin, +test5-fillin } -%%% all the problems of a file + +\textsc{All the problems of a file} + + \selectallproblems[random]{test11} %\fi\fi \end{questions} -Some other questions\\[5mm] +\textsc{Some other questions}\\[5mm] -%\begin{questions} %% a new set of questions -%\esercizi{test12, -%test13 -%} -%\end{questions} +\begin{questions} %% a new set of questions +\esercizi{test12, +test13 +} +\end{questions} \end{test} +\newpage \section*{Part two} \istruzioniii%%% Some other instructions \esercizi{problem1} +\newpage +An example of matching question. + +\esercizi{problem3-matching} + +\newpage +An example of ``tabella'' question. + +\esercizi{problem2-tabella} \closevers \newpage % % diff --git a/macros/latex/contrib/esami/doc/examples/testA-xetex-sol.pdf b/macros/latex/contrib/esami/doc/examples/testA-xetex-sol.pdf Binary files differindex fc64643065..26b70dcc96 100644 --- a/macros/latex/contrib/esami/doc/examples/testA-xetex-sol.pdf +++ b/macros/latex/contrib/esami/doc/examples/testA-xetex-sol.pdf diff --git a/macros/latex/contrib/esami/doc/examples/testA-xetex-sol.sol.tex b/macros/latex/contrib/esami/doc/examples/testA-xetex-sol.sol.tex new file mode 100644 index 0000000000..00cc5e002c --- /dev/null +++ b/macros/latex/contrib/esami/doc/examples/testA-xetex-sol.sol.tex @@ -0,0 +1,84 @@ +\begin{minipage}{.33\textwidth}{\large\textbf{Soluzione\ Versione\ n. 1}} +\begin{enumerate} +\item\ref{e:1-file:test2-q:i} +\item\ref{e:1-file:test3-q:ii} +\item\ref{e:1-file:test2-q:ii} +\item\ref{e:1-file:test2-q:iii} +\item\ref{e:1-file:test3-q:i} +\item\ref{e:1-file:test1-q:i} +\item\ref{e:1-file:test9-q:ii} +\item\ref{e:1-file:test14-q:i} +\item\ref{e:1-file:test4-q:v} +\item \makeatletter \input{qftest5-fillinqiie1.parametri}\makeatother + \FPsv [2]{b/k} +\item\ref{e:1-file:test11-q:i} +\item\ref{e:1-file:test11-q:ii} +\par\end{enumerate}\vspace{3ex} +\begin{enumerate} +\item\ref{e:1-file:test12-q:i} +\item\ref{e:1-file:test13-q:ii} +\par\end{enumerate}\vspace{3ex} +\end{minipage} +\begin{minipage}{.33\textwidth}{\large\textbf{Soluzione\ Versione\ n. 2}} +\begin{enumerate} +\item\ref{e:2-file:test2-q:iii} +\item\ref{e:2-file:test3-q:i} +\item\ref{e:2-file:test2-q:ii} +\item\ref{e:2-file:test3-q:iv} +\item\ref{e:2-file:test2-q:i} +\item\ref{e:2-file:test1-q:ii} +\item \makeatletter \input{qftest5-fillinqiie2.parametri}\makeatother + \FPsv [2]{a/c} +\item\ref{e:2-file:test9-q:iii} +\item\ref{e:2-file:test14-q:i} +\item\ref{e:2-file:test4-q:ii} +\item\ref{e:2-file:test11-q:i} +\item\ref{e:2-file:test11-q:ii} +\par\end{enumerate}\vspace{3ex} +\begin{enumerate} +\item\ref{e:2-file:test13-q:iii} +\item\ref{e:2-file:test12-q:iii} +\par\end{enumerate}\vspace{3ex} +\end{minipage} +\begin{minipage}{.33\textwidth}{\large\textbf{Soluzione\ Versione\ n. 3}} +\begin{enumerate} +\item\ref{e:3-file:test2-q:iii} +\item\ref{e:3-file:test3-q:i} +\item\ref{e:3-file:test2-q:i} +\item\ref{e:3-file:test3-q:ii} +\item\ref{e:3-file:test2-q:ii} +\item\ref{e:3-file:test14-q:i} +\item \makeatletter \input{qftest5-fillinqiie3.parametri}\makeatother + \FPsv [2]{b/k} +\item\ref{e:3-file:test4-q:iii} +\item\ref{e:3-file:test1-q:i} +\item\ref{e:3-file:test9-q:iv} +\item\ref{e:3-file:test11-q:i} +\item\ref{e:3-file:test11-q:ii} +\par\end{enumerate}\vspace{3ex} +\begin{enumerate} +\item\ref{e:3-file:test12-q:i} +\item\ref{e:3-file:test13-q:iv} +\par\end{enumerate}\vspace{3ex} +\end{minipage} +\begin{minipage}{.33\textwidth}{\large\textbf{Soluzione\ Versione\ n. 4}} +\begin{enumerate} +\item\ref{e:4-file:test2-q:ii} +\item\ref{e:4-file:test2-q:i} +\item\ref{e:4-file:test3-q:i} +\item\ref{e:4-file:test3-q:ii} +\item\ref{e:4-file:test2-q:iii} +\item\ref{e:4-file:test4-q:v} +\item\ref{e:4-file:test9-q:iii} +\item\ref{e:4-file:test1-q:ii} +\item\ref{e:4-file:test14-q:i} +\item \makeatletter \input{qftest5-fillinqiie4.parametri}\makeatother + \FPsv [2]{a/c} +\item\ref{e:4-file:test11-q:i} +\item\ref{e:4-file:test11-q:ii} +\par\end{enumerate}\vspace{3ex} +\begin{enumerate} +\item\ref{e:4-file:test13-q:iii} +\item\ref{e:4-file:test12-q:iii} +\par\end{enumerate}\vspace{3ex} +\end{minipage} diff --git a/macros/latex/contrib/esami/doc/examples/testA-xetex-sol.tex b/macros/latex/contrib/esami/doc/examples/testA-xetex-sol.tex new file mode 100644 index 0000000000..3b57a2dbd6 --- /dev/null +++ b/macros/latex/contrib/esami/doc/examples/testA-xetex-sol.tex @@ -0,0 +1,124 @@ +\documentclass[a4paper,italian]{article} + \usepackage{fixltx2e} + \usepackage{fontspec} + \XeTeXinputencoding utf8 +\usepackage[shuffle,xyz,pointsonright,solutions,quizsolutions,twocolumns]{esami}%%%%% TEMA + +% +=============================+ +% | DEFINITIONS | +% +=============================+ + +\def\examname{The name of the exam} +\def\numcompiti{4}%%% The number of the versions +\date{2022/01/22}%%% THE DATE IN THE FORMAT YYYY/M/D or D/M/YYYY +\def\Data{\longdate}%%% or \shortdate: the date in the heading +%\def\cartella{pop}%%% The folder where are the exercises: by default the current folder% +%\def\Acapo{\newpage} +\usepackage{babel} + +\renewcommand{\checkpoints}{ } % So we don't check if the total points of an exercise is correct + +\begin{document} +\testversioni +\pagestyle{esame} + +\whiledo{\thevers<\numcompiti}{\stepvers +% +=============================+ +% | THE SEED | +% +=============================+ + +%\FPeval\seme{round((\thenomefile+(3*\thevers)):0)} +%%% OR SOME OTHER LIKE +\FPeval\seme{round(\thenomefile*(\thevers)+1-trunc(\thenomefile*(\thevers)/(2^31-1):0)*(2^31-1):0)} +%\FPeval\seme{round(1+abs(\thenomefile/(\thevers)+sin(\thevers)*(\thevers)^(2)):0)} +%\FPeval\semeex{round(\thenomefile+1-trunc(\thenomefile/(2^31-1):0)*(2^31-1):0)} +\randomi=\seme + +\permuta +% +=============================+ +% | STUFF DEFINED IN CFG FILE | +% +=============================+ + +\testa%%% the heading +\istruzionii%%% some instructions + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\section*{Part One} + + +\begin{test}[15] + \textsc{some exercises from 2 files} + + +\begin{questions} +%\ifluatex +%\esercizi{ +%test14, +%test1, +%test4, +%test9 +%} +%\else\ifxetex +%\esercizi{ +%test14, +%test1, +%test4, +%test9 +%} +%\else + + + +\begin{esdb}{mydb} %% some exercises from 2 files + \selectrandomlyn{3}{test2} + \selectrandomlyn{2}{test3} + \end{esdb} + +\esercizi{ +test14, +test1, +test4, +test9, +test5-fillin +} + +\textsc{All the problems of a file} + + +\selectallproblems[random]{test11} +%\fi\fi + +\end{questions} + +\textsc{Some other questions}\\[5mm] + + +\begin{questions} %% a new set of questions +\esercizi{test12, +test13 +} +\end{questions} +\end{test} + +\newpage +\section*{Part two} +\istruzioniii%%% Some other instructions + +\esercizi{problem1} +\newpage +An example of matching question. + +\esercizi{problem3-matching} + +\newpage +An example of ``tabella'' question. + +\esercizi{problem2-tabella} +\closevers +\newpage % + % +\setcounter{page}{1} %%% dvi +} + +\end{document} diff --git a/macros/latex/contrib/esami/doc/examples/testA-xetex.pdf b/macros/latex/contrib/esami/doc/examples/testA-xetex.pdf Binary files differindex 30aad4bfd9..024e322ab1 100644 --- a/macros/latex/contrib/esami/doc/examples/testA-xetex.pdf +++ b/macros/latex/contrib/esami/doc/examples/testA-xetex.pdf diff --git a/macros/latex/contrib/esami/doc/examples/testA-xetex.tex b/macros/latex/contrib/esami/doc/examples/testA-xetex.tex new file mode 100644 index 0000000000..7a6cf40946 --- /dev/null +++ b/macros/latex/contrib/esami/doc/examples/testA-xetex.tex @@ -0,0 +1,124 @@ +\documentclass[a4paper,italian]{article} + \usepackage{fixltx2e} + \usepackage{fontspec} + \XeTeXinputencoding utf8 +\usepackage[shuffle,xyz,pointsonright,nosolutions,noquizsolutions,twocolumns]{esami} + +% +=============================+ +% | DEFINITIONS | +% +=============================+ + +\def\examname{The name of the exam} +\def\numcompiti{4}%%% The number of the versions +\date{2022/01/22}%%% THE DATE IN THE FORMAT YYYY/M/D or D/M/YYYY +\def\Data{\longdate}%%% or \shortdate: the date in the heading +%\def\cartella{pop}%%% The folder where are the exercises: by default the current folder% +%\def\Acapo{\newpage} +\usepackage{babel} + +\renewcommand{\checkpoints}{ } % So we don't check if the total points of an exercise is correct + +\begin{document} +\testversioni +\pagestyle{esame} + +\whiledo{\thevers<\numcompiti}{\stepvers +% +=============================+ +% | THE SEED | +% +=============================+ + +%\FPeval\seme{round((\thenomefile+(3*\thevers)):0)} +%%% OR SOME OTHER LIKE +\FPeval\seme{round(\thenomefile*(\thevers)+1-trunc(\thenomefile*(\thevers)/(2^31-1):0)*(2^31-1):0)} +%\FPeval\seme{round(1+abs(\thenomefile/(\thevers)+sin(\thevers)*(\thevers)^(2)):0)} +%\FPeval\semeex{round(\thenomefile+1-trunc(\thenomefile/(2^31-1):0)*(2^31-1):0)} +\randomi=\seme + +\permuta +% +=============================+ +% | STUFF DEFINED IN CFG FILE | +% +=============================+ + +\testa%%% the heading +\istruzionii%%% some instructions + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\section*{Part One} + + +\begin{test}[15] + \textsc{some exercises from 2 files} + + +\begin{questions} +%\ifluatex +%\esercizi{ +%test14, +%test1, +%test4, +%test9 +%} +%\else\ifxetex +%\esercizi{ +%test14, +%test1, +%test4, +%test9 +%} +%\else + + + +\begin{esdb}{mydb} %% some exercises from 2 files + \selectrandomlyn{3}{test2} + \selectrandomlyn{2}{test3} + \end{esdb} + +\esercizi{ +test14, +test1, +test4, +test9, +test5-fillin +} + +\textsc{All the problems of a file} + + +\selectallproblems[random]{test11} +%\fi\fi + +\end{questions} + +\textsc{Some other questions}\\[5mm] + + +\begin{questions} %% a new set of questions +\esercizi{test12, +test13 +} +\end{questions} +\end{test} + +\newpage +\section*{Part two} +\istruzioniii%%% Some other instructions + +\esercizi{problem1} +\newpage +An example of matching question. + +\esercizi{problem3-matching} + +\newpage +An example of ``tabella'' question. + +\esercizi{problem2-tabella} +\closevers +\newpage % + % +\setcounter{page}{1} %%% dvi +} + +\end{document} diff --git a/macros/latex/contrib/esami/doc/examples/testA.pdf b/macros/latex/contrib/esami/doc/examples/testA.pdf Binary files differindex 16f1ca17ab..78f7234f83 100644 --- a/macros/latex/contrib/esami/doc/examples/testA.pdf +++ b/macros/latex/contrib/esami/doc/examples/testA.pdf diff --git a/macros/latex/contrib/esami/doc/examples/testA.tex b/macros/latex/contrib/esami/doc/examples/testA.tex index b468611935..0a443d7518 100644 --- a/macros/latex/contrib/esami/doc/examples/testA.tex +++ b/macros/latex/contrib/esami/doc/examples/testA.tex @@ -1,25 +1,21 @@ \documentclass[a4paper,italian]{article} -\usepackage{ifxetex}%%NUOVO -\usepackage{ifluatex}%%%NUOVO +\usepackage{ifxetex} +\usepackage{ifluatex} -%\usepackage[shuffle,xyz,pointsonright,nosolutions,noquizsolutions,twocolumns]{esami}%%%%% TEMA \ifluatex \usepackage{luatextra} % also loads fixltx2e, fontspec, xunicode - \usepackage{unicode-math} - \setmathfont{Latin Modern Math} \usepackage[utf8]{luainputenc} \else\ifxetex \usepackage{fixltx2e} \usepackage{fontspec} - \usepackage{unicode-math} - \XeTeXinputencoding utf8 + \XeTeXinputencoding utf8 \else \usepackage{fixltx2e} \usepackage[T1]{fontenc} \usepackage[utf8]{inputenc} \usepackage{lmodern,textcomp} \fi\fi -\usepackage[shuffle,xyz,pointsonright,nosolutions,noquizsolutions,twocolumns]{esami}%%%%% TEMA +\usepackage[shuffle,xyz,pointsonright,nosolutions,noquizsolutions,twocolumns]{esami} % +=============================+ % | DEFINITIONS | @@ -27,12 +23,14 @@ \def\examname{The name of the exam} \def\numcompiti{4}%%% The number of the versions -\date{2014/07/22}%%% THE DATE IN THE FORMAT YYYY/M/D or D/M/YYYY +\date{2022/01/22}%%% THE DATE IN THE FORMAT YYYY/M/D or D/M/YYYY \def\Data{\longdate}%%% or \shortdate: the date in the heading %\def\cartella{pop}%%% The folder where are the exercises: by default the current folder% %\def\Acapo{\newpage} \usepackage{babel} +\renewcommand{\checkpoints}{ } % So we don't check if the total points of an exercise is correct + \begin{document} \testversioni \pagestyle{esame} @@ -63,6 +61,9 @@ \begin{test}[15] + \textsc{some exercises from 2 files} + + \begin{questions} %\ifluatex %\esercizi{ @@ -79,39 +80,54 @@ %test9 %} %\else + + + \begin{esdb}{mydb} %% some exercises from 2 files \selectrandomlyn{3}{test2} \selectrandomlyn{2}{test3} \end{esdb} \esercizi{ -%prova-colombia, test14, test1, test4, test9, -test5-fillin, +test5-fillin } -%%% all the problems of a file + +\textsc{All the problems of a file} + + \selectallproblems[random]{test11} %\fi\fi \end{questions} -Some other questions\\[5mm] +\textsc{Some other questions}\\[5mm] -%\begin{questions} %% a new set of questions -%\esercizi{test12, -%test13 -%} -%\end{questions} +\begin{questions} %% a new set of questions +\esercizi{test12, +test13 +} +\end{questions} \end{test} +\newpage \section*{Part two} \istruzioniii%%% Some other instructions \esercizi{problem1} +\newpage +An example of matching question. + +\esercizi{problem3-matching} + +\newpage +An example of ``tabella'' question. + +\esercizi{problem2-tabella} \closevers \newpage % % diff --git a/macros/latex/contrib/esami/esami-xyz.cfg b/macros/latex/contrib/esami/esami-xyz.cfg index 0d76641979..13484158d2 100644 --- a/macros/latex/contrib/esami/esami-xyz.cfg +++ b/macros/latex/contrib/esami/esami-xyz.cfg @@ -1,11 +1,11 @@ %% Package `esami' to use with LaTeX 2e -%% Copyright (C) 2008-2021 G. Messineo e S. Vassallo +%% Copyright (C) 2008-2022 G. Messineo e S. Vassallo %% %% This is file `esami-xyz.cfg', %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% esami-xyz.cfg, 2021-10-11 %% -%% Copyright (C) 2008-2021 G. Messineo e S. Vassallo %% +%% esami-xyz.cfg, 2022-01-11 %% +%% Copyright (C) 2008-2022 G. Messineo e S. Vassallo %% %% %% %% This program can be redistributed and/or modified %% %% under the terms of the LaTeX Project Public License %% diff --git a/macros/latex/contrib/esami/esami.sty b/macros/latex/contrib/esami/esami.sty index 668bef7606..2968a0d60d 100644 --- a/macros/latex/contrib/esami/esami.sty +++ b/macros/latex/contrib/esami/esami.sty @@ -2,8 +2,8 @@ %% This is file `esami.sty', %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% esami.sty package, 2021-10-11 %% -%% Copyright (C) 2008-2021 G. Messineo e S. Vassallo %% +%% esami.sty package, 2022-01-11 %% +%% Copyright (C) 2008-2022 G. Messineo e S. Vassallo %% %% %% %% This program can be redistributed and/or modified %% %% under the terms of the LaTeX Project Public License %% @@ -47,10 +47,14 @@ %Corrected a misprint in the code. Improved the selection of random exercises. % Version 2.6 % 2021/10/11 -%Corrected a misprint in the code. Improved the selection of random exercises. +%Improved the spacing in \cmd{\FPsignpol}. Corrected the code to avoid some spourios spaces. +% Version 2.7 +% 2022/01/11 +%Improved the spacing in \cmd{\sempli} and \cmd{\FPsignpol}. Corrected a misprint in the code. +% \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{esami} - [2021/10/11 v2.6 An Exam Construction Package] + [2022/01/11 v2.7 An Exam Construction Package] % +=============================+ % | THE OPTIONS | @@ -428,7 +432,7 @@ } \FPeval\fp@num{round((\fp@n/\fp@restoold):0)}% \FPeval\fp@den{round((\fp@d/\fp@restoold):0)}% - \FPifneg\segnofrac{-} + \FPifneg\segnofrac{-\:} \else{} \fi \ifthenelse{\fp@den=1}{% @@ -547,26 +551,44 @@ %========================================================% \newcommand{\FPsignpol}[2] %%% adapted from code contributed by Hjalmar Basile NEW 2016/04/11 +%{\FPval\tempsign{#1} + %\ifthenelse{\equal{#2}{}} + %{% + %\ifnum \tempsign<0 {\:\sempli{\tempsign}{1}#2} + %\else + %\ifnum \tempsign>0{\:+\:\sempli{\tempsign}{1}#2} + %\else{} + %\fi + %\fi + %} + %{% + %\ifnum \tempsign<0 {\:\semplix{\tempsign}{1}#2\:} + %\else + %\ifnum \tempsign>0{\:+\:\semplix{\tempsign}{1}#2} + %\else{} + %\fi + %\fi + %} +%} %% improved for spacing 2021/10/11 {\FPval\tempsign{#1} \ifthenelse{\equal{#2}{}} {% \ifnum \tempsign<0 {\:\sempli{\tempsign}{1}#2} \else - \ifnum \tempsign>0{\:+\:\sempli{\tempsign}{1}#2} - \else{} - \fi + \ifnum \tempsign>0{+\:\sempli{\tempsign}{1}#2} + \else{} + \fi \fi } {% \ifnum \tempsign<0 {\:\semplix{\tempsign}{1}#2\:} \else - \ifnum \tempsign>0{\:+\:\semplix{\tempsign}{1}#2} - \else{} - \fi + \ifnum \tempsign>0{\:+\:\semplix{\tempsign}{1}#2} + \else{} + \fi \fi } -} %% improved for spacing 2021/10/11 - +} %% improved for spacing 2021/10/11 %========================================================% % Commands adapted from exerquiz % @@ -926,9 +948,13 @@ \addtocounter{match@plo}{1} \expandafter\edef\csname match@numi\number\i@sh\endcsname{(\Alph{match@plu})} \vspace{2ex} + \begin{tabular}{p{.05\textwidth}p{.40\textwidth}p{.01\textwidth}p{.40\textwidth}} - \underbar{\makebox[.5cm]{\match@ans@color{\csname match@numi\number\i@sh\endcsname}}} & \csname match@qsti\number\i@sh\endcsname&&(\Alph{match@plo})\hspace{3mm}\csname match@ansi\number\i@sh\endcsname%\tabularnewline - \end{tabular} + \underbar{\makebox[.5cm]{\match@ans@color{\csname match@numi\number\i@sh\endcsname}}} & \csname match@qsti\number\i@sh\endcsname&&(\Alph{match@plo})\hspace{3mm}\csname match@ansi\number\i@sh\endcsname%\tabularnewline + \end{tabular} + %% ADD next line + % \vspace{2ex} \\ + %% \advance\i@sh by-1 \ifnum\i@sh > 0 \fi \fi diff --git a/macros/latex/contrib/pdfmanagement-testphase/CHANGELOG.md b/macros/latex/contrib/pdfmanagement-testphase/CHANGELOG.md index 62ad8aee74..ec1686c578 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/CHANGELOG.md +++ b/macros/latex/contrib/pdfmanagement-testphase/CHANGELOG.md @@ -5,6 +5,33 @@ first release 0.95a, 2021-02-23 will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), this project uses date-based 'snapshot' version identifiers. +## [Unreleased] + +## [2022-01-13] +### Changed + - the keys `firstaidoff` and `pdfmanagement` should now be set with the `debug` key. + - `testphase` will now load files from the latex-lab bundle. This requires a current + latex-dev: LaTeX2e <2022-06-01> pre-release-1. + - new values for `testphase`: `phase-I` and `phase-II`. + `phase-I` will loaded tagpdf and activate tagging and interword spaces, `phase-II will + additionally activate paratagging. The value `tagpdf` for the `testphase` + key has been deprecated. It will not error for some time and has been aliased to + `phase-II`, but it is recommended to use the new values `phase-I` and `phase-II` instead. + - renamed `\DeclareDocumentMetadata` to `\DocumentMetadata` (the older version is still provided) + to follow the development in latex-dev. + +### Fixed + + - adapted the file hooks to the changes in LaTeX + - small bugs + +### Removed + + - the `activate` key has been removed, its function is integrated in the testphase key. + +### Added + - preliminary support for structure destination to prepare for binary changes in texlive 2022 + ## [2021-08-28] ### Changed - colorscheme 'original' has been renamed to 'primary-colors' diff --git a/macros/latex/contrib/pdfmanagement-testphase/README.md b/macros/latex/contrib/pdfmanagement-testphase/README.md index a438100385..e08a4162ff 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/README.md +++ b/macros/latex/contrib/pdfmanagement-testphase/README.md @@ -1,6 +1,6 @@ # LaTeX PDF management testphase bundle -Version: 0.95i, 2021-08-28 +Version: 0.95j, 2022-01-13 This package is used during a test phase to load the new PDF management code of LaTeX. @@ -31,7 +31,7 @@ For manual installation: unpack by compiling the .ins, then move all ## Copyright (C) -* 2021 The LaTeX Project +* 2021-2022 The LaTeX Project ## License LaTeX Project Public License, version 1.3c or later. diff --git a/macros/latex/contrib/pdfmanagement-testphase/color-ltx.sty b/macros/latex/contrib/pdfmanagement-testphase/color-ltx.sty index 94d5f5c395..9ea89b54e1 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/color-ltx.sty +++ b/macros/latex/contrib/pdfmanagement-testphase/color-ltx.sty @@ -22,7 +22,7 @@ %% This file has the LPPL maintenance status "maintained". %% \NeedsTeXFormat{LaTeX2e}[1995/12/01] -\ProvidesPackage{color-ltx}[2021-08-28 v0.95i +\ProvidesPackage{color-ltx}[2022-01-13 v0.95j Standard LaTeX Color (patched for l3color, part of pdfmanagement-testphase, original version 2021/03/07 v1.2e) (DPC)] \edef\Gin@codes{% \catcode`\noexpand\^^A\the\catcode`\^^A\relax diff --git a/macros/latex/contrib/pdfmanagement-testphase/hyperref-generic.dtx b/macros/latex/contrib/pdfmanagement-testphase/hyperref-generic.dtx index 24f129b8ff..cc8ab85ef5 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/hyperref-generic.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/hyperref-generic.dtx @@ -2,7 +2,7 @@ % %% File: hyperref-generic.dtx % -% Copyright (C) 2021 The LaTeX Project +% Copyright (C) 2021-2022 The LaTeX Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -26,7 +26,7 @@ % %<*driver> \RequirePackage{pdfmanagement-testphase} -\DeclareDocumentMetadata{pdfstandard=A-2b} +\DocumentMetadata{pdfstandard=A-2b} \makeatletter \declare@file@substitution{doc.sty}{doc-v3beta.sty} \makeatother @@ -86,7 +86,7 @@ % }^^A % } % -% \date{Version 0.95i, released 2021-08-28} +% \date{Version 0.95j, released 2022-01-13} % % \maketitle % \begin{documentation} @@ -104,7 +104,7 @@ % should start like this % \begin{verbatim} % \RequirePackage{pdfmanagement-testphase} %loads the code -% \DeclareDocumentMetadata % activates it +% \DocumentMetadata % activates it % { % %% options % %% e.g. pdf version, backend: @@ -113,6 +113,18 @@ % } % \end{verbatim} % +% Starting with \LaTeX-2022-06-01 (or a suitable latex-dev) loading the testphase +% package is no longer required and this can be simplified to +% \begin{verbatim} +% \DocumentMetadata +% { +% %% options +% %% e.g. pdf version, backend: +% % pdfversion=1.7, +% % backend = dvipdfmx +% } +% \end{verbatim} + % The new driver tries to be compatible with the standard \pkg{hyperref} drivers % but there are nevertheless differences. Some of them due to the still experimental % status of the driver, others are design decisions: one part of the project is @@ -201,10 +213,9 @@ % If the key hasn't be set, the result is empty. This gives external % packages a public and reliable access to the data. % -% \item |pdflang| is deprecated. Instead \cs{DeclareDocumentMetadata} -% should be used: +% \item |pdflang| is deprecated. Instead \cs{DocumentMetadata} should be used: % \begin{verbatim} -% \DeclareDocumentMetadata{lang=de-DE} +% \cs{DocumentMetadata}{lang=de-DE} % \end{verbatim} % % The value can be retrieved as |document/lang|. @@ -626,7 +637,7 @@ % \section{Dropped options} % A number of options are ignored by this driver % \begin{description} -% \item[pdfversion] The pdfversion should be set in \cs{DeclareDocumentMetadata} +% \item[pdfversion] The pdfversion should be set in \cs{DocumentMetadata} % \item[setpagesize] The key is ignored and the PDF page size is not % set. Load \pkg{color} or \pkg{graphicx} or use a class which sets the PDF page size. % \item[breaklinks] The option does nothing sensible anyway (apart from triggering @@ -636,9 +647,9 @@ % \item[pdfa] If this option is set to true \pkg{hyperref} normally checks and sets % a small number of requirements for the PDF standard PDF/A. % The key is ignored with this driver. Instead the wanted standard should be declared -% in \cs{DeclareDocumentMetadata}: +% in \cs{DocumentMetadata}: % \begin{verbatim} -% \DeclareDocumentMetadata{pdfstandard=A-2b} +% \DocumentMetadata{pdfstandard=A-2b} % \end{verbatim} % Currently |A-1b|, |A-2b|, |A-3b| can be set. % The support for various requirements is still incomplete, but the parts that @@ -882,7 +893,7 @@ % the setting is global (and has to be done in the preamble). % % \DescribeHypkey{pdflang} The key will work, but it is recommended to the set -% the language in \cs{DeclareDocumentMetadata} instead. +% the language in \cs{DocumentMetadata} instead. %^^A %% This is an adapted version of hluatex.def %^^A %% meant to test the use of the commands %^^A %% from pdfmanagement.sty @@ -951,7 +962,7 @@ %<@@=hyp> % \end{macrocode} % \begin{macrocode} -\ProvidesFile{hgeneric-testphase.def}[2021-08-28 v0.95i % +\ProvidesFile{hgeneric-testphase.def}[2022-01-13 v0.95j % generic Hyperref driver for the LaTeX PDF management testphase bundle] \RequirePackage{etoolbox} %why? @@ -971,31 +982,45 @@ % \end{macrocode} % At first a message for the testing of the resource management % \begin{macrocode} -\msg_new:nnnn - { hyp } - { missing-resource-management } - { The~PDF~resource~management~is~required~for~this~hyperref~driver! } +\cs_if_exist:NTF \DocumentMetadata { - Activate~it~with \\ - \tl_to_str:n{\RequirePackage{pdfmanagement-testphase}}\\ - \tl_to_str:n{\DeclareDocumentMetadata{<options>}}\\ - before~\tl_to_str:n{\documentclass} + \msg_new:nnnn + { hyp } + { missing-resource-management } + { The~PDF~resource~management~is~required~for~this~hyperref~driver! } + { + Activate~it~with \\ + \tl_to_str:n{\DocumentMetadata{<options>}}\\ + before~\tl_to_str:n{\documentclass} + } } + { + \msg_new:nnnn + { hyp } + { missing-resource-management } + { The~PDF~resource~management~is~required~for~this~hyperref~driver! } + { + Activate~it~with \\ + \tl_to_str:n{\RequirePackage{pdfmanagement-testphase}}\\ + \tl_to_str:n{\DocumentMetadata{<options>}}\\ + before~\tl_to_str:n{\documentclass} + } + } % \end{macrocode} -% The pdfversion should be set in \cs{DeclareDocumentMetadata} +% The pdfversion should be set in \cs{DocumentMetadata} % \begin{macrocode} \msg_new:nnnn { hyp } { pdfversion-disabled } { This~hyperref~driver~ignores~the~pdfversion~key!\\ - Set~the~pdfversion~in~\token_to_str:N \DeclareDocumentMetadata + Set~the~pdfversion~in~\token_to_str:N \DocumentMetadata } { For example:\\ \tl_to_str:n { - \DeclareDocumentMetadata { pdfversion=1.7 } + \DocumentMetadata { pdfversion=1.7 } } } % \end{macrocode} @@ -1148,8 +1173,10 @@ %\cs_set_protected:Npn \PDF@SetupDoc{} %\\PDF@FinishDoc{}% dummy needed for hyperref ... % \end{macrocode} +% \begin{function}{\hypercalcbp} +% We define a better (expandable) version of \cs{hypercalcbp} +% \end{function} % \begin{macro}[EXP]{\hypercalcbp} -% We define a better (expandable) version of \cs{hypercalcbp} % \begin{macrocode} \cs_set_eq:NN \hypercalcbp \dim_to_decimal_in_bp:n % \end{macrocode} @@ -1163,7 +1190,7 @@ \def\Hy@numberline#1{#1\c_space_tl} %needed by bookmark % \end{macrocode} % -% The pdfversion should be set in \cs{DeclareDocumentMetadata} but we must +% The pdfversion should be set in \cs{DocumentMetadata} but we must % copy it to the \pkg{hyperref} command: % \begin{macrocode} \cs_set_eq:NN \Hy@pdfminorversion \pdf_version_minor: @@ -1493,7 +1520,7 @@ % TODO We overwrite the color key here for now, but this should be moved to bookmark % % \begin{macrocode} -\AddToHook { package / after / bookmark} +\AddToHook { package/bookmark/after} { \define@key{BKM}{color} { diff --git a/macros/latex/contrib/pdfmanagement-testphase/hyperref-generic.pdf b/macros/latex/contrib/pdfmanagement-testphase/hyperref-generic.pdf Binary files differindex 8066c863d6..578272d238 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/hyperref-generic.pdf +++ b/macros/latex/contrib/pdfmanagement-testphase/hyperref-generic.pdf diff --git a/macros/latex/contrib/pdfmanagement-testphase/hyperxmp-patches-tmp-ltx.sty b/macros/latex/contrib/pdfmanagement-testphase/hyperxmp-patches-tmp-ltx.sty index 56e9dd45db..a1bc3caddb 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/hyperxmp-patches-tmp-ltx.sty +++ b/macros/latex/contrib/pdfmanagement-testphase/hyperxmp-patches-tmp-ltx.sty @@ -19,7 +19,7 @@ % % for those people who are interested. \NeedsTeXFormat{LaTeX2e}[2020/10/01] -\ProvidesExplPackage{hyperxmp-patches-tmp-ltx}{2021-08-28}{0.95i} +\ProvidesExplPackage{hyperxmp-patches-tmp-ltx}{2022-01-13}{0.95j} {Store hyperref metadata in XMP format / temporay patches to test pdfresource management ... UF} \cs_if_exist:NT \pdfmanagement_add:nnn @@ -124,6 +124,9 @@ \exp_args:NNe \pdfstringdef\@pdftitle{\GetDocumentProperties{hyperref/pdftitle}} \cs_set_eq:NN\hyxmp@pdftitle\@pdftitle + \exp_args:NNe + \pdfstringdef\@pdfcopyright{\GetDocumentProperties{hyperref/pdfcopyright}} + \cs_set_eq:NN\hyxmp@pdfcopyright\@pdfcopyright % pdflang, \tl_if_exist:cF{@pdflang}{\tl_new:c{@pdflang}} \tl_set:cx {@pdflang}{\GetDocumentProperties{document/lang}} @@ -131,8 +134,15 @@ % we need to provide a few commands so that hyperxmp stops to overwrite them % in \AtEndPreamble +% we need also add it to the document properties to avoid stray commas +% with empty author. \AddToHook{begindocument/before}[pdfmanagement/firstaid/hyperxmp]{% - \def\@pdfauthor{Author}\def\@pdftitle {Title}} + \def\@pdfauthor{Author}\def\@pdftitle {Title}% + \tl_if_blank:eT{\GetDocumentProperties{hyperref/pdfauthor}} + {\AddToDocumentProperties[hyperref]{pdfauthor}{Author}} + \tl_if_blank:eT{\GetDocumentProperties{hyperref/pdftitle}} + {\AddToDocumentProperties[hyperref]{pdfauthor}{Title}} + } \DeclareHookRule{begindocument/before}{pdfmanagement/firstaid/hyperxmp}{before}{hyperxmp} diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3backend-testphase.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3backend-testphase.dtx index 7c902d8b92..54f2e089df 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3backend-testphase.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/l3backend-testphase.dtx @@ -45,7 +45,7 @@ % }^^A % } % -% \date{Version 0.95i, released 2021-08-28} +% \date{Version 0.95j, released 2022-01-13} % % \maketitle % @@ -56,27 +56,27 @@ % \begin{macrocode} %<drivers>\ProvidesExplFile %<*dvipdfmx> - {l3backend-testphase-dvipdfmx.def}{2021-08-28}{} + {l3backend-testphase-dvipdfmx.def}{2022-01-13}{} {LaTeX~PDF~management~testphase~bundle~backend~support: dvipdfmx} %</dvipdfmx> %<*dvips> - {l3backend-testphase-dvips.def}{2021-08-28}{} + {l3backend-testphase-dvips.def}{2022-01-13}{} {LaTeX~PDF~management~testphase~bundle~backend~support: dvips} %</dvips> %<*dvisvgm> - {l3backend-testphase-dvisvgm.def}{2021-08-28}{} + {l3backend-testphase-dvisvgm.def}{2022-01-13}{} {LaTeX~PDF~management~testphase~bundle~backend~support: dvisvgm} %</dvisvgm> %<*luatex> - {l3backend-testphase-luatex.def}{2021-08-28}{} + {l3backend-testphase-luatex.def}{2022-01-13}{} {LaTeX~PDF~management~testphase~bundle~backend~support: PDF output (LuaTeX)} %</luatex> %<*pdftex> - {l3backend-testphase-pdftex.def}{2021-08-28}{} + {l3backend-testphase-pdftex.def}{2022-01-13}{} {LaTeX~PDF~management~testphase~bundle~backend~support: PDF output (pdfTeX)} %</pdftex> %<*xdvipdfmx> - {l3backend-testphase-xetex.def}{2021-08-28}{} + {l3backend-testphase-xetex.def}{2022-01-13}{} {LaTeX~PDF~management~testphase~bundle~backend~support: XeTeX} %</xdvipdfmx> % \end{macrocode} @@ -1600,6 +1600,354 @@ % \end{macrocode} % \end{macro} % \end{macro} +% \subsection{Structure Destinations} +% Standard destinations consist of a reference to a page in the pdf and instructions +% how to display it---typically they will put a specific location in the left top corner +% of the viewer and so give the impression that a link jumped to the word in this place. +% But in reality they are not connected to the content. +% +% Starting with pdf~2.0 destinations can in a tagged PDF also point to a structure, to a /StructElem object. +% GoTo links can then additionally to the \texttt{/D} key pointing to a +% page destination also point to such a structure destination with an \texttt{/SD} key. +% Programs that e.g. convert such a PDF to html can then create better links. +% (According to the reference, PDF-viewer should prefer the structure destination +% over the page destination, but as far as it is known this isn't done yet.) +% +% Currently structure destinations and GoTo links making use of it could natively only +% be created with the dvipdfmx backend. With pdftex and lualatex it was only possible to create +% a restricted type which used only the \enquote{Fit} mode. Starting with +% \TeX{}live 2022 (earlier in miktex) both engine will knew new keywords which allow +% to create structure destination easily. +% +% The following backend code prepares the use of structure destinations. The general idea is +% that if structure destinations are used, they should be used always. So we define +% alternative commands which can be activated by mapping them to the standard backend commands. +% +% \begin{macro}{\l_pdf_current_structure_destination_tl} +% +% This commands holds the name of the structure object to use in the next command +% which creates a destination. The code which activates structure destinations +% must also ensure that it has a sensible, expandable content. \pkg{tagpdf} for example +% will define it as +% \begin{verbatim} +% \tl_set:Nn \l_pdf_current_structure_destination_tl { __tag/struct/\g__tag_struct_stack_current_tl } +% \end{verbatim} +% \begin{macrocode} +%<*drivers> +\tl_new:N \l_pdf_current_structure_destination_tl +%</drivers> +% \end{macrocode} +% \end{macro} +% +% We will define alternatives for three backend commands: +% \begin{verbatim} +% \__pdf_backend_destination:nn -> \__pdf_backend_structure_destination:nn +% \__pdf_backend_destination:nnnn -> \__pdf_backend_structure_destination:nnnn +% \__pdf_backend_link_begin_goto:nnw -> \__pdf_backend_link_begin_structure_goto:nnw +% \end{verbatim} +% +% Activating means mapping them onto the original commands. Be aware that not +% all engines and compilation routes support structure destinations, for them +% the command will be a no-op. +% +% \begin{macro}{\pdf_activate_structure_destination:} +% \begin{macrocode} +%<*drivers> +\cs_new_protected:Npn \pdf_activate_structure_destination: + { + \cs_gset_eq:NN \@@_backend_destination:nn \@@_backend_structure_destination:nn + \cs_gset_eq:NN \@@_backend_destination:nnnn \@@_backend_structure_destination:nnnn + \cs_gset_eq:NN \@@_backend_link_begin_goto:nnw \@@_backend_link_begin_structure_goto:nnw + } +%</drivers> +% \end{macrocode} +% \end{macro} +% Now the driver dependant parts. +% By default the new commands are simply copies of the original commands. +% We adapt them then for the engines and engine version which provide support +% for structure destinations. +% +% \begin{macrocode} +%<*drivers> +\cs_set_eq:NN \@@_backend_structure_destination:nn \@@_backend_destination:nn +\cs_set_eq:NN \@@_backend_structure_destination:nnnn \@@_backend_destination:nnnn +\cs_set_eq:NN \@@_backend_link_begin_structure_goto:nnw \@@_backend_link_begin_goto:nnw +%</drivers> +% \end{macrocode} +% \begin{macro}{\@@_backend_structure_destination:nn} +% This command is the backend command to create a destination. +% It should in parallel create also a structure destination. +% At first xetex/dvipdfmx. +% The structure destination is an array, so we use obj for it +% so that we can reference it: +% \begin{macrocode} +%<*xdvipdfmx|dvipdfmx> +\cs_set_protected:Npn \@@_backend_structure_destination:nn #1#2 + { + \@@_backend:x + { + dest ~ ( \exp_not:n {#1} ) + [ + @thispage + \str_case:nnF {#2} + { + { xyz } { /XYZ ~ @xpos ~ @ypos ~ null } + { fit } { /Fit } + { fitb } { /FitB } + { fitbh } { /FitBH } + { fitbv } { /FitBV ~ @xpos } + { fith } { /FitH ~ @ypos } + { fitv } { /FitV ~ @xpos } + { fitr } { /Fit } + } + { /XYZ ~ @xpos ~ @ypos ~ \fp_eval:n { (#2) / 100 } } + ] + } +% \end{macrocode} +% We test if the structure object exist. The object of the structure destination +% gets the name \texttt{@pdf.Sdest.\meta{destname}}, where \meta{destname} is the +% name of the standard destination so that we can reference it in the GoTo links. +% \begin{macrocode} + \exp_args:Ne \pdf_object_if_exist:nT { \l_pdf_current_structure_destination_tl } + { + \@@_backend:x + { + obj ~ @pdf.SDest.\exp_not:n{#1} + [ + \exp_args:Ne \pdf_object_ref:n { \l_pdf_current_structure_destination_tl } + \str_case:nnF {#2} + { + { xyz } { /XYZ ~ @xpos ~ @ypos ~ null } + { fit } { /Fit } + { fitb } { /FitB } + { fitbh } { /FitBH } + { fitbv } { /FitBV ~ @xpos } + { fith } { /FitH ~ @ypos } + { fitv } { /FitV ~ @xpos } + { fitr } { /Fit } + } + { /XYZ ~ @xpos ~ @ypos ~ \fp_eval:n { (#2) / 100 } } + ] + } + } + } +% \end{macrocode} +% The second destination command is for the boxed destination. Here we need to define +% an new auxiliary command: +% \begin{macrocode} +\cs_new_protected:Npn \@@_backend_structure_destination_aux:nnnn #1#2#3#4 + { + \vbox_to_zero:n + { + \__kernel_kern:n {#4} + \hbox:n + { + \@@_backend:n { obj ~ @pdf_ #2 _llx ~ @xpos } + \@@_backend:n { obj ~ @pdf_ #2 _lly ~ @ypos } + } + \tex_vss:D + } + \__kernel_kern:n {#1} + \vbox_to_zero:n + { + \__kernel_kern:n { -#3 } + \hbox:n + { + \@@_backend:n + { + dest ~ (#2) + [ + @thispage + /FitR ~ + @pdf_ #2 _llx ~ @pdf_ #2 _lly ~ + @xpos ~ @ypos + ] + } +% \end{macrocode} +% Here we add the structure destination to the same box +% \begin{macrocode} + \exp_args:Ne \pdf_object_if_exist:nT { \l_pdf_current_structure_destination_tl } + { + \@@_backend:x + { + obj ~ @pdf.SDest.\exp_not:n{#2} + [ + \exp_args:Ne \pdf_object_ref:n { \l_pdf_current_structure_destination_tl } + /FitR ~ + @pdf_ #2 _llx ~ @pdf_ #2 _lly ~ + @xpos ~ @ypos + ] + } + } + } + \tex_vss:D + } + \__kernel_kern:n { -#1 } + } +% \end{macrocode} +% And now we redefine the destination command: +% \begin{macrocode} +\cs_set_protected:Npn \@@_backend_structure_destination:nnnn #1#2#3#4 + { + \exp_args:Ne \@@_backend_structure_destination_aux:nnnn + { \dim_eval:n {#2} } {#1} {#3} {#4} + } +% \end{macrocode} +% At last the goto link. +% \begin{macrocode} +\cs_set_protected:Npn \@@_backend_link_begin_structure_goto:nnw #1#2 + { + \@@_backend_link_begin:n { #1 /Subtype /Link /A << /S /GoTo /D ( #2 ) /SD~@pdf.SDest.#2 >> } + } +%</xdvipdfmx|dvipdfmx> +% \end{macrocode} +% \end{macro} +% Now pdftex. We only redefine for version 1.40 revision 24 or later. +% \begin{macrocode} +%<*pdftex> +\bool_lazy_and:nnT + { \int_compare_p:nNn {\tex_pdftexversion:D } > {139} } + { \int_compare_p:nNn {\tex_pdftexrevision:D } > {23} } + { + \cs_set_protected:Npn \@@_backend_structure_destination:nn #1#2 + { + \tex_pdfdest:D + name {#1} + \str_case:nnF {#2} + { + { xyz } { xyz } + { fit } { fit } + { fitb } { fitb } + { fitbh } { fitbh } + { fitbv } { fitbv } + { fith } { fith } + { fitv } { fitv } + { fitr } { fitr } + } + { xyz ~ zoom \fp_eval:n { #2 * 10 } } + \scan_stop: + \exp_args:Ne \pdf_object_if_exist:nT { \l_pdf_current_structure_destination_tl } + { + \tex_pdfdest:D + struct~ + \int_use:c + { c_@@_backend_object_ \exp_args:Ne \tl_to_str:n {\l_pdf_current_structure_destination_tl} _int }~ + name {#1} + \str_case:nnF {#2} + { + { xyz } { xyz } + { fit } { fit } + { fitb } { fitb } + { fitbh } { fitbh } + { fitbv } { fitbv } + { fith } { fith } + { fitv } { fitv } + { fitr } { fitr } + } + { xyz ~ zoom \fp_eval:n { #2 * 10 } } + \scan_stop: + } + } + \cs_set_protected:Npn \@@_backend_destination:nnnn #1#2#3#4 + { + \tex_pdfdest:D + name {#1} + fitr ~ + width \dim_eval:n {#2} ~ + height \dim_eval:n {#3} ~ + depth \dim_eval:n {#4} \scan_stop: + \exp_args:Ne \pdf_object_if_exist:nT { \l_pdf_current_structure_destination_tl } + { + \tex_pdfdest:D + struct~ + \int_use:c + { c_@@_backend_object_ \exp_args:Ne \tl_to_str:n {\l_pdf_current_structure_destination_tl} _int }~ + name {#1} + fitr ~ + width \dim_eval:n {#2} ~ + height \dim_eval:n {#3} ~ + depth \dim_eval:n {#4} \scan_stop: + } + } + \cs_set_protected:Npn \@@_backend_link_begin_structure_goto:nnw #1#2 + { + \@@_backend_link_begin:nnnw {#1} { goto~struct~name~{#2}~name } {#2} + } + } +%</pdftex> +% \end{macrocode} +% luatex is quite similar to pdftex. Mostly the test for the version is different +% \begin{macrocode} +%<*luatex> + \int_compare:nNnT {\directlua{tex.print(status.list()["development_id"])} } > {7468} + { + \cs_set_protected:Npn \@@_backend_structure_destination:nn #1#2 + { + \tex_pdfextension:D dest + name {#1} + \str_case:nnF {#2} + { + { xyz } { xyz } + { fit } { fit } + { fitb } { fitb } + { fitbh } { fitbh } + { fitbv } { fitbv } + { fith } { fith } + { fitv } { fitv } + { fitr } { fitr } + } + { xyz ~ zoom \fp_eval:n { #2 * 10 } } + \scan_stop: + \exp_args:Ne \pdf_object_if_exist:nT { \l_pdf_current_structure_destination_tl } + { + \tex_pdfextension:D dest + struct~ + \int_use:c + { c_@@_backend_object_ \exp_args:Ne \tl_to_str:n {\l_pdf_current_structure_destination_tl} _int }~ + name {#1} + \str_case:nnF {#2} + { + { xyz } { xyz } + { fit } { fit } + { fitb } { fitb } + { fitbh } { fitbh } + { fitbv } { fitbv } + { fith } { fith } + { fitv } { fitv } + { fitr } { fitr } + } + { xyz ~ zoom \fp_eval:n { #2 * 10 } } + \scan_stop: + } + } + \cs_set_protected:Npn \@@_backend_destination:nnnn #1#2#3#4 + { + \tex_pdfextension:D dest + name {#1} + fitr ~ + width \dim_eval:n {#2} ~ + height \dim_eval:n {#3} ~ + depth \dim_eval:n {#4} \scan_stop: + \exp_args:Ne \pdf_object_if_exist:nT { \l_pdf_current_structure_destination_tl } + { + \tex_pdfextension:D dest + struct~ + \int_use:c + { c_@@_backend_object_ \exp_args:Ne \tl_to_str:n {\l_pdf_current_structure_destination_tl} _int }~ + name {#1} + fitr ~ + width \dim_eval:n {#2} ~ + height \dim_eval:n {#3} ~ + depth \dim_eval:n {#4} \scan_stop: + } + } + \cs_set_protected:Npn \@@_backend_link_begin_structure_goto:nnw #1#2 + { + \@@_backend_link_begin:nnnw {#1} { goto~struct~name~{#2}~name } {#2} + } + } +%</luatex> +% \end{macrocode} % \subsection{lua code for lualatex} % \begin{macrocode} %<*lua> diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3backend-testphase.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3backend-testphase.pdf Binary files differindex cf05f338c0..bd6d7985ee 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3backend-testphase.pdf +++ b/macros/latex/contrib/pdfmanagement-testphase/l3backend-testphase.pdf diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfannot.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdfannot.dtx index 03df126efd..c77314ca25 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdfannot.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdfannot.dtx @@ -2,7 +2,7 @@ % %% File: l3pdfannot.dtx % -% Copyright (C) 2021 The LaTeX Project +% Copyright (C) 2021-2022 The LaTeX Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -24,7 +24,7 @@ % %<*driver> \RequirePackage{pdfmanagement-testphase} -\DeclareDocumentMetadata{pdfstandard=A-2b} +\DocumentMetadata{pdfstandard=A-2b} \makeatletter \declare@file@substitution{doc.sty}{doc-v3beta.sty} \makeatother @@ -52,7 +52,7 @@ % }^^A % } % -% \date{Version 0.95i, released 2021-08-28} +% \date{Version 0.95j, released 2022-01-13} % % \maketitle % \begin{documentation} @@ -436,7 +436,7 @@ % \begin{macrocode} %<@@=pdfannot> %<*header> -\ProvidesExplPackage{l3pdfannot}{2021-08-28}{0.95i} +\ProvidesExplPackage{l3pdfannot}{2022-01-13}{0.95j} {PDF-annotations} \RequirePackage{l3pdfdict} %</header> diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfannot.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdfannot.pdf Binary files differindex bb8974469c..cc44dcca2c 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdfannot.pdf +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdfannot.pdf diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfdict.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdfdict.dtx index 354d9a8654..3a63005f37 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdfdict.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdfdict.dtx @@ -2,7 +2,7 @@ % %% File: l3pdfdict.dtx % -% Copyright (C) 2018-2021 The LaTeX Project +% Copyright (C) 2018-2022 The LaTeX Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -24,7 +24,7 @@ % %<*driver> \RequirePackage{pdfmanagement-testphase} -\DeclareDocumentMetadata{pdfstandard=A-2b} +\DocumentMetadata{pdfstandard=A-2b} \makeatletter \declare@file@substitution{doc.sty}{doc-v3beta.sty} \makeatother @@ -53,7 +53,7 @@ % }^^A % } % -% \date{Version 0.95i, released 2021-08-28} +% \date{Version 0.95j, released 2022-01-13} % % \maketitle % \begin{documentation} @@ -212,7 +212,7 @@ % \begin{macrocode} %<@@=pdfdict> %<*header> -\ProvidesExplPackage{l3pdfdict}{2021-08-28}{0.95i} +\ProvidesExplPackage{l3pdfdict}{2022-01-13}{0.95j} {Tools for PDF dictionaries (LaTeX PDF management testphase bundle)} %</header> % \end{macrocode} @@ -362,7 +362,7 @@ % \end{macro} % % -% \begin{macro} +% \begin{macro}[pTF] % { % \@@_if_exist:n, \pdfdict_if_exist:n, % } @@ -383,7 +383,7 @@ % \end{macro} % % -% \begin{macro} +% \begin{macro}[pTF] % { % \@@_if_empty:n, \pdfdict_if_empty:n, % } diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfdict.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdfdict.pdf Binary files differindex 864ec52bd8..29b211ec27 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdfdict.pdf +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdfdict.pdf diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-action.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-action.dtx index 85852e8cd5..2de21f001a 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-action.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-action.dtx @@ -2,7 +2,7 @@ % %% File: l3pdfpdffield-action.dtx % -% Copyright (C) 2021 The LaTeX Project +% Copyright (C) 2021-2022 The LaTeX Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -24,7 +24,7 @@ % %<*driver> \RequirePackage{pdfmanagement-testphase} -\DeclareDocumentMetadata{} +\DocumentMetadata{} \makeatletter \declare@file@substitution{doc.sty}{doc-v3beta.sty} \makeatother @@ -53,7 +53,7 @@ % }^^A % } % -% \date{Version 0.95i, released 2021-08-28} +% \date{Version 0.95j, released 2022-01-13} % % \maketitle % \begin{documentation} diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-action.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-action.pdf Binary files differindex d44f2aaa3d..9e4f0061b1 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-action.pdf +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-action.pdf diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-checkbox.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-checkbox.dtx index 11d1c869df..eff3d2cd1e 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-checkbox.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-checkbox.dtx @@ -2,7 +2,7 @@ % %% File: l3pdfpdffield-checkbox.dtx % -% Copyright (C) 2021 The LaTeX Project +% Copyright (C) 2021-2022 The LaTeX Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -24,7 +24,7 @@ % %<*driver> \RequirePackage{pdfmanagement-testphase} -\DeclareDocumentMetadata{} +\DocumentMetadata{} \makeatletter \declare@file@substitution{doc.sty}{doc-v3beta.sty} \makeatother @@ -68,7 +68,7 @@ % }^^A % } % -% \date{Version 0.95i, released 2021-08-28} +% \date{Version 0.95j, released 2022-01-13} % % \maketitle % \begin{documentation} diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-checkbox.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-checkbox.pdf Binary files differindex 6268527c46..70666fc007 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-checkbox.pdf +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-checkbox.pdf diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-choice.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-choice.dtx index 81047dfe3d..7c16fa4982 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-choice.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-choice.dtx @@ -2,7 +2,7 @@ % %% File: l3pdfpdffield-choice.dtx % -% Copyright (C) 2021 The LaTeX Project +% Copyright (C) 2021-2022 The LaTeX Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -24,7 +24,7 @@ % %<*driver> \RequirePackage{pdfmanagement-testphase} -\DeclareDocumentMetadata{} +\DocumentMetadata{} \makeatletter \declare@file@substitution{doc.sty}{doc-v3beta.sty} \makeatother @@ -53,7 +53,7 @@ % }^^A % } % -% \date{Version 0.95i, released 2021-08-28} +% \date{Version 0.95j, released 2022-01-13} % % \maketitle % \begin{documentation} diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-choice.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-choice.pdf Binary files differindex 146f100385..72dfa1e3ce 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-choice.pdf +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-choice.pdf diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-pushbutton.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-pushbutton.dtx index 0045b14ba6..eff2adfdb2 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-pushbutton.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-pushbutton.dtx @@ -2,7 +2,7 @@ % %% File: l3pdfpdffield-pushbutton.dtx % -% Copyright (C) 2021 The LaTeX Project +% Copyright (C) 2021-2022 The LaTeX Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -24,7 +24,7 @@ % %<*driver> \RequirePackage{pdfmanagement-testphase} -\DeclareDocumentMetadata{} +\DocumentMetadata{} \makeatletter \declare@file@substitution{doc.sty}{doc-v3beta.sty} \makeatother @@ -59,7 +59,7 @@ % }^^A % } % -% \date{Version 0.95i, released 2021-08-28} +% \date{Version 0.95j, released 2022-01-13} % % \maketitle % \begin{documentation} diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-pushbutton.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-pushbutton.pdf Binary files differindex 867145ba5a..cf69bffb99 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-pushbutton.pdf +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-pushbutton.pdf diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-radiobutton.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-radiobutton.dtx index 45f6a3527f..9d5515d1f4 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-radiobutton.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-radiobutton.dtx @@ -2,7 +2,7 @@ % %% File: l3pdfpdffield-radiobutton.dtx % -% Copyright (C) 2021 The LaTeX Project +% Copyright (C) 2021-2022 The LaTeX Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -24,7 +24,7 @@ % %<*driver> \RequirePackage{pdfmanagement-testphase} -\DeclareDocumentMetadata{} +\DocumentMetadata{} \makeatletter \declare@file@substitution{doc.sty}{doc-v3beta.sty} \makeatother @@ -87,7 +87,7 @@ % }^^A % } % -% \date{Version 0.95i, released 2021-08-28} +% \date{Version 0.95j, released 2022-01-13} % % \maketitle % \begin{documentation} diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-radiobutton.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-radiobutton.pdf Binary files differindex 2c04b5a2b8..2164a70c1c 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-radiobutton.pdf +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-radiobutton.pdf diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-textfield.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-textfield.dtx index 792b7df7ad..4a5f729910 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-textfield.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-textfield.dtx @@ -2,7 +2,7 @@ % %% File: l3pdfpdffield-textfield.dtx % -% Copyright (C) 2021 The LaTeX Project +% Copyright (C) 2021-2022 The LaTeX Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -24,7 +24,7 @@ % %<*driver> \RequirePackage{pdfmanagement-testphase} -\DeclareDocumentMetadata{} +\DocumentMetadata{} \makeatletter \declare@file@substitution{doc.sty}{doc-v3beta.sty} \makeatother @@ -53,7 +53,7 @@ % }^^A % } % -% \date{Version 0.95i, released 2021-08-28} +% \date{Version 0.95j, released 2022-01-13} % % \maketitle % \begin{documentation} diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-textfield.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-textfield.pdf Binary files differindex a3eedc92dc..2ce744434d 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-textfield.pdf +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-textfield.pdf diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield.dtx index d7b2b40424..b872c40f26 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield.dtx @@ -2,7 +2,7 @@ % %% File: l3pdffield.dtx % -% Copyright (C) 2021 The LaTeX Project +% Copyright (C) 2021-2022 The LaTeX Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -24,7 +24,7 @@ % %<*driver> \RequirePackage{pdfmanagement-testphase} -\DeclareDocumentMetadata{} +\DocumentMetadata{} \makeatletter \declare@file@substitution{doc.sty}{doc-v3beta.sty} \makeatother @@ -73,7 +73,7 @@ % }^^A % } % -% \date{Version 0.95i, released 2021-08-28} +% \date{Version 0.95j, released 2022-01-13} % % \maketitle % \begin{documentation} @@ -139,7 +139,7 @@ % % \begin{verbatim} % \RequirePackage{pdfmanagement-testphase} -% \DeclareDocumentMetadata{uncompress} +% \DocumentMetadata{uncompress} % \documentclass{article} % \usepackage{hyperref} % \usepackage{l3pdffield-testphase} @@ -343,7 +343,7 @@ % \Arg{key-val} can be an arbitrary collection of the keys of the module. % \end{function} % -% \begin{function}{create-style} +% \begin{function}{style} % \begin{syntax} % |style| = \Arg{style} % \end{syntax} @@ -463,7 +463,7 @@ % The value is passed through \cs{pdf_string_from_unicode:nnN} % \end{function} % -% \begin{function}{mappingname,TM} +% \begin{function}{FT} % \begin{syntax} % |FT| = |Btn|\verb"|"|Tx|\verb"|"|Ch|\verb"|"|Sig| % \end{syntax} @@ -710,6 +710,13 @@ % all values are zero. % \end{function} % +% \begin{function}{tag} +% \begin{syntax} +% |tag| = |true|\verb+|+|false| +% \end{syntax} +% This key is related to tagging and enables/disables the tagging. +% \end{function} +% % \begin{function}{parent} % \begin{syntax} % |parent| = \meta{field ID}\\ @@ -763,7 +770,7 @@ % \begin{syntax} % |AA/*| = \meta{ECMAScript} % \end{syntax} -% * should be one of |F|, |Bl|, |D|, |U|, |E|, |X|, |PO|, |PC|, |PV|, |PI|. +% * should be one of |Fo|, |Bl|, |D|, |U|, |E|, |X|, |PO|, |PC|, |PV|, |PI|. % Alias names for the first six keys are % |onfocus|, |onblur|, |onmousedown|, |onmouseup|, |onenter|, |onexit|. % These keys adds then the respective key to the |/AA| dictionary @@ -858,7 +865,7 @@ % Currently no special syntax support % is implemented. They will be handled if needed when the code for % push buttons is developed and tested. -% \begin{function}{MK/*} +% \begin{function}{MK/I,MK/RI,MK/IX,MK/IF,MK/TP} % \begin{syntax} % |MK/*| = \meta{various} % \end{syntax} @@ -970,7 +977,7 @@ %<*package> %<@@=pdffield> \NeedsTeXFormat{LaTeX2e} -\ProvidesExplPackage{l3pdffield-testphase}{2021-08-28}{0.95i}% +\ProvidesExplPackage{l3pdffield-testphase}{2022-01-13}{0.95j}% {form fields} % \end{macrocode} % \subsection{hyperref specific command} @@ -1743,7 +1750,7 @@ % \end{macrocode} % \end{macro} % \begin{macro}{tag} -% to disable tagging locall +% to disable tagging locally % \begin{macrocode} \keys_define:nn { pdffield } { diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield.pdf Binary files differindex addd600158..9bb4331db6 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield.pdf +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield.pdf diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffile.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdffile.dtx index 46426e01a2..4da7ef9723 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdffile.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffile.dtx @@ -2,7 +2,7 @@ % %% File: l3pdffile.dtx % -% Copyright (C) 2018-2021 The LaTeX Project +% Copyright (C) 2018-2022 The LaTeX Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -24,7 +24,7 @@ % %<*driver> \RequirePackage{pdfmanagement-testphase} -\DeclareDocumentMetadata{pdfstandard=A-2b} +\DocumentMetadata{pdfstandard=A-2b} \makeatletter \declare@file@substitution{doc.sty}{doc-v3beta.sty} \makeatother @@ -53,7 +53,7 @@ % }^^A % } % -% \date{Version 0.95i, released 2021-08-28} +% \date{Version 0.95j, released 2022-01-13} % % \maketitle % \begin{documentation} @@ -400,7 +400,7 @@ % % \begin{macrocode} %<*header> -\ProvidesExplPackage{l3pdffile}{2021-08-28}{0.95i} +\ProvidesExplPackage{l3pdffile}{2022-01-13}{0.95j} {embedding and referencing files in PDF---LaTeX PDF management testphase bundle} \RequirePackage{l3pdftools} %temporarly!! %</header> @@ -467,8 +467,9 @@ % \end{variable} % \begin{macrocode} \prop_new:N \g_pdffile_mimetypes_prop -\prop_set_from_keyval:Nn \g_pdffile_mimetypes_prop +\prop_gset_from_keyval:Nn \g_pdffile_mimetypes_prop { + ,.css = text/css ,.csv = text/csv ,.html= text/html ,.dtx = text/plain %or application/x-tex, not in iana.org list diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffile.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdffile.pdf Binary files differindex 68e65183e4..2561e4d118 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdffile.pdf +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffile.pdf diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.dtx index 7cb4bf4eeb..f2e494c1fa 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.dtx @@ -2,7 +2,7 @@ % %% File: l3pdfmanagement.dtx % -% Copyright (C) 2018-2021 The LaTeX Project +% Copyright (C) 2018-2022 The LaTeX Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -24,7 +24,7 @@ % %<*driver> \RequirePackage{pdfmanagement-testphase} -\DeclareDocumentMetadata{pdfstandard=A-2b} +\DocumentMetadata{pdfstandard=A-2b} \makeatletter \declare@file@substitution{doc.sty}{doc-v3beta.sty} \makeatother @@ -61,7 +61,7 @@ % }^^A % } % -% \date{Version 0.95i, released 2021-08-28} +% \date{Version 0.95j, released 2022-01-13} % % \maketitle % \begin{documentation} @@ -622,7 +622,7 @@ %<@@=pdfmanagement> %<*header> % -\ProvidesExplPackage{l3pdfmanagement}{2021-08-28}{0.95i} +\ProvidesExplPackage{l3pdfmanagement}{2022-01-13}{0.95j} {Management of core PDF dictionaries (LaTeX PDF management testphase bundle)} %</header> % \end{macrocode} @@ -674,7 +674,7 @@ % \begin{variable}{\g_@@_active_bool} % This boolean will control the activation of the management code. % It is used in the hooks, and in some backend files. -% % \cs{DeclareDocumentMetadata} should set it to true +% % \cs{DocumentMetadata} should set it to true % \begin{macrocode} \bool_new:N \g_@@_active_bool % \end{macrocode} @@ -1563,7 +1563,7 @@ } % \end{macrocode} % \end{macro} -% \begin{macro}{ Handler} +% \begin{macro}{ \@@_handler/Catalog/Names/EmbeddedFiles_gput:n } % EmbeddedFiles is an array and needs a special handler to add values. % \begin{macrocode} \pdfdict_new:n { g__pdf_Core/Catalog/Names } diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.pdf Binary files differindex 3c21347de4..a62a1a0d80 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.pdf +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.pdf diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfmeta.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdfmeta.dtx index 0b83ac71ff..f91555dd04 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdfmeta.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdfmeta.dtx @@ -2,7 +2,7 @@ % %% File: l3pdfmeta.dtx % -% Copyright (C) 2018-2021 The LaTeX Project +% Copyright (C) 2018-2022 The LaTeX Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -24,7 +24,7 @@ % %<*driver> \RequirePackage{pdfmanagement-testphase} -\DeclareDocumentMetadata{pdfstandard=A-2b} +\DocumentMetadata{pdfstandard=A-2b} \makeatletter \declare@file@substitution{doc.sty}{doc-v3beta.sty} \makeatother @@ -53,7 +53,7 @@ % }^^A % } % -% \date{Version 0.95i, released 2021-08-28} +% \date{Version 0.95j, released 2022-01-13} % % \maketitle % \begin{documentation} @@ -192,7 +192,7 @@ % reference it in a /Outputintent and that all output intents reference % the same colorprofile. The value stores the subtype. % {\em This requirement is detected and fulfilled by \pkg{l3pdfmeta} if the -% provided interface in \cs{DeclareDocumentMetadata} is used, see below}. +% provided interface in \cs{DocumentMetadata} is used, see below}. % % \item[|annot_flags|] in annotations the |Print| flag should be true, % |Hidden|, |Invisible|, |NoView| should be false. @@ -235,7 +235,7 @@ % It should be checked against the current PDF version (\cs{pdf_version:}). % A failure means that the version should be changed. % This check is done by \pkg{l3pdfmeta} when the version is set with -% \cs{DeclareDocumentMetadata} so more checks are only needed if the version is changed later. +% \cs{DocumentMetadata} so more checks are only needed if the version is changed later. % % \item[|named_actions|] this requirement restricts the list of % allowed named actions to |NextPage|, |PrevPage|, |FirstPage|, |LastPage|. @@ -290,7 +290,7 @@ % The interface looks like this % % \begin{verbatim} -% \DeclareDocumentMetadata +% \DocumentMetadata % { % %other options for example pdfstandard % colorprofiles= @@ -318,7 +318,7 @@ % color profile, the setting is changed to the equivalent of % % \begin{verbatim} -% \DeclareDocumentMetadata +% \DocumentMetadata % { % %other options % pdfstandard=A-2b, @@ -345,7 +345,7 @@ % \begin{macrocode} %<@@=pdfmeta> %<*header> -\ProvidesExplPackage{l3pdfmeta}{2021-08-28}{0.95i} +\ProvidesExplPackage{l3pdfmeta}{2022-01-13}{0.95j} {PDF-Standards---LaTeX PDF management testphase bundle} %</header> % \end{macrocode} @@ -526,7 +526,7 @@ % } % \begin{macrocode} \prop_new:c { g_@@_standard_pdf/A-1B_prop } -\prop_set_from_keyval:cn { g_@@_standard_pdf/A-1B_prop } +\prop_gset_from_keyval:cn { g_@@_standard_pdf/A-1B_prop } { ,name = pdf/A-1B ,type = A diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfmeta.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdfmeta.pdf Binary files differindex 6466964faf..6bf44b039b 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdfmeta.pdf +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdfmeta.pdf diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdftools.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdftools.dtx index 4b35e21e17..9959583cd3 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdftools.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdftools.dtx @@ -2,7 +2,7 @@ % %% File: l3pdftools.dtx % -% Copyright (C) 2018-2021 The LaTeX Project +% Copyright (C) 2018-2022 The LaTeX Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -24,7 +24,7 @@ % %<*driver> \RequirePackage{pdfmanagement-testphase} -\DeclareDocumentMetadata{pdfstandard=A-2b} +\DocumentMetadata{pdfstandard=A-2b} \makeatletter \declare@file@substitution{doc.sty}{doc-v3beta.sty} \makeatother @@ -53,7 +53,7 @@ % }^^A % } % -% \date{Version 0.95i, released 2021-08-28} +% \date{Version 0.95j, released 2022-01-13} % % \maketitle % \begin{documentation} @@ -215,7 +215,7 @@ % % \begin{macrocode} %<*header> -\ProvidesExplPackage{l3pdftools}{2021-08-28}{0.95i} +\ProvidesExplPackage{l3pdftools}{2022-01-13}{0.95j} {candidate commands for l3pdf---LaTeX PDF management testphase bundle} %</header> % \end{macrocode} diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdftools.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdftools.pdf Binary files differindex d9f94b94ae..df2e659463 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdftools.pdf +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdftools.pdf diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfxform.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdfxform.dtx index 86ecfccb45..f4a4a6a7f4 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdfxform.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdfxform.dtx @@ -2,7 +2,7 @@ % %% File: l3pdfxform.dtx % -% Copyright (C) 2018-2021 The LaTeX Project +% Copyright (C) 2018-2022 The LaTeX Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -24,7 +24,7 @@ % %<*driver> \RequirePackage{pdfmanagement-testphase} -\DeclareDocumentMetadata{pdfstandard=A-2b} +\DocumentMetadata{pdfstandard=A-2b} \makeatletter \declare@file@substitution{doc.sty}{doc-v3beta.sty} \makeatother @@ -52,7 +52,7 @@ % }^^A % } % -% \date{Version 0.95i, released 2021-08-28} +% \date{Version 0.95j, released 2022-01-13} % % \maketitle % \begin{documentation} @@ -136,7 +136,7 @@ % \begin{macrocode} %<@@=pdf> %<*header> -\ProvidesExplPackage{l3pdfxform}{2021-08-28}{0.95i} +\ProvidesExplPackage{l3pdfxform}{2022-01-13}{0.95j} {command to create xforms (beta)---LaTeX PDF management testphase bundle} %</header> % \end{macrocode} diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfxform.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdfxform.pdf Binary files differindex 2046decacb..9e341ac965 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdfxform.pdf +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdfxform.pdf diff --git a/macros/latex/contrib/pdfmanagement-testphase/ltdocinit.dtx b/macros/latex/contrib/pdfmanagement-testphase/ltdocinit.dtx index 9af1a938eb..110bbb09b2 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/ltdocinit.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/ltdocinit.dtx @@ -2,7 +2,7 @@ % %% File: ltdocinit.dtx % -% Copyright (C) 2018-2021 The LaTeX Project +% Copyright (C) 2018-2022 The LaTeX Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -24,7 +24,7 @@ % %<*driver> \RequirePackage{pdfmanagement-testphase} -\DeclareDocumentMetadata{pdfstandard=A-2b} +\DocumentMetadata{pdfstandard=A-2b} \makeatletter \declare@file@substitution{doc.sty}{doc-v3beta.sty} \makeatother @@ -51,20 +51,25 @@ % }^^A % } % -% \date{Version 0.95i, released 2021-08-28} +% \date{Version 0.95j, released 2022-01-13} % % \maketitle % \begin{documentation} % % \section{\pkg{ltdocinit} documentation} -% This small module defines \cs{DeclareDocumentMetadata} and the related keys. +% This small module defines \cs{DocumentMetadata} and the older alias +% \cs{DeclareDocumentMetadata} and the related keys. % It also defines commands to store document properties in a global container. % -% \subsection{\cs{DeclareDocumentMetadata}} +% When the kernel will provide \cs{DocumentMetadata} directly +% this module will slowly disappear. % -% \begin{function}{\DeclareDocumentMetadata} +% \subsection{\cs{DocumentMetadata}/\cs{DeclareDocumentMetadata}} +% +% \begin{function}{\DocumentMetadata,\DeclareDocumentMetadata} % \begin{syntax} -% \cs{DeclareDocumentMetadata}\Arg{key-value list} +% \cs{DocumentMetadata}\Arg{key-value list}\\ +% \cs{DeclareDocumentMetadata}\Arg{key-value list} (deprecated) % \end{syntax} % \end{function} % @@ -75,65 +80,89 @@ % for example the pdf version can no longer be changed if a % package has used code which already opened the PDF. % -% \cs{DeclareDocumentMetadata} as a new command +% \cs{DocumentMetadata} as a new command % should unify such settings in one place. -% It should be used before \cs{documentclass}, directly after -% loading \pkg{pdfmanagement-testphase}. \cs{DeclareDocumentMetadata} -% can be used more than once. +% It should be used before \cs{documentclass}. +% \cs{DocumentMetadata} can be used more than once. +% +% With a \LaTeX{} 2022-06-01 or newer (currently provided as |latex-dev|) the command +% is provided by the kernel and will load the pdfmanagement, +% with older \LaTeX{} the pdfmanagement must be loaded +% first manually with |\RequirePackage{pdfmanagement-testphase}|. % -% The keys defined for \cs{DeclareDocumentMetadata} +% The keys defined for \cs{DocumentMetadata} % currently allows to set the PDF version, to set the PDF \texttt{/Lang}, % to uncompress a pdf, to set the language and to declare a few PDF standards -% and some colorprofiles. +% and to load some colorprofiles. % -% \cs{DeclareDocumentMetadata} is also used to +% \cs{DocumentMetadata} is also used to % activate the new PDF management code and it loads % a number of required files for the PDF management code. % As this forces the loading of the backend files, a backend % which can't be detected automatically like |dvipdfmx|, -% must be set in the first \cs{DeclareDocumentMetadata}. +% must be set in the first \cs{DocumentMetadata}. % % Currently the following keys are implemented % % \begin{description} -% \item[\texttt{backend}] passes the backend name to expl3. -% This will probably be extended to pass the value also to packages. -% \item[\texttt{pdfversion}] e.g. \texttt{pdfversion=1.7} -% \item[\texttt{uncompress}] no value. Forces an uncompressed pdf. -% \item[\texttt{lang}] to set the Lang entry in the Catalog. -% E.g. \texttt{lang=de-DE}. The initial value is |en-US| +% \item[\texttt{backend}] Passes the backend name to expl3. This is +% needed only if the needed backend can't be automatically +% determined or if the workflow used requires a special backend. +% +%^^A This will probably be extended to pass the value also to +%^^A packages. +% +% \item[\texttt{pdfversion}] Sets the PDF version explicitly, e.g., \texttt{pdfversion=1.7} +% \item[\texttt{uncompress}] (no value) Forces an uncompressed pdf +% --- mainly for debugging purposes. +% +% \item[\texttt{lang}] Explicitly sets the Lang entry in the Catalog, +% e.g., \texttt{lang=de-DE}. If not given the default value used is |en-US|. +% % \item[\texttt{pdfstandard}] Choice key to set the pdf standard. % Currently |A-1b|, |A-2a|, |A-2b|, |A-2u|, |A-3a|, |A-3b| and |A-3u| are accepted as % values. The casing is irrelevant, |a-1b| works too. % The underlying code to ensure the requirements (as far as they -% can be ensured) is incomplete, but a color profile is included and the -% /OutputIntent is set. The |u| variants for example do not force unicode, +% can be ensured) is still incomplete, but a color profile is included and the +% \texttt{/OutputIntent} is set. The |u| variants for example do not force unicode, % but they will pass the information to hyperref and hyperxmp. The |a| variants % do \emph{not} enforce (or even test) a tagged pdf yet. % More information can be found in the documentation % of \pkg{l3pdfmeta}. +% % \item[\texttt{colorprofiles}] This allows to load icc-colorprofiles. Details -% are described in the documentation of \pkg{l3pdfmeta}. -% \item[\texttt{pdfmanagement}] Boolean. This activates/deactivates -% the core management code. By default the value is true. -% \item[\texttt{firstaidoff}] This accepts a comma lists of keysword and disable the patches -% related to them. More information can be found in the documentation of -% \pkg{pdfmanagement-firstaid}. +% are described in the documentation of \pkg{l3pdfmeta}. +% % \item[\texttt{testphase}] This key is used to load testphase code. The values it accepts % and their effect will change over time, when testphase packages are added or -% removed when the code is moved into the kernel. Currently the accepted values are -% \texttt{tagpdf}, this load the tagpdf package, \texttt{headings}, this loads -% code which reimplements heading commands, and \texttt{ptagging} this loads code -% to allow paragraph tagging to work with engine other than luatex. -% \item[\texttt{activate}] This key is used to enable some document wide functions. It is -% currently in an experimental state. The values and their behaviour are subject to change. -% Currently the only value is |tagging|, -% which will do |\tagpdfsetup{activate,paratagging,interwordspace}|. It requires that -% \pkg{tagpdf} has been loaded first with the |testphase| key. -% \item[\texttt{debug}] This key activates some debug options. Currently only the -% keys |para| (with the default and only value |show|), -% and |log| (with the values of \pkg{tagpdf}) and |uncompress| (which does the same -% as |uncompress| as main key) are known. +% removed or when the code is moved into the kernel. +% \begin{description} +% \item[\texttt{phase-I}] +% This value loads code implementing the first phase of the project~\cite{blueprint}, i.e., it +% will load the tagpdf package. It will also activate tagging by issuing +% |\tagpdfsetup{activate,interwordspace}|. This phase +% is frozen. +% \item[\texttt{phase-II}] +% This is the current development phase. +% Currently it differs from \texttt{phase-I} only in one point: It will +% additionally activate tagging of paragraphs with +% |\tagpdfsetup{paratagging}|. In the upcoming months it will +% also enable automatic tagging of other basic document elements. +% \end{description} +% The |testphase| key can only be used in the first \cs{DocumentMetadata}. +% +% \item[\texttt{debug}] This key activates some debug options. It takes a list of key-values +% as value. Currently the following keys are known: +% \begin{description} +% \item[\texttt{para}] with the default and only value |show|. It will activate the |paratagging-show| +% option of \pkg{tagpdf}, +% \item[\texttt{log}] with the values as described in the documentation \pkg{tagpdf}, +% \item[\texttt{uncompress}] which does the same as |uncompress| as main key +% \item[\texttt{pdfmanagement}] a boolean which allows to deactivate the pdfmanagement. +% \item[\texttt{firstaidoff}] This accepts a comma lists of keywords and disables the patches +% related to them. More information can be found in the documentation of +% \pkg{pdfmanagement-firstaid}. +% \end{description} % \end{description} % % \subsection{Container for document properties} @@ -151,7 +180,7 @@ % \end{syntax} % This stores \meta{value} under the key \meta{label}/\meta{property}. % By default \meta{label} is the current package name |\@currname|. If another -% label is choosen, it should be one which avoids clashes with other packages +% label is chosen, it should be one which avoids clashes with other packages % using the container. The label |document| is reserved. % \end{function} % @@ -174,91 +203,290 @@ % This show the current content of the container. % \end{function} % +% \begin{thebibliography}{9} +% +% \bibitem{blueprint} Frank Mittelbach and Chris Rowley: +% \emph{\LaTeX{} Tagged PDF\,---\,A blueprint for a large project}. +% \url{https://latex-project.org/publications/indexbyyear/2020/} +% +% \end{thebibliography} +% % \end{documentation} % % \begin{implementation} % % \section{\pkg{ltdocinit} implementation} -% \subsection{\cs{DeclareDocumentMetadata}} % \begin{macrocode} %<@@=pdfmanagement> %<*header> -\ProvidesExplPackage{ltdocinit}{2021-08-28}{0.95i} +\ProvidesExplPackage{ltdocinit}{2022-01-13}{0.95j} {Initialize document metadata} %</header> % \end{macrocode} -% \cs{DeclareDocumentMetadata} should for now not be used after -% \cs{documentclass} so we error in this case. It can be used more than once -% but follow-up calls should not do the initialization code. +% \cs{DocumentMetadata} will be defined by the kernel in short time. +% So we define it and the keys here only if it is not already defined. +% \subsection{The keys for \cs{DocumentMetadata}} +% We define the keys first so that we can test if \cs{DocumentMetadata} +% exist (testing for the format date would be nice but would fail for the current +% latex-dev). +% \begin{variable}{\g_@@_firstaidoff_clist} +% A list to store the firstaid code which should be disabled % \begin{macrocode} %<*package> -\msg_new:nnn { document } { setup-after-documentclass } +\clist_new:N \g_@@_firstaidoff_clist +% \end{macrocode} +% \end{variable} +% \begin{variable}{\g_@@_testphase_tl} +% a tl to store the testphase loading code so that we can load them at +% the end of the command. +% \begin{macrocode} +\tl_new:N \g_@@_testphase_tl +% \end{macrocode} +% \end{variable} +% \begin{macrocode} +\cs_if_free:NT \DocumentMetadata + { + \keys_define:nn { document / metadata } + { + backend .choices:nn = + { dvipdfmx , dvips , dvisvgm , luatex , pdftex , pdfmode , xdvipdfmx , xetex } + { + \sys_load_backend:n {#1} + }, + backend .groups:n = { init } , + } + + \keys_define:nn { document / metadata } + { + ,pdfversion .code:n = + { + \pdf_version_gset:n { #1 } + \AddToDocumentProperties[document]{pdfversion}{#1} + } + ,uncompress .code:n = + { + \pdf_uncompress: + } + ,uncompress .value_forbidden:n = true + ,lang .code:n = + { + \pdfmanagement_add:nnn {Catalog} {Lang}{(#1)} + \AddToDocumentProperties[document]{lang}{#1} + } + %,xmpmeta .bool_gset:N = \g_pdfmeta_xmp_bool %see pdfmeta unused and undefined for now! + % this uses internal command from pdfmeta, it should probably move there ... + ,pdfstandard .code:n = + { + \exp_args:Nnx + \keys_set:nn {document / metadata} {_pdfstandard=\str_uppercase:n{#1}} + } + ,_pdfstandard .choices:nn = + {A-1B,A-2A,A-2B,A-2U,A-3A,A-3B,A-3U} + { + \prop_if_exist:cT { g__pdfmeta_standard_pdf/#1_prop } { - \token_to_str:N \DeclareDocumentMetadata \c_space_tl - should~be~used~only~before~\token_to_str:N\documentclass + \prop_gset_eq:Nc \g__pdfmeta_standard_prop { g__pdfmeta_standard_pdf/#1 _prop } } + \AddToDocumentProperties [document]{pdfstandard}{#1} + } + ,_pdfstandard / unknown .code:n = + { + \msg_warning:nnn{pdf}{unknown-standard}{#1} + } + ,testphase .multichoice: + ,testphase / tagpdf .code:n = + { + \tl_gput_right:Nn\g_@@_testphase_tl + { + \file_if_exist_input:nF {tagpdf-latex-lab-testphase.ltx} + { + \RequirePackage{tagpdf} + \AddToDocumentProperties [document]{testphase/tagpdf}{loaded} + \tagpdfsetup{activate,paratagging,interwordspace} + \AddToDocumentProperties [document]{tagging}{active} + \AddToDocumentProperties [document]{tagging/para}{active} + \AddToDocumentProperties [document]{tagging/interwordspace}{active} + } + } + } + ,testphase / unknown .code:n = + { + \tl_gput_right:Nn\g_@@_testphase_tl + { + \file_if_exist_input:nF {#1-latex-lab-testphase.ltx} + { + \msg_warning:nnn{document}{latex-lab-pkg-missing}{#1} + } + } + } + ,activate .multichoice: + ,activate / tagging .code:n = + { + \PackageWarning{pdfmanagement-testphase} + {The~activate~key~is~deprecated.\MessageBreak + Tagging~is~activated~with~'testphase=tagpdf'~directly}{} + } + ,debug .code:n = + { + \keys_set:nn { document / metadata / debug } {#1} + } + ,debug / para .code:n = + { + \AddToHook + { + package/tagpdf/after + } + { + \tagpdfsetup{paratagging-show} + } + } + ,debug / log .code:n = + { + \AddToHook + { + package/tagpdf/after + } + { + \tagpdfsetup{log=#1} + } + } + ,debug / uncompress .code:n = + { + \pdf_uncompress: + } + ,debug / pdfmanagement .bool_gset:N = \g_@@_active_bool + ,debug / firstaidoff .clist_gset:N = \g_@@_firstaidoff_clist + } + } % \end{macrocode} -% \begin{macro}{\DeclareDocumentMetadata} +% +% \subsection{\cs{DocumentMetadata}/\cs{DeclareDocumentMetadata}} +% At first we have to define the older alias \cs{DeclareDocumentMetadata} if +% \cs{DocumentMetadata} is already defined in a newer LaTeX version. Here +% we load the latex-lab support (if it hasn't been loaded +% before) and redefine then \cs{DeclareDocumentMetadata} +% to \cs{DocumentMetadata} +% % \begin{macrocode} -\NewDocumentCommand\DeclareDocumentMetadata { m } +\cs_if_exist:NT \DocumentMetadata + { + \cs_new_protected:Npn \DeclareDocumentMetadata + { + \cs_if_free:NT \DocumentMetadata + { + \file_if_exist_input:nF {documentmetadata-support.ltx}% + { + \@latex@error + {No~support~files~for~\noexpand\DeclareDocumentMetadata~found} + { + Is~the~'LaTeX-lab'~bundle~installed? + \MessageBreak + Without~it,~the~declaration~is~ignored. + } + \let\DeclareDocumentMetadata\@gobble + } + } + \RenewDocumentCommand \DeclareDocumentMetadata {} + { \DocumentMetadata } + \DocumentMetadata + } + } +% \end{macrocode} +% Now we provide a definition for \cs{DocumentMetadata} if it doesn't exist yet. +% \begin{macrocode} +\cs_if_free:NT \DocumentMetadata { - \cs_if_eq:NNTF \documentclass \@twoclasseserror - { \msg_error:nn { document }{ setup-after-documentclass } } +% \end{macrocode} +% \cs{DocumentMetadata} should for now not be used after +% \cs{documentclass} so we error in this case. It can be used more than once +% but follow-up calls should not do the initialization code. +% \begin{macrocode} + \prop_gput:Nnn \g_msg_module_type_prop { document } { LaTeX } + \prop_gput:Nnn \g_msg_module_name_prop { document } { DocumentMetadata } + \msg_new:nnn + { document } { setup-after-documentclass } + { + \token_to_str:N \DocumentMetadata \c_space_tl + should~be~used~only~before~\token_to_str:N\documentclass + } + \msg_new:nnn + { document } { latex-lab-pkg-missing } + { + LaTeX-lab~package~'#1'~not~found. + } +% \end{macrocode} +% \begin{macro}{\DocumentMetadata} +% \begin{macrocode} + \NewDocumentCommand\DocumentMetadata { m } { + \cs_if_eq:NNTF \documentclass \@twoclasseserror + { \msg_error:nn { document }{ setup-after-documentclass } } + { % \end{macrocode} % The wanted backend must be detected first, we read the init key and then -% force the loading by either loading l3pdf (+ expl3) or only expl3. -% The backend contains now management command, so the boolean should true first. +% force the loading by loading expl3. +% The backend can contains management commands, so the boolean should be set to true first. % \begin{macrocode} - \keys_set_groups:nnn { document / metadata} {init}{ #1 } - %should be loaded after the backend is set, and only if not in the kernel - \bool_gset_true:N \g_@@_active_bool - \cs_if_free:NTF \pdf_uncompress: - {\RequirePackage{l3pdf}}{\RequirePackage{expl3}} + \bool_gset_true:N \g_@@_active_bool + \keys_set_groups:nnn { document / metadata} {init}{ #1 } + %if no backend has been loaded force it now: + \str_if_exist:NF \c_sys_backend_str + { + \sys_load_backend:n {} + } % \end{macrocode} % Now we load the extra backend code % \begin{macrocode} \ExplSyntaxOn\makeatletter - \file_input:n {l3backend-testphase-\c_sys_backend_str.def} + \file_input:n {l3backend-testphase-\c_sys_backend_str.def} \ExplSyntaxOff\makeatother % \end{macrocode} % set the default language, process the rest of the keys, % and setup the generic driver % \begin{macrocode} - \keys_set_filter:nnn { document / metadata } { init } { lang=en-US, #1 } - \bool_if:NT \g_@@_active_bool - { - \PassOptionsToPackage{customdriver=hgeneric-testphase}{hyperref} - } + \keys_set_filter:nnn { document / metadata } { init } { lang=en-US, #1 } + \bool_if:NT \g_@@_active_bool + { + \PassOptionsToPackage{customdriver=hgeneric-testphase}{hyperref} + } % \end{macrocode} % \cs{pdfmanagement_add:nnn} has collected values in this hook. % \begin{macrocode} - \hook_use_once:n {pdfmanagement/add} + \hook_use_once:n {pdfmanagement/add} % \end{macrocode} -% Redefine \cs{DeclareDocumentMetadata} so that it only process the keys. +% Redefine \cs{DocumentMetadata} so that it only process the keys. % We need to update the hyperref option if the active status changes. % \begin{macrocode} - \RenewDocumentCommand\DeclareDocumentMetadata { m } - { - \keys_set_filter:nnn { document / metadata } { init } { ##1 } - \bool_if:NTF \g_@@_active_bool - { - \str_remove_all:cn {opt@hyperref.sty}{customdriver=hgeneric-testphase} - \PassOptionsToPackage{customdriver=hgeneric-testphase}{hyperref} - } - { - \str_remove_all:cn {opt@hyperref.sty}{customdriver=hgeneric-testphase} - } - } + \RenewDocumentCommand\DocumentMetadata { m } + { + \keys_set_filter:nnn { document / metadata } { init } { ##1 } + \bool_if:NTF \g_@@_active_bool + { + \str_remove_all:cn + {opt@hyperref.sty}{customdriver=hgeneric-testphase} + \PassOptionsToPackage + {customdriver=hgeneric-testphase}{hyperref} + } + { + \str_remove_all:cn + {opt@hyperref.sty}{customdriver=hgeneric-testphase} + } + } % \end{macrocode} % Load more modules, the testphase code and the firstaid code. % \begin{macrocode} - \g_@@_testphase_tl - \RequirePackage{pdfmanagement-firstaid} + \g_@@_testphase_tl + \RequirePackage{pdfmanagement-firstaid} + } } +% \end{macrocode} +% At last we need to provide the older alias here too +% \begin{macrocode} + \NewDocumentCommand\DeclareDocumentMetadata{}{\DocumentMetadata} } % \end{macrocode} % \end{macro} +% % \subsection{Container for document Properties} % The container for the document properties is a prop % \begin{variable}{\g_@@_documentproperties_prop} @@ -303,147 +531,6 @@ } % \end{macrocode} % \end{macro} -% \subsection{The keys for \cs{DeclareDocumentMetadata}} -% As they use \cs{AddToDocumentProperties} they have to come after -% it has been defined. -% -% \begin{variable}{\g_@@_firstaidoff_clist} -% A list to store the firstaid code which should be disabled -% \begin{macrocode} -\clist_new:N \g_@@_firstaidoff_clist -% \end{macrocode} -% \end{variable} -% \begin{variable}{\g_@@_testphase_tl} -% a tl to store the testphase loading code so that we can load them at -% the end of the command. -% \begin{macrocode} -\tl_new:N \g_@@_testphase_tl -% \end{macrocode} -% \end{variable} -% \begin{macrocode} -\keys_define:nn { document / metadata } - { - backend .code:n = - { - \PassOptionsToPackage { driver=#1 } {expl3} - \AddToDocumentProperties[document]{backend}{#1} - }, - backend .groups:n = { init } , - } - -\keys_define:nn { document / metadata } - { - ,pdfversion .code:n = - { - \pdf_version_gset:n { #1 } - \AddToDocumentProperties[document]{pdfversion}{#1} - } - ,uncompress .code:n = - { - \pdf_uncompress: - } - ,uncompress .value_forbidden:n = true - ,lang .code:n = - { - \pdfmanagement_add:nnn {Catalog} {Lang}{(#1)} - \AddToDocumentProperties[document]{lang}{#1} - } - %,xmpmeta .bool_gset:N = \g_pdfmeta_xmp_bool %see pdfmeta unused and undefined for now! - % this uses internal command from pdfmeta, it should probably move there ... - ,pdfstandard .code:n = - { - \exp_args:Nnx - \keys_set:nn {document / metadata} {_pdfstandard=\str_uppercase:n{#1}} - } - ,_pdfstandard .choices:nn = - {A-1B,A-2A,A-2B,A-2U,A-3A,A-3B,A-3U} - { - \prop_if_exist:cT { g__pdfmeta_standard_pdf/#1_prop } - { - \prop_gset_eq:Nc \g__pdfmeta_standard_prop { g__pdfmeta_standard_pdf/#1 _prop } - } - \AddToDocumentProperties [document]{pdfstandard}{#1} - } - ,_pdfstandard / unknown .code:n = - { - \msg_warning:nnn{pdf}{unknown-standard}{#1} - } - ,pdfmanagement .bool_gset:N = \g_@@_active_bool - ,firstaidoff .clist_gset:N = \g_@@_firstaidoff_clist - ,testphase .multichoice: - ,testphase / tagpdf .code:n = - { - \tl_gput_right:Nn\g_@@_testphase_tl - { - \RequirePackage{tagpdf} - \AddToDocumentProperties [document]{testphase/tagpdf}{loaded} - } - } - ,testphase / headings .code:n = - { - \tl_gput_right:Nn\g_@@_testphase_tl - { - \RequirePackage{headings-testphase} - \AddToDocumentProperties [document]{testphase/headings}{loaded} - } - } - ,testphase / ptagging .code:n = - { - \tl_gput_right:Nn\g_@@_testphase_tl - { - \AddToHook{class/after} - { - \RequirePackage{ptagging-testphase} - \AddToDocumentProperties [document]{testphase/ptagging}{loaded} - } - } - } - ,testphase / unknown .code:n = - { - \tl_gput_right:Nn\g_@@_testphase_tl - { - \AddToHook{class/after} - { - \RequirePackage{#1-testphase} - \AddToDocumentProperties [document]{testphase/#1}{loaded} - } - } - } - ,activate .multichoice: - ,activate / tagging .code:n = - { - \AddToHook{package/after/tagpdf} - { - \tagpdfsetup{activate,paratagging,interwordspace} - \AddToDocumentProperties [document]{tagging}{active} - \AddToDocumentProperties [document]{tagging/para}{active} - \AddToDocumentProperties [document]{tagging/interwordspace}{active} - } - } - ,debug .code:n = - { - \keys_set:nn { document / metadata / debug } {#1} - } - ,debug / para .code:n = - { - \AddToHook{package/after/tagpdf} - { - \tagpdfsetup{paratagging-show} - } - } - ,debug / log .code:n = - { - \AddToHook{package/after/tagpdf} - { - \tagpdfsetup{log=#1} - } - } - ,debug / uncompress .code:n = - { - \pdf_uncompress: - } - } -% \end{macrocode} % \begin{macrocode} %</package> % \end{macrocode} diff --git a/macros/latex/contrib/pdfmanagement-testphase/ltdocinit.pdf b/macros/latex/contrib/pdfmanagement-testphase/ltdocinit.pdf Binary files differindex 1bc3aa262d..0816edae0f 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/ltdocinit.pdf +++ b/macros/latex/contrib/pdfmanagement-testphase/ltdocinit.pdf diff --git a/macros/latex/contrib/pdfmanagement-testphase/output-patches-tmp-ltx.dtx b/macros/latex/contrib/pdfmanagement-testphase/output-patches-tmp-ltx.dtx index 7b67c520b3..f084030fd2 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/output-patches-tmp-ltx.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/output-patches-tmp-ltx.dtx @@ -119,7 +119,8 @@ % \end{itemize} % % \begin{macrocode} -\AddToHook{package/after/multicol}{% multicol needs later loading +\AddToHook{package/multicol/after} + {% multicol needs later loading % \end{macrocode} % % \begin{macrocode} diff --git a/macros/latex/contrib/pdfmanagement-testphase/output-patches-tmp-ltx.pdf b/macros/latex/contrib/pdfmanagement-testphase/output-patches-tmp-ltx.pdf Binary files differindex 30d2a68ced..a99709cf13 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/output-patches-tmp-ltx.pdf +++ b/macros/latex/contrib/pdfmanagement-testphase/output-patches-tmp-ltx.pdf diff --git a/macros/latex/contrib/pdfmanagement-testphase/pdflscape-ltx.sty b/macros/latex/contrib/pdfmanagement-testphase/pdflscape-ltx.sty index b7a12f5545..677e3fe40e 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/pdflscape-ltx.sty +++ b/macros/latex/contrib/pdfmanagement-testphase/pdflscape-ltx.sty @@ -22,7 +22,7 @@ %% This work consists of the main source file pdflscape-ltx.sty %% \NeedsTeXFormat{LaTeX2e} -\ProvidesExplPackage{pdflscape-ltx}{2021-08-28}{0.95i} +\ProvidesExplPackage{pdflscape-ltx}{2022-01-13}{0.95j} {Display of landscape pages in PDF - adaption of pdflscape to the PDFmanagement bundle (testphase)} \DeclareOption*{\PassOptionsToPackage\CurrentOption{graphics}} diff --git a/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-firstaid.dtx b/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-firstaid.dtx index 65f3f7cfa4..6383bd9922 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-firstaid.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-firstaid.dtx @@ -2,7 +2,7 @@ % %% File: pdfmanagement-firstaid.dtx % -% Copyright (C) 2018-2021 The LaTeX Project +% Copyright (C) 2018-2022 The LaTeX Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -24,7 +24,7 @@ % %<*driver> \RequirePackage{pdfmanagement-testphase} -\DeclareDocumentMetadata{pdfstandard=A-2b} +\DocumentMetadata{pdfstandard=A-2b} \makeatletter \declare@file@substitution{doc.sty}{doc-v3beta.sty} \makeatother @@ -51,7 +51,7 @@ % }^^A % } % -% \date{Version 0.95i, released 2021-08-28} +% \date{Version 0.95j, released 2022-01-13} % % \maketitle % \begin{documentation} @@ -63,11 +63,11 @@ % This code should disappear when packages adapt to the central interfaces. % % The package contains an number of sections for various packages. Every -% section can be disabled in (the first) \cs{DeclareDocumentMetadata} with -% |firstaidoff={name1,name2,...}|. +% section can be disabled in (the first) \cs{DocumentMetadata} with +% |debug={firstaidoff={name1,name2,...},...}|. % \begin{macrocode} %<*package> -\ProvidesExplPackage{pdfmanagement-firstaid}{2021-08-28}{0.95i} +\ProvidesExplPackage{pdfmanagement-firstaid}{2022-01-13}{0.95j} {LaTeX PDF management testphase bundle / firstaid-patches} %<@@=pdfmanagement> @@ -137,7 +137,10 @@ % \begin{macrocode} \bool_if:NT \g_@@_firstaid_xcolor_bool { - \AddToHook{package/after/xcolor} + \AddToHook + { + package/xcolor/after + } {\RequirePackage{xcolor-patches-tmp-ltx}\XC@@@@names} } % \end{macrocode} @@ -170,7 +173,10 @@ \bool_if:NT \g_@@_firstaid_pgf_bool { \msg_info:nnn{pdfmanagement }{firstaid}{pgf} - \AddToHook{file/after/pgfrcs.sty} + \AddToHook + { + file/pgfrcs.sty/after + } { \cs_set_eq:NN \@@_pgfori_pgfutil@setuppdfresources @@ -274,7 +280,9 @@ \bool_if:NT \g_@@_firstaid_hyperxmp_bool { \AddToHook - {file/after/hyperxmp.sty} + { + file/hyperxmp.sty/after + } {\RequirePackage{hyperxmp-patches-tmp-ltx}} } %</package> diff --git a/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-firstaid.pdf b/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-firstaid.pdf Binary files differindex 7f601e819e..b730d9e75e 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-firstaid.pdf +++ b/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-firstaid.pdf diff --git a/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.dtx b/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.dtx index 313f2d326e..1364b8e83c 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.dtx @@ -2,7 +2,7 @@ % %% File: pdfmanagement-testphase.dtx % -% Copyright (C) 2019-2021 The LaTeX Project +% Copyright (C) 2019-2022 The LaTeX Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -24,9 +24,9 @@ % %<*driver> \RequirePackage{pdfmanagement-testphase} -\DeclareDocumentMetadata{pdfstandard=A-2b} +\DocumentMetadata{pdfstandard=A-2b} \makeatletter -\declare@file@substitution{doc.sty}{doc-v3beta.sty} +%\declare@file@substitution{doc.sty}{doc-v3beta.sty} \makeatother \documentclass{l3doc} \usepackage{tabularx,array,booktabs,hyperxmp} @@ -51,7 +51,7 @@ % }^^A % } % -% \date{Version 0.95i, released 2021-08-28} +% \date{Version 0.95j, released 2022-01-13} % % \maketitle % \begin{documentation} @@ -66,7 +66,7 @@ % \begin{verbatim} % \RequirePackage{pdfmanagement-testphase} % load the package % -% \DeclareDocumentMetadata % activate the PDF management (with options) +% \DocumentMetadata % activate the PDF management (with options) % { % % options % } @@ -76,6 +76,8 @@ % Note that the activation has to happen before the \cs{documentclass} declaration. % Because of this, the package needs loading with \cs{RequirePackage}. % +% Starting with LaTeX 2022-06-01 (or a suitable latex-dev) it is no longer necessary to +% load pdfmanagement-testphase manually, using \cs{DocumentMetadata} is enough. % % % \section*{Feedback wanted!} @@ -125,8 +127,9 @@ % written by the kernel directly and this can not be done without proper, % well-defined and well-behaving interfaces and hooks. % -% Some first steps for better support of PDF related commands have been already done -% with the \pkg{l3pdf} package which has now been integrated into \pkg{l3kernel}. +% Some first steps for better support of PDF related commands have been done +% with the \pkg{l3pdf} package which has now been integrated as a module +% into \pkg{l3kernel}. % It offers backend independent commands to create % PDF objects and destination, to set the compress level and the PDF version. % @@ -171,7 +174,7 @@ % % Loading the package will only \emph{load} the modules, % to \emph{activate} the core PDF management the trigger command -% \cs{DeclareDocumentMetadata} has to be used too. +% \cs{DocumentMetadata} has to be used too. % The loading and activation has to be done % \emph{before} the \cs{documentclass} command. % @@ -201,22 +204,24 @@ % \section{Use}\label{sec:use} % The package should be loaded before \cs{documentclass}. To activate % the resource management it should be followed by -% \cs{DeclareDocumentMetadata}\marg{key-val}. -% The options of \cs{DeclareDocumentMetadata} are described in the documentation of +% \cs{DocumentMetadata}\marg{key-val}. +% The options of \cs{DocumentMetadata} are described in the documentation of % \pkg{ltdocinit}. % % \begin{verbatim} % \RequirePackage{pdfmanagement-testphase} % load the package -% \DeclareDocumentMetadata % activates the PDF management interface +% % not needed with LaTeX 2022-06-01 +% \DocumentMetadata % activates the PDF management interface % { % %options % } % \documentclass {...} % \end{verbatim} % -% The PDF management can be deactivated either setting the key +% The PDF management can be deactivated either setting in the \texttt{debug} key +% the key % \texttt{pdfmanagement} to \texttt{false} or by commenting out -% the whole \cs{DeclareDocumentMetadata} declaration. +% the whole \cs{DocumentMetadata} declaration. % % To test if the PDF management is active the predicate % \cs{pdfmanagement_if_active:TF} can be used, see the documentation of \pkg{l3pdfmanagement}. @@ -250,7 +255,7 @@ % % \item[l3pdfmanagement] This is the core code of the PDF management. % -% \item[ltdocinit] This module provides the \cs{DeclareDocumentMetadata} command. +% \item[ltdocinit] This module provides the \cs{DocumentMetadata} command. % % \item[hyperref-generic] This module provides a new generic hyperref driver. % The driver will @@ -332,23 +337,23 @@ % Some patch code is provided by the bundle and loaded automatically, % but it is not complete currently. Failures are e.g. possible with complicated % author or title settings. The handling of dates isn't correct either yet. -% The patch code can be disabled by using |firstaidoff=hyperxmp| in \cs{DeclareDocumentMetadata} +% The patch code can be disabled by using |debug={firstaidoff=hyperxmp}| in \cs{DocumentMetadata} % % \subsection{tikz/pgf} % \pkg{pgf} writes to the page resources too and so is incompatible. The needed % changes are rather small and will be done in coordination with the maintainer. % Until this works, \pkg{pagemanagement} will load the patches automatically. -% This can be disabled by using |firstaidoff=pgf| in \cs{DeclareDocumentMetadata} +% This can be disabled by using |debug={firstaidoff=pgf}| in \cs{DocumentMetadata} % % \subsection{transparent} % The package \pkg{transparent} is incompatible. A replacement has been written % (\pkg{transparent-ltx}) and is loaded automatically. It requires a very recent % L3 programming layer! -% This can be disabled by using |firstaidoff=transparent| in \cs{DeclareDocumentMetadata} +% This can be disabled by using |debug={firstaidoff=transparent}| in \cs{DocumentMetadata} % \subsection{pdflscape} % The package \pkg{pdflscape} is incompatible. A replacement has been written % (\pkg{pdflscape-ltx}) and is loaded automatically. -% This can be disabled by using |firstaidoff=pdflscape| in \cs{DeclareDocumentMetadata} +% This can be disabled by using |debug={firstaidoff=pdflscape}| in \cs{DocumentMetadata} % % \subsection{colorspace} % The package is incompatible. Some patches @@ -384,7 +389,7 @@ % \begin{macrocode} %<@@=pdf> %<*package> -\ProvidesExplPackage{pdfmanagement-testphase}{2021-08-28}{0.95i} +\ProvidesExplPackage{pdfmanagement-testphase}{2022-01-13}{0.95j} {LaTeX PDF management testphase bundle} \providecommand\IfFormatAtLeastTF{\@ifl@t@r\fmtversion} \IfFormatAtLeastTF{2020-10-01}{}{ @@ -393,6 +398,7 @@ \MessageBreak Loading~is~aborted.}{} \DeclareOption { debug }{} \newcommand\DeclareDocumentMetadata[1]{} + \newcommand\DocumentMetadata[1]{} \ProcessOptions\relax } \IfFormatAtLeastTF{2020-10-01}{}{\endinput} @@ -411,13 +417,13 @@ % to allow to set it in the document. % \begin{macrocode} %<*header> -\ProvidesExplFile{pdfmanagement-testphase.ltx}{2021-08-28}{0.95i} +\ProvidesExplFile{pdfmanagement-testphase.ltx}{2022-01-13}{0.95j} {PDF~management~code~(testphase)} %</header> %<*package> %\RequirePackage{l3pdfdict} % needed by l3pdfmanagement %\RequirePackage{l3pdfmanagement} % loads the core code with the boolean -%\RequirePackage{ltdocinit} % DeclareDocumentMetadata, +%\RequirePackage{ltdocinit} % DocumentMetadata, %% can perhaps be combined or made optional ... %\RequirePackage{l3pdfannot} %\RequirePackage{l3pdfxform-beta} diff --git a/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.pdf b/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.pdf Binary files differindex 32ea161de1..70cf64c5c1 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.pdf +++ b/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.pdf diff --git a/macros/latex/contrib/pdfmanagement-testphase/transparent-ltx.sty b/macros/latex/contrib/pdfmanagement-testphase/transparent-ltx.sty index 61235bc846..f9987ba443 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/transparent-ltx.sty +++ b/macros/latex/contrib/pdfmanagement-testphase/transparent-ltx.sty @@ -3,7 +3,7 @@ %% a replacement for transparent sty from Heiko Oberdiek %% \NeedsTeXFormat{LaTeX2e}[2020/10/01] -\ProvidesExplPackage{transparent-ltx}{2021-08-28}{0.95i} +\ProvidesExplPackage{transparent-ltx}{2022-01-13}{0.95j} {Transparency with color stacks (replacement for transparent.sty from Heiko Oberdiek)}% \RequirePackage{l3opacity} diff --git a/macros/latex/contrib/pdfmanagement-testphase/xcolor-patches-tmp-ltx.sty b/macros/latex/contrib/pdfmanagement-testphase/xcolor-patches-tmp-ltx.sty index 45cd4413cf..5ff2ef0997 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/xcolor-patches-tmp-ltx.sty +++ b/macros/latex/contrib/pdfmanagement-testphase/xcolor-patches-tmp-ltx.sty @@ -1,6 +1,6 @@ %% LaTeX2e file `xcolor-patches.sty' %% -\ProvidesPackage{xcolor-patches-tmp-ltx}[2021-08-28 v0.95i patch xcolor for l3color] +\ProvidesPackage{xcolor-patches-tmp-ltx}[2022-01-13 v0.95j patch xcolor for l3color] \@ifundefined{color_set:nn}{\RequirePackage{l3color}}{} \ExplSyntaxOn diff --git a/macros/latex/contrib/siunitx/CHANGELOG.md b/macros/latex/contrib/siunitx/CHANGELOG.md index 4c603b08ae..649008576a 100644 --- a/macros/latex/contrib/siunitx/CHANGELOG.md +++ b/macros/latex/contrib/siunitx/CHANGELOG.md @@ -7,7 +7,13 @@ Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to ## [Unreleased] -## [v3.0.40]: 2022-01-12 +## [v3.0.41] - 2022-01-13 + +### Fixed +- Rounding to an uncertainty purely in the integer part (see issue + [\#568](https://github.com/josephwright/siunitx/issues/568)) + +## [v3.0.40] - 2022-01-12 ### Changed - Remove a deprecated `expl3` function @@ -1654,7 +1660,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.40...HEAD +[Unreleased]: https://github.com/josephwright/siunitx/compare/v3.0.41...HEAD +[v3.0.41]: https://github.com/josephwright/siunitx/compare/v3.0.40...v3.0.41 [v3.0.40]: https://github.com/josephwright/siunitx/compare/v3.0.39...v3.0.40 [v3.0.39]: https://github.com/josephwright/siunitx/compare/v3.0.38...v3.0.39 [v3.0.38]: https://github.com/josephwright/siunitx/compare/v3.0.37...v3.0.38 diff --git a/macros/latex/contrib/siunitx/siunitx-code.pdf b/macros/latex/contrib/siunitx/siunitx-code.pdf Binary files differindex a03f199dd8..b5922ebc96 100644 --- a/macros/latex/contrib/siunitx/siunitx-code.pdf +++ b/macros/latex/contrib/siunitx/siunitx-code.pdf diff --git a/macros/latex/contrib/siunitx/siunitx-number.dtx b/macros/latex/contrib/siunitx/siunitx-number.dtx index 97600d5d4b..a7bd0b7e16 100644 --- a/macros/latex/contrib/siunitx/siunitx-number.dtx +++ b/macros/latex/contrib/siunitx/siunitx-number.dtx @@ -2848,7 +2848,11 @@ \prg_replicate:nn { \int_max:nn - { 0 - ( \tl_count:n {#4} - \tl_count:n {#2} - #5 + 1 ) } + { + \tl_if_blank:nTF {#4} + { #5 } + { 0 - ( \tl_count:n {#4} - \tl_count:n {#2} - #5 + 1 ) } + } { 0 } } { 0 } diff --git a/macros/latex/contrib/siunitx/siunitx.dtx b/macros/latex/contrib/siunitx/siunitx.dtx index 2381945c38..35902e25c7 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} {2022-01-12} {3.0.40} +\ProvidesExplPackage {siunitx} {2022-01-13} {3.0.41} {A comprehensive (SI) units package} % \end{macrocode} % diff --git a/macros/latex/contrib/siunitx/siunitx.pdf b/macros/latex/contrib/siunitx/siunitx.pdf Binary files differindex 86ccfbcd8a..266462e8b6 100644 --- a/macros/latex/contrib/siunitx/siunitx.pdf +++ b/macros/latex/contrib/siunitx/siunitx.pdf diff --git a/macros/latex/contrib/tagpdf/README.md b/macros/latex/contrib/tagpdf/README.md index d21932976e..f614f459fa 100644 --- a/macros/latex/contrib/tagpdf/README.md +++ b/macros/latex/contrib/tagpdf/README.md @@ -1,6 +1,6 @@ #tagpdf — A package to create tagged pdf -Packageversion: 0.92 -Packagedate: 2021/08/27 +Packageversion: 0.93 +Packagedate: 2022/01/13 Author: Ulrike Fischer ## License @@ -10,29 +10,35 @@ The tagpdf package may be modified and distributed under the terms and condition ## Contents -- Readme (this file) -- tagpdf.sty (the sty) -- tagpdf-roles-code.sty (internal code) -- tagpdf-mc-code-shared.sty (internal code) -- tagpdf-mc-code-generic.sty (internal code) -- tagpdf-mc-code-lua.sty (internal code) -- tagpdf-struct-code.sty (internal code) -- tagpdf-tree-code.sty (internal code) -- tagpdf-space-code.sty (internal code) -- tagpdf-attr-code.sty (internal code) -- tagpdf-checks-code.sty (internal code) -- tagpdf-user.sty (user commands) -- tagpdf-pdftex.def (pdftex specific code) -- tagpdf-luatex.def (luatex specific code) -- tagpdf.lua (lua code for luatex) -- tagpdf.tex, tagpdf.pdf, tagpdf.bib, tagpdfdocu-patches.sty, - link-figure-input.tex, pac3.png (the docu) -- various examples (part of the documentation) +- README.md (this file) +- code files: + - tagpdf.ins + - tagpdf.dtx + - tagpdf-roles.dtx + - tagpdf-mc-shared.dtx + - tagpdf-mc-generic.dtx + - tagpdf-mc-lua.dtx + - tagpdf-struct.dtx + - tagpdf-tree.dtx + - tagpdf-space.dtx + - tagpdf-checks.dtx + - tagpdf-user.dtx +- documentation: + - tagpdf.pdf + - various examples (part of the documentation) +- source files for the documentation: + - tagpdf.tex + - tagpdf.bib + - tagpdfdocu-patches.sty, + - link-figure-input.tex + - pac3.png, global-ex.png ## Installation -Put the styles (with the exception of the tagpdfdocu-patches.sty), -the .def and the lua-files where it can be found. +At best use the package manager of your texsystem to install tagpdf. +For a manual installation run the .ins-file with latex and put the +created .sty, .def and .lua-files +where they can be found. ## Issues, comments, etc diff --git a/macros/latex/contrib/tagpdf/ex-AF-file.pdf b/macros/latex/contrib/tagpdf/ex-AF-file.pdf Binary files differindex a1b7db7c77..19a9d7b8ea 100644 --- a/macros/latex/contrib/tagpdf/ex-AF-file.pdf +++ b/macros/latex/contrib/tagpdf/ex-AF-file.pdf diff --git a/macros/latex/contrib/tagpdf/ex-AF-file.tex b/macros/latex/contrib/tagpdf/ex-AF-file.tex index 3e569807db..2282cd0026 100644 --- a/macros/latex/contrib/tagpdf/ex-AF-file.tex +++ b/macros/latex/contrib/tagpdf/ex-AF-file.tex @@ -1,26 +1,26 @@ % !Mode:: "TeX:DE:UTF-8:Main" -\RequirePackage{pdfmanagement-testphase} -\DeclareDocumentMetadata{ - pdfversion=2.0 - ,lang=de-DE - ,uncompress} +\IfFormatAtLeastTF{2022-06-01}{} + {\RequirePackage{pdfmanagement-testphase}} +\DocumentMetadata + { + uncompress, + pdfversion=2.0, + lang=de-DE, + testphase=tagpdf %load and activate tagpdf + } \documentclass{article} -\usepackage{tagpdf} \usepackage{iftex} -\tagpdfsetup{tabsorder=structure, - activate, - interwordspace - } +\tagpdfsetup{tabsorder=structure} -\iftutex +\ifluatex \usepackage{fontspec} \usepackage{unicode-math} \usepackage{luacode} \newfontface\zerowidthfont{freeserif} \else \usepackage[T1]{fontenc} -\fi +\fi \usepackage{graphicx} \begin{filecontents}{example-input-file.tex} @@ -29,6 +29,7 @@ Additional info! \begin{document} \pagestyle{empty} +\tagpdfparaOff %we don't want to nest paragraphs ... \ExplSyntaxOn diff --git a/macros/latex/contrib/tagpdf/ex-alt-actualtext-luatex.pdf b/macros/latex/contrib/tagpdf/ex-alt-actualtext-luatex.pdf Binary files differindex 3cda28e0da..d77cb67941 100644 --- a/macros/latex/contrib/tagpdf/ex-alt-actualtext-luatex.pdf +++ b/macros/latex/contrib/tagpdf/ex-alt-actualtext-luatex.pdf diff --git a/macros/latex/contrib/tagpdf/ex-alt-actualtext.tex b/macros/latex/contrib/tagpdf/ex-alt-actualtext.tex index 148a010701..ae44370152 100644 --- a/macros/latex/contrib/tagpdf/ex-alt-actualtext.tex +++ b/macros/latex/contrib/tagpdf/ex-alt-actualtext.tex @@ -8,7 +8,7 @@ \usepackage{tagpdf} \tagpdfsetup{tabsorder=structure, activate} -\usepackage{iftex} +\usepackage{iftex} \iftutex \usepackage{fontspec} \usepackage{unicode-math} @@ -26,6 +26,7 @@ % with pdflatex there is a encoding problem with the math \begin{document} +\tagpdfparaOff \pagestyle{empty} @@ -155,9 +156,9 @@ Etwas unmarkierter Text. actualtext=Ente, alttext=Dies ist eine Ente} %% a char is needed so that actualtext works, - \tagpdfifluatexTF + \ifluatex {{\zerowidthfont^^^^200c}}% - {\makebox[0pt][l]{.}}% + \else {\makebox[0pt][l]{.}} \fi% %it seems not to be needed for alttext and voice software .... \includegraphics[width=1cm]{example-image-duck} \tagmcend diff --git a/macros/latex/contrib/tagpdf/ex-attribute-luatex.pdf b/macros/latex/contrib/tagpdf/ex-attribute-luatex.pdf Binary files differindex f813c0e919..dc0d6b9df8 100644 --- a/macros/latex/contrib/tagpdf/ex-attribute-luatex.pdf +++ b/macros/latex/contrib/tagpdf/ex-attribute-luatex.pdf diff --git a/macros/latex/contrib/tagpdf/ex-attribute.pdf b/macros/latex/contrib/tagpdf/ex-attribute.pdf Binary files differdeleted file mode 100644 index 9871e6a033..0000000000 --- a/macros/latex/contrib/tagpdf/ex-attribute.pdf +++ /dev/null diff --git a/macros/latex/contrib/tagpdf/ex-formula-problem-luatex.pdf b/macros/latex/contrib/tagpdf/ex-formula-problem-luatex.pdf Binary files differindex 5a9f8e03a9..f470531f33 100644 --- a/macros/latex/contrib/tagpdf/ex-formula-problem-luatex.pdf +++ b/macros/latex/contrib/tagpdf/ex-formula-problem-luatex.pdf diff --git a/macros/latex/contrib/tagpdf/ex-mc-manual-para-split.pdf b/macros/latex/contrib/tagpdf/ex-mc-manual-para-split-obsolete.pdf Binary files differindex 3dedd62f26..6fcda263ce 100644 --- a/macros/latex/contrib/tagpdf/ex-mc-manual-para-split.pdf +++ b/macros/latex/contrib/tagpdf/ex-mc-manual-para-split-obsolete.pdf diff --git a/macros/latex/contrib/tagpdf/ex-mc-manual-para-split.tex b/macros/latex/contrib/tagpdf/ex-mc-manual-para-split-obsolete.tex index d89e3601f4..92966275c5 100644 --- a/macros/latex/contrib/tagpdf/ex-mc-manual-para-split.tex +++ b/macros/latex/contrib/tagpdf/ex-mc-manual-para-split-obsolete.tex @@ -1,11 +1,17 @@ % !Mode:: "TeX:DE:UTF-8:Main" % !!!!!!!!!!!!!!!!! +% Obsolete example! +% !!!!!!!!!!!!!!!! % This test files shows how to add a manual page split. % It *only* handles the mc-step in the page stream. % Structure commands and all the related management are not % involved. So it also only uses activate-mc. +% It is obsolete as the current tagpdf version now handles the +% page split automatically. To keep the example working this is disabled +% below with \csname __tag_mc_disable_marks:\endcsname + \RequirePackage{pdfmanagement-testphase} \DeclareDocumentMetadata{pdfversion=1.7,uncompress} \documentclass{book} @@ -17,7 +23,7 @@ \iftutex \usepackage{fontspec} \usepackage{luacode} -\else +\else \usepackage[T1]{fontenc} \fi @@ -31,8 +37,10 @@ \pagestyle{fancy} \fancyhf{} -\cfoot{\tagmcbegin{artifact=pagination}\thepage\tagmcend} \begin{document} +%disable the automatic page break handler: +\csname __tag_mc_disable_marks:\endcsname + \tagmcbegin{tag=P} Cras egestas ipsum a nisl. Vivamus varius dolor ut dolor. Fusce vel enim. Pellentesque accumsan ligula et eros. Cras diff --git a/macros/latex/contrib/tagpdf/ex-patch-list-luatex.pdf b/macros/latex/contrib/tagpdf/ex-patch-list-luatex.pdf Binary files differindex 9ddd1a9f99..d432342c1e 100644 --- a/macros/latex/contrib/tagpdf/ex-patch-list-luatex.pdf +++ b/macros/latex/contrib/tagpdf/ex-patch-list-luatex.pdf diff --git a/macros/latex/contrib/tagpdf/ex-patch-list-obsolete.tex b/macros/latex/contrib/tagpdf/ex-patch-list-obsolete.tex new file mode 100644 index 0000000000..7245dd39b8 --- /dev/null +++ b/macros/latex/contrib/tagpdf/ex-patch-list-obsolete.tex @@ -0,0 +1,100 @@ +% !Mode:: "TeX:DE:UTF-8:Main" + + +%!! Obsolete example as it uses manual tagging of paragraph. +% Check the newer version ex-patch-list for a simpler version! + +%This example shows how one can patch lists command +%it is based on enumitem + +%It uses a command to end \item (\meti). It is perhaps possible to hide this command +% inside \item/end{list}, but with nested list it is not so easy. + +% not really up-to-date, with paratagging one could simplify things. + +% Pay attention to casing. Li/LI, Lbody/Lbody are different. +%no page break involved. So the example works in lua and generic mode +\RequirePackage{pdfmanagement-testphase} +\DeclareDocumentMetadata{pdfversion=1.7,uncompress} + +\documentclass{scrbook} +\usepackage[english]{babel} +\usepackage{tagpdf} + +\usepackage{iftex} +\iftutex + \usepackage{fontspec} + \usepackage{luacode} +\else + \usepackage[T1]{fontenc} +\fi + + + +\tagpdfsetup{tabsorder=structure, + activate, + } + +\usepackage{lipsum}%\textheight3cm + +\usepackage{enumitem,xpatch} + +\makeatletter + +\newcommand\tag@enit@format@preset[1]{% + \tagstructbegin{tag=LI}% + \tagstructbegin{tag=Lbl}% + \tagmcbegin{tag=Lbl}% + #1% + \tagmcend + \tagstructend %end Lbl + \tagstructbegin{tag=LBody}} + +\newcommand\meti{% end of \item + \tagstructend %end of LBody + \tagstructend %end of LI +} + +\xpatchcmd\enit@preset{\@firstofone}{\tag@enit@format@preset}{}{\fail} + +\setlist{ + before*=\tagstructbegin{tag=L}, + after*={\tagstructend}} + +% keys that overwrite \enit@format must be patched, eg like the follow +% the font key should be patched in a similar way +\enitkv@key{enumitem}{format}{% + \def\enit@format{% + \tagstructbegin{tag=LI}% + \tagstructbegin{tag=Lbl}% + \tagmcbegin{tag=Lbl}% + #1\tagmcend}} +\makeatother +% marking of the text inside the list can not be handled automatically -- one doesn't know the type +% we use simple P here +\newcommand\TAGP{\tagstructbegin{tag=P}\tagmcbegin{tag=P}} +\newcommand\PGAT{\tagmcend\tagstructend} + +\begin{document} +%I don't want to handle pagestyles, so set everything to empty: +\pagestyle{empty}\renewcommand\chapterpagestyle{empty} + + + +\begin{itemize} +\item \TAGP Ducks say quack\PGAT\meti +\item \TAGP Marmots say something Parmotlike\PGAT\meti +\end{itemize} + +\begin{enumerate} +\item \TAGP The highest pass is the Col de l'Iseran.\PGAT\meti +\item \TAGP The second highest pass is the Passo dello Stelvio.\PGAT\meti +\end{enumerate} + +\begin{description} +\item[ducks] \TAGP yellow\PGAT\meti +\item[marmots] \TAGP brown\PGAT\meti +\end{description} + + +\end{document}
\ No newline at end of file diff --git a/macros/latex/contrib/tagpdf/ex-patch-list.tex b/macros/latex/contrib/tagpdf/ex-patch-list.tex index d6485c86fe..30448c6a80 100644 --- a/macros/latex/contrib/tagpdf/ex-patch-list.tex +++ b/macros/latex/contrib/tagpdf/ex-patch-list.tex @@ -1,24 +1,25 @@ % !Mode:: "TeX:DE:UTF-8:Main" -%This example shows how one can patch lists command -%it is based on enumitem +% This example shows how one can patch lists command +% it is based on enumitem -%It uses a command to end \item (\meti). It is perhaps possible to hide this command -% inside \item/end{list}, but with nested list it is not so easy. +% Pay attention to casing. Li/LI, Lbody/Lbody are different. -% not really up-to-date, with paratagging one could simplify things. +% It doesn't test nesting! + +% We are using \DocumentMetadata +% This requires a new pdfmanagement and/or latex-dev! +% Older systems should use \DeclareDocumentMetadata +\IfFormatAtLeastTF{2022-06-01}{} + {\RequirePackage{pdfmanagement-testphase}} +\DocumentMetadata{pdfversion=1.7,uncompress,testphase=tagpdf} -% Pay attention to casing. Li/LI, Lbody/Lbody are different. -%no page break involved. So the example works in lua and generic mode -\RequirePackage{pdfmanagement-testphase} -\DeclareDocumentMetadata{pdfversion=1.7,uncompress} \documentclass{scrbook} \usepackage[english]{babel} -\usepackage{tagpdf} \usepackage{iftex} -\iftutex +\ifluatex \usepackage{fontspec} \usepackage{luacode} \else @@ -27,49 +28,53 @@ -\tagpdfsetup{tabsorder=structure, - activate, - } +\tagpdfsetup + { + tabsorder=structure, + } \usepackage{lipsum}%\textheight3cm \usepackage{enumitem,xpatch} -\makeatletter +% At first we add to the begin/end hooks the structure commands. +% To avoid problems with nested paragraphs we force a new paragraph for now. +% Real code should avoid that! +\AddToHook{env/itemize/begin}{\par\tagstructbegin{tag=L}}%\par is needed to close the paragraph before. +\AddToHook{env/itemize/end}{\par\tagstructend\tagstructend\tagstructend}%LBody,LI,L +\AddToHook{env/enumerate/begin}{\par\tagstructbegin{tag=L}} +\AddToHook{env/enumerate/end}{\par\tagstructend\tagstructend\tagstructend}%LBody,LI,L +\AddToHook{env/description/begin}{\par\tagstructbegin{tag=L}} +\AddToHook{env/description/end}{\par\tagstructend\tagstructend\tagstructend}%LBody,LI,L +\makeatletter +\ExplSyntaxOn +%We detect is this is the first or a follow up item where we have to end a structure first: \newcommand\tag@enit@format@preset[1]{% - \tagstructbegin{tag=LI}% - \tagstructbegin{tag=Lbl}% - \tagmcbegin{tag=Lbl}% - #1% + \str_if_eq:eeTF { \prop_item:cn { g__tag_struct_\g__tag_struct_stack_current_tl _prop }{S} }{/L} + { + %\typeout{BEGIN~OF~LIST} + } + {%\typeout{NEXT ITEM} + \tagstructend\tagstructend} % for the LBody/LI + \tagstructbegin{tag=LI} + \tagstructbegin{tag=Lbl} + \tagmcbegin{tag=Lbl} + #1 \tagmcend - \tagstructend %end Lbl - \tagstructbegin{tag=LBody}} - -\newcommand\meti{% end of \item - \tagstructend %end of LBody - \tagstructend %end of LI -} + \tagstructend + \tagstructbegin{tag=LBody} + } + +\ExplSyntaxOff \xpatchcmd\enit@preset{\@firstofone}{\tag@enit@format@preset}{}{\fail} +%close mc from paratagging and reopen ... +\xpatchcmd\@item{\box\@labels}{\tagmcend \box\@labels \tagmcbegin{tag=P}}{}{\fail} -\setlist{ - before*=\tagstructbegin{tag=L}, - after*={\tagstructend}} - -% keys that overwrite \enit@format must be patched, eg like the follow -% the font key should be patched in a similar way -\enitkv@key{enumitem}{format}{% - \def\enit@format{% - \tagstructbegin{tag=LI}% - \tagstructbegin{tag=Lbl}% - \tagmcbegin{tag=Lbl}% - #1\tagmcend}} \makeatother -% marking of the text inside the list can not be handled automatically -- one doesn't know the type -% we use simple P here -\newcommand\TAGP{\tagstructbegin{tag=P}\tagmcbegin{tag=P}} -\newcommand\PGAT{\tagmcend\tagstructend} + + \begin{document} %I don't want to handle pagestyles, so set everything to empty: @@ -78,18 +83,18 @@ \begin{itemize} -\item \TAGP Ducks say quack\PGAT\meti -\item \TAGP Marmots say something Parmotlike\PGAT\meti +\item Ducks say quack +\item Marmots say something Parmotlike \end{itemize} \begin{enumerate} -\item \TAGP The highest pass is the Col de l'Iseran.\PGAT\meti -\item \TAGP The second highest pass is the Passo dello Stelvio.\PGAT\meti +\item The highest pass is the Col de l'Iseran. +\item The second highest pass is the Passo dello Stelvio. \end{enumerate} \begin{description} -\item[ducks] \TAGP yellow\PGAT\meti -\item[marmots] \TAGP brown\PGAT\meti +\item[ducks] yellow +\item[marmots] brown \end{description} diff --git a/macros/latex/contrib/tagpdf/ex-patch-sectioning-koma-luatex.pdf b/macros/latex/contrib/tagpdf/ex-patch-sectioning-koma-luatex.pdf Binary files differindex c0e033318c..2b76c005a8 100644 --- a/macros/latex/contrib/tagpdf/ex-patch-sectioning-koma-luatex.pdf +++ b/macros/latex/contrib/tagpdf/ex-patch-sectioning-koma-luatex.pdf diff --git a/macros/latex/contrib/tagpdf/ex-patch-sectioning-koma.pdf b/macros/latex/contrib/tagpdf/ex-patch-sectioning-koma.pdf deleted file mode 100644 index 4b1ceb47ad..0000000000 --- a/macros/latex/contrib/tagpdf/ex-patch-sectioning-koma.pdf +++ /dev/null @@ -1,2134 +0,0 @@ -%PDF-1.7 -% -11 0 obj -<< /MCID 0 >> -endobj -16 0 obj -<< /MCID 1 >> -endobj -18 0 obj -<< /MCID 2 >> -endobj -20 0 obj -<< /MCID 3 >> -endobj -23 0 obj -<< /MCID 4 >> -endobj -25 0 obj -<< /MCID 5 >> -endobj -28 0 obj -<< /MCID 6 >> -endobj -30 0 obj -<< /MCID 7 >> -endobj -32 0 obj -<< /MCID 8 >> -endobj -35 0 obj -<< /MCID 9 >> -endobj -37 0 obj -<< /MCID 10 >> -endobj -39 0 obj -<< /MCID 11 >> -endobj -41 0 obj -<< -/Length 5594 ->> -stream -/opacity1 gs -/H1 /l3pdf1 BDC -BT -/F32 20.6625 Tf 59.528 690.672 Td [(Contents)]TJ -ET -EMC -/Lbl /l3pdf2 BDC -BT -/F29 10.9091 Tf 59.528 653.751 Td [(1)]TJ -ET -EMC -/P /l3pdf3 BDC -BT -/F29 10.9091 Tf 75.798 653.751 Td [(c)28(hapter)]TJ -ET -EMC -/Reference /l3pdf4 BDC -BT -/F29 10.9091 Tf 470.797 653.751 Td [(3)]TJ -ET -EMC -/P /l3pdf5 BDC -BT -/F29 10.9091 Tf 59.528 629.354 Td [(c)28(hapter)]TJ -ET -EMC -/Reference /l3pdf6 BDC -BT -/F29 10.9091 Tf 470.797 629.354 Td [(5)]TJ -ET -EMC -/Lbl /l3pdf7 BDC -BT -/F29 10.9091 Tf 75.798 615.805 Td [(1.1)]TJ -ET -EMC -/P /l3pdf8 BDC -BT -/F29 10.9091 Tf 100.747 615.805 Td [(section)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 138.478 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 146.947 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 155.416 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 163.885 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 172.355 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 180.824 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 189.293 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 197.762 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 206.231 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 214.701 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 223.17 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 231.639 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 240.108 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 248.578 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 257.047 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 265.516 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 273.985 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 282.454 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 290.924 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 299.393 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 307.862 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 316.331 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 324.801 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 333.27 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 341.739 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 350.208 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 358.677 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 367.147 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 375.616 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 384.085 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 392.554 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 401.023 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 409.493 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 417.962 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 426.431 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 434.9 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 443.37 615.805 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 451.839 615.805 Td [(.)]TJ -ET -EMC -/Reference /l3pdf9 BDC -BT -/F29 10.9091 Tf 470.797 615.805 Td [(5)]TJ -ET -EMC -/Lbl /l3pdf10 BDC -BT -/F29 10.9091 Tf 100.747 602.256 Td [(1.1.1)]TJ -ET -EMC -/P /l3pdf11 BDC -BT -/F29 10.9091 Tf 135.458 602.256 Td [(subsection)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 189.293 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 197.762 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 206.231 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 214.701 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 223.17 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 231.639 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 240.108 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 248.578 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 257.047 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 265.516 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 273.985 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 282.454 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 290.924 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 299.393 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 307.862 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 316.331 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 324.801 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 333.27 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 341.739 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 350.208 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 358.677 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 367.147 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 375.616 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 384.085 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 392.554 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 401.023 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 409.493 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 417.962 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 426.431 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 434.9 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 443.37 602.256 Td [(.)]TJ -ET -EMC -/Artifact BMC -BT -/F29 10.9091 Tf 451.839 602.256 Td [(.)]TJ -ET -EMC -/Reference /l3pdf12 BDC -BT -/F29 10.9091 Tf 470.797 602.256 Td [(5)]TJ -ET -EMC - -endstream -endobj -12 0 obj -<< -/Type /Page -/Contents 41 0 R -/Resources 40 0 R -/MediaBox [0 0 595.276 841.89] -/Tabs /S /StructParents 0 -/Parent 44 0 R ->> -endobj -40 0 obj -<< -/Properties <</l3pdf1 11 0 R /l3pdf2 16 0 R /l3pdf3 18 0 R /l3pdf4 20 0 R /l3pdf5 23 0 R /l3pdf6 25 0 R /l3pdf7 28 0 R /l3pdf8 30 0 R /l3pdf9 32 0 R /l3pdf10 35 0 R /l3pdf11 37 0 R /l3pdf12 39 0 R >>/ExtGState 1 0 R -/Font << /F32 42 0 R /F29 43 0 R >> -/ProcSet [ /PDF /Text ] ->> -endobj -47 0 obj -<< -/Length 13 ->> -stream -/opacity1 gs - -endstream -endobj -46 0 obj -<< -/Type /Page -/Contents 47 0 R -/Resources 45 0 R -/MediaBox [0 0 595.276 841.89] -/Tabs /S /StructParents 1 -/Parent 44 0 R ->> -endobj -45 0 obj -<< -/ExtGState 1 0 R -/ProcSet [ /PDF ] ->> -endobj -49 0 obj -<< /MCID 0 >> -endobj -51 0 obj -<< /MCID 1 >> -endobj -53 0 obj -<< -/Length 157 ->> -stream -/opacity1 gs -/H1 /l3pdf13 BDC -BT -/F32 20.6625 Tf 59.528 690.672 Td [(1)]TJ -ET -EMC -/H1 /l3pdf14 BDC -BT -/F32 20.6625 Tf 83.699 690.672 Td [(chapter)]TJ -ET -EMC - -endstream -endobj -50 0 obj -<< -/Type /Page -/Contents 53 0 R -/Resources 52 0 R -/MediaBox [0 0 595.276 841.89] -/Tabs /S /StructParents 2 -/Parent 44 0 R ->> -endobj -52 0 obj -<< -/Properties <</l3pdf13 49 0 R /l3pdf14 51 0 R >>/ExtGState 1 0 R -/Font << /F32 42 0 R >> -/ProcSet [ /PDF /Text ] ->> -endobj -56 0 obj -<< -/Length 13 ->> -stream -/opacity1 gs - -endstream -endobj -55 0 obj -<< -/Type /Page -/Contents 56 0 R -/Resources 54 0 R -/MediaBox [0 0 595.276 841.89] -/Tabs /S /StructParents 3 -/Parent 44 0 R ->> -endobj -54 0 obj -<< -/ExtGState 1 0 R -/ProcSet [ /PDF ] ->> -endobj -58 0 obj -<< /MCID 0 >> -endobj -61 0 obj -<< /MCID 1 >> -endobj -62 0 obj -<< /MCID 2 >> -endobj -64 0 obj -<< /MCID 3 >> -endobj -65 0 obj -<< /MCID 4 >> -endobj -67 0 obj -<< /MCID 5 >> -endobj -68 0 obj -<< /MCID 6 >> -endobj -70 0 obj -<< /MCID 7 >> -endobj -1 0 obj -<< /opacity1 <</ca 1/CA 1>> >> -endobj -72 0 obj -<< -/Length 595 ->> -stream -/opacity1 gs -/H1 /l3pdf15 BDC -BT -/F32 20.6625 Tf 59.528 690.672 Td [(chapter)]TJ -ET -EMC -/H2 /l3pdf16 BDC -BT -/F41 14.3462 Tf 59.528 649.367 Td [(1.1)]TJ -ET -EMC -/H2 /l3pdf17 BDC -BT -/F41 14.3462 Tf 88.826 649.367 Td [(section)]TJ -ET -EMC -/H3 /l3pdf18 BDC -BT -/F42 11.9552 Tf 59.528 624.619 Td [(1.1.1)]TJ -ET -EMC -/H3 /l3pdf19 BDC -BT -/F42 11.9552 Tf 93.89 624.619 Td [(subsection)]TJ -ET -EMC -/H4 /l3pdf20 BDC -EMC -/H4 /l3pdf21 BDC -BT -/F31 10.9091 Tf 59.528 604.026 Td [(subsubsection)]TJ -ET -EMC -/P /l3pdf22 BDC -BT -/F29 10.9091 Tf 59.528 583.433 Td [(a)-331(paragraph)]TJ 10.847 -13.549 Td [(x)]TJ -ET -EMC - -endstream -endobj -59 0 obj -<< -/Type /Page -/Contents 72 0 R -/Resources 71 0 R -/MediaBox [0 0 595.276 841.89] -/Tabs /S /StructParents 4 -/Parent 44 0 R ->> -endobj -71 0 obj -<< -/Properties <</l3pdf15 58 0 R /l3pdf16 61 0 R /l3pdf17 62 0 R /l3pdf18 64 0 R /l3pdf19 65 0 R /l3pdf20 67 0 R /l3pdf21 68 0 R /l3pdf22 70 0 R >>/ExtGState 1 0 R -/Font << /F32 42 0 R /F41 73 0 R /F42 74 0 R /F31 75 0 R /F29 43 0 R >> -/ProcSet [ /PDF /Text ] ->> -endobj -76 0 obj -<< /Marked true >> -endobj -6 0 obj -<< /Nums [0 [ 10 0 R 15 0 R 17 0 R 19 0 R 22 0 R 24 0 R 27 0 R 29 0 R 31 0 R 34 0 R 36 0 R 38 0 R ] -1 [ ] -2 [ 48 0 R 48 0 R ] -3 [ ] -4 [ 57 0 R 60 0 R 60 0 R 63 0 R 63 0 R 66 0 R 66 0 R 69 0 R ] -] >> -endobj -7 0 obj -<< /DocumentFragment /Art /Aside /Note /Title /H1 /Sub /Span /H7 /H6 /H8 /H6 /H9 /H6 /H10 /H6 /FENote /Note /Em /Span /Strong /Span >> -endobj -8 0 obj -[ ] -endobj -9 0 obj -<< /Type /StructElem /S /Document /P 5 0 R /K [10 0 R 13 0 R 48 0 R 57 0 R 60 0 R 63 0 R 66 0 R 69 0 R] >> -endobj -10 0 obj -<< /Type /StructElem /S /H1 /P 9 0 R /K <</Type /MCR /Pg 12 0 R/MCID 0>> >> -endobj -13 0 obj -<< /Type /StructElem /S /TOC /P 9 0 R /K [14 0 R 21 0 R 26 0 R 33 0 R] >> -endobj -14 0 obj -<< /Type /StructElem /S /TOCI /P 13 0 R /K [15 0 R 17 0 R 19 0 R] >> -endobj -15 0 obj -<< /Type /StructElem /S /Lbl /P 14 0 R /K <</Type /MCR /Pg 12 0 R/MCID 1>> >> -endobj -17 0 obj -<< /Type /StructElem /S /P /P 14 0 R /K <</Type /MCR /Pg 12 0 R/MCID 2>> >> -endobj -19 0 obj -<< /Type /StructElem /S /Reference /P 14 0 R /K <</Type /MCR /Pg 12 0 R/MCID 3>> >> -endobj -21 0 obj -<< /Type /StructElem /S /TOCI /P 13 0 R /K [22 0 R 24 0 R] >> -endobj -22 0 obj -<< /Type /StructElem /S /P /P 21 0 R /K <</Type /MCR /Pg 12 0 R/MCID 4>> >> -endobj -24 0 obj -<< /Type /StructElem /S /Reference /P 21 0 R /K <</Type /MCR /Pg 12 0 R/MCID 5>> >> -endobj -26 0 obj -<< /Type /StructElem /S /TOCI /P 13 0 R /K [27 0 R 29 0 R 31 0 R] >> -endobj -27 0 obj -<< /Type /StructElem /S /Lbl /P 26 0 R /K <</Type /MCR /Pg 12 0 R/MCID 6>> >> -endobj -29 0 obj -<< /Type /StructElem /S /P /P 26 0 R /K <</Type /MCR /Pg 12 0 R/MCID 7>> >> -endobj -31 0 obj -<< /Type /StructElem /S /Reference /P 26 0 R /K <</Type /MCR /Pg 12 0 R/MCID 8>> >> -endobj -33 0 obj -<< /Type /StructElem /S /TOCI /P 13 0 R /K [34 0 R 36 0 R 38 0 R] >> -endobj -34 0 obj -<< /Type /StructElem /S /Lbl /P 33 0 R /K <</Type /MCR /Pg 12 0 R/MCID 9>> >> -endobj -36 0 obj -<< /Type /StructElem /S /P /P 33 0 R /K <</Type /MCR /Pg 12 0 R/MCID 10>> >> -endobj -38 0 obj -<< /Type /StructElem /S /Reference /P 33 0 R /K <</Type /MCR /Pg 12 0 R/MCID 11>> >> -endobj -48 0 obj -<< /Type /StructElem /S /H1 /P 9 0 R /K [<</Type /MCR /Pg 50 0 R/MCID 0>> <</Type /MCR /Pg 50 0 R/MCID 1>>] >> -endobj -57 0 obj -<< /Type /StructElem /S /H1 /P 9 0 R /K <</Type /MCR /Pg 59 0 R/MCID 0>> >> -endobj -60 0 obj -<< /Type /StructElem /S /H2 /P 9 0 R /K [<</Type /MCR /Pg 59 0 R/MCID 1>> <</Type /MCR /Pg 59 0 R/MCID 2>>] >> -endobj -63 0 obj -<< /Type /StructElem /S /H3 /P 9 0 R /K [<</Type /MCR /Pg 59 0 R/MCID 3>> <</Type /MCR /Pg 59 0 R/MCID 4>>] >> -endobj -66 0 obj -<< /Type /StructElem /S /H4 /P 9 0 R /K [<</Type /MCR /Pg 59 0 R/MCID 5>> <</Type /MCR /Pg 59 0 R/MCID 6>>] >> -endobj -69 0 obj -<< /Type /StructElem /S /P /P 9 0 R /K <</Type /MCR /Pg 59 0 R/MCID 7>> /ActualText <FEFF0061006200630021> >> -endobj -5 0 obj -<< /Type /StructTreeRoot /K 9 0 R /ParentTree 6 0 R /RoleMap 7 0 R /Namespaces 8 0 R >> -endobj -78 0 obj -[565 489.6 565 502.5 336.6 550.8 565 259 289.6 534.4 259 871 565 550.8 565 565 374.3 422.3 397.8 565] -endobj -79 0 obj -[312.4 562.4 562.4 562.4 562.4 562.4 562.4 562.4 562.4 562.4 562.4 562.4 312.4 312.4 874.8 874.8 874.8 531.1 749.8 742.9 746.3 718.6 808.8 671.1 639.9 749.8 786.8 305.5 527.6 774.1 608.6 974.3 786.8 830.8 715.1 830.8 724.4 624.8 768.3 764.9 742.9 1055.3 742.9 742.9 687.3 339 562.4 339 687.3 874.8 312.4 539.2 578.6 499.9 578.6 510.9 343.7 562.4 578.6 266.1 297.4 547.3 266.1 891 578.6 562.4 578.6 578.6 383 431.1 406.1 578.6] -endobj -80 0 obj -[319.1 574.4 574.4 574.4 574.4 574.4 574.4 574.4 574.4 574.4 574.4 574.4 319.1 319.1 893.5 893.5 893.5 542.5 765.8 767.2 766.5 733.9 830.3 681.6 649.7 765.8 820.1 320.4 543.1 799.1 617.8 1011.6 820.1 840.5 734.6 840.5 740 638.2 776.7 793.6 767.2 1086.3 767.2 767.2 702 348.3 574.4 348.3 702 893.5 319.1 550.7 590.8 510.6 590.8 523.9 351 574.4 590.8 271.7 303.7 558.9 271.7 909.9 590.8 574.4 590.8 590.8 391.2 440.4 414.8] -endobj -81 0 obj -[276.4 497.2 497.2 497.2 497.2 497.2 497.2 497.2 497.2 497.2 497.2 497.2 276.4 276.4 773.2 773.2 773.2 469.6 773.2 745.3 704 718 759.2 676.4 648.8 780 745.3 358.9 510.8 772.9 621.2 910.9 745.3 773.2 676.4 773.2 731.6 552.4 718 745.3 745.3 1021.3 745.3 745.3 607.6 276.4 497.2 276.4 607.6 773.2 276.4 497.2 552.4 442 552.4 442 304 497.2 552.4 276.4 304 524.8 276.4 828.4 552.4 497.2 552.4 524.8 386.8 392.3 386.8 552.4 524.8 718 524.8] -endobj -82 0 obj -[584.9 584.9 584.9 584.9 584.9 584.9 584.9 584.9 584.9 325 325 909.9 909.9 909.9 552.4 779.9 781.2 780.6 747.4 845.5 706.8 674.3 779.9 822.5 326.3 553.1 813.7 641.8 1017.4 822.5 868.6 748.1 868.6 759.9 649.9 803.6 801.8 781.2 1106.2 781.2 781.2 714.9 343.9 584.9 343.9 714.9 909.9 325 562.8 605.7 519.9 605.7 522.6 357.5 584.9 605.7 280.8 313.3 573.2 280.8 930.7 605.7 584.9 605.7 605.7 400.3 448.4 422.4] -endobj -83 0 obj -<< -/Length1 721 -/Length2 14150 -/Length3 0 -/Length 14871 ->> -stream -%!FontType1-1.0: SFRM1095 0.3 -%%CreationDate: Wed Sep 12 2001 -% Copyright (c) 2001 Vladimir Volovich <vvv@vsu.ru>. -% See the file COPYING (GNU General Public License) for license conditions. -% Converted from METAFONT EC/TC and LH fonts: -% ecrm1095, tcrm1095, larm1095, lbrm1095, lcrm1095, rxrm1095. -11 dict begin -/FontInfo 6 dict dup begin -/version (0.3) def -/FullName (Computer Modern Roman) def -/FamilyName (Computer Modern) def -/ItalicAngle 0 def -/isFixedPitch false def -/Weight (Medium) def -end readonly def -/FontName /HHSFZO+SFRM1095 def -/Encoding StandardEncoding def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] def -/FontBBox{-188 -320 1445 942}readonly def -currentdict end -currentfile eexec -oc;j~EЪ+`U+1;[ihd_Twρb=I"aě!]#g~Q^VmcNtقP*4Jq=G1`ސnG)]'Ze+hb?%_hpY5(9Թ-H$-:ynK")cff,vrG+@) -`{/}*D@Vٴ:Ix`(]-.a1ŗ/O)@0p<n-fe̸=yrB<S'Z챒ZyDX㣢}'MZc|-5,fש39٦4y5+:
g}`)H@ R/{x}PzH2LK$Q "jGϜd;'w-+=0"e<a{6 -oK^"]npY\NCE,pJ˪ڻWGBdSQis;叮՝dɷziR?X<nJgD -AwkR+-]&9Ze"J{|+<+r3K0Dw(
yVRfۢOű8EFxx~lϧA&۫+|~n0+=K9ʧ) -C*j -ʢضʸ -Fo?apt#`J68%`o -1=31#QtP#Y?>IѹB@=TLX+2*"V&uNQXKfHt*NxsH*J1Kl<OFxgt#Lڟl&!^cnԘ,ҷe4I>a C^B -R];{ܻb9|4A_cؤ1t-b0q+E0Lf1XwcU?3B0Y>҉m'D&G;GwV![ŘҭckdmuV~w^Wc Pesoph>5T&^WUۉ) -ǗNhSHWd<]"}[w"L9 !0G7!l_gג.V͇b>*[ -V8hn^$w8"."~ bG!eIxJu[Q[HШQ&Kp5d %f -`R^g
)alCY
5ÌG̖) #|FrHY\ISާ)dPbXOPʶ|b¢D,<qULQzJXW!wShn BdcP0Y>҉m'eHUDџ6D{zr#}q]`ќd!ea"\9E9D*R1[6gw}ϰ@8 -* -sZd<"sXAyt`ve -e|r5|7* -}V!PFq:b?`29Ҿ
. Ac BxwQz6䴊Y(Ub`ؓȇ·svJ[ -v~ -u@5/V_-/^^dHZZVXGBѢX -%z"QųoŹDEZYGqlP:!eVX~[l$3jY XU}6y~^yOOy,Io\o7WQ]f?:uEYRD|IMJ5wt(ڕL)HkԉqXI[0u8l@V62N$*,!94&LҾ!"7o$?i[Y>9iue!H(ds,3'1[͞L̈<!^Phx&^@ݥ
{~!<ن`:y&_a5TX2zzH+3ږA8G?O?Ml - -F?5gH3Qɼe'i7&9Y+BI'o,l686h?c)CTrH!7a=1awscpDHaKҏR6<}[/Uذ3qЀBJɌ2W"`6G1/CPuY<$W86%,H9qyH3pWz"#\tK6=k -?m? -EK=ie~hACVS'BZ",-C`{F)Ђ_I$Lb{apys̠\[447?TMd~$%, ogASi%GAn@ sy]pq!ldKnr? \":.Zt&uqxN*ZjRT*dr 5߆/F`꾢)-Iѯ;a7hE?bV~B4Uװg>6j3e 7a0U -ˁ1纷pN8Y!7_3)o^Z@]_?U'
p̬{uA"o%\g7xZ3gVU?8"_a&wl
(ؑiɍ$k":n2Xm*QՎI5W0Q/\# ҡu93ZDQx$ -ajKr6JcZ|{y7W >aDS36 -X0}!3He
65+o -.+>ǗsP%gwe7|T rXL$b& -r>xz:\i:Va kzC~S~Sƾ~)گ]1Kֿ -dL`|VcH)>}z4Ssh c*b
aŢF+r\7wV{8RlGёPw=K'Ǒw
-إn;u˾#SoҦd-.nLp%N<ifj, -(CZ߮C>"sd~_{I<i_!J/7x飠5xuu`s_z9JnG$k2'& TS!i41Bۨ}:"k}ߩf&'u"23C{ ~)Ū3zF!+J8 -wSZS;Ve
JJjgx}Z' -bGI3OW rNAc,[@ҋN7Ф<,<}o@rW\fv=ҊA =bSk FCry.Gܭٌ`](x-NW2k!BhVW@?,[- ^`{p ۡ9PP,&I6`f㩹uKoǴ9Kyb_mô5+?sV -0C
5;{%+&ve
N%3]MRhYDT{]N=.\o!jX]V>M9ZɃS!DcSYl1W]f -KD{6sH^S Ub˾]/b|]hcpR)3qK0!a)dM`®Ss"HzSLg>Yt -g5g
i"; Zuk=V~ӂ-+
qlhUMe$uqP須4<kū[{+S{SJ)E..qZJj&@Ll4L-0ٳV<5rbY) [p[,eŴNhye,ɤK2TC?-=dCs:hT~gXݵknXwh&{i^9z^I54#O&eI&fdMIo8/~]R(+ԼAcU#KQگ(]'*O௷RpR~$b.@%xaYRR=D7LDA=Ad#Sާ-%ݐS0op"Q¼s%9Vxz3w(_/롘ydqEHDd()lF}/QC4|*]Zo,^oJ˷<g7{|T`=!zE?Ź@E(Ax|,& -탲ܯ&x:O;#dxUn]#\H>dC|u*X=WZL{%flJ~rvH -(iGYhvO0Wcߨ|BM##
L+G,bD=45.UDq')[~&)
`(5?ձJ:A
`e dWcĖK@Uـ;lbd`+CI)B&"&1d1iKk݁5Nn<=dp~+أ -¶&"]qU!vj+MooTiu* -%</B˙UהrV@ik7
7=R{fb!cBx/Jj'>NWTs96z?(&Bt<$===pɏzSüF 2֜/ \8[CEFͿFfGPbv<JYᨉ6tLԆ -Acl!{v\n@!)%o2qXb% -i@ڈT>dL읽ex6dZhp"K {E{f詊TikIʵE9鮫}OJȊ*Q[0 x0d,#]9|(79n.<
m`'c7;B$JB7hC1VuR Vp`ITP{NvEdMOrPNx/V%Rޑep2=@sXDo݀:d؛k,$NIuڿ\tI$)qkz~7LVOo&Kqp_[QbFln8[aڤ[$8qY9
{ EUV.ysGߑ3mCp0WxYdcTVEoez.nw$3 -8QVd'3`9HvJ7)o &a -t42MUO(} 3^Z*3sZ#l{i[yLn08/2qLȕԱ]EB[ɳkZo8
Rۊ -j=p^*^)*ڬmP:7SYc2g%'&%ޥ1?2@jE3tl!9 -U9>cLM?#{zf7|Iw諎C.V/~e%YOY# -:)
Jrv5W(#эϋ] ;s"cm@Iˏ'+>*?nB29QγP(M|_Ib.NIVĻ?~$~L<Q"BQ]9Ax)4I!I {lۯ?^XL{Opa
K*X~%dC|0!+zM8KuR)Tuz},'˺vp;"˔ᤉiÒs.2
gpX=Zx4ZVǺ-OFy3N]I> 0ll2}vWGj?ܮfxϻ~\N]tR)UQHD{Asl33l'`o7V -8 -Yoe${S·$`gW~_99kuOW"i = l}yz}Q}xihʢBainXUAʐ\eNVЀ._
e/'#ي~"!=Re -!GQMy
jzg&}eHa]Д":gDZ3.qw"wSF˷:THY 6"6}'>OK=O7YIGVEc'!FW%zERfʎ\)o:|>**S+g0U͂Dž\O#pEs@x%Т\?[ߴ$ȣ'j6Em J kclzuNX۟)zuEoǜ%v{
9-5;I疲^jtb.0J;FxR#a@j` -9J5~@Km* #ذ>.by*y<B,\GJN,lVZ$/6G~n0FH4^Jժ=&炕lm14*ݻrqEύkX7smxfACǑ|)q:-㫔z -)џ
-*#~~WnwKNNZ6yh!%`V9Pf -9
NQiF3ǝqdSgx~p#-xNS -ִ݈gVL
)m&V-y[8G:%`wl*gZi2;XJ
tZjkI3H -DpXاfZR
l8s먴up{M+ Tky
SB
vRu3 -endstream -endobj -84 0 obj -<< -/Type /FontDescriptor -/FontName /HHSFZO+SFRM1095 -/Flags 4 -/FontBBox [-188 -320 1445 942] -/Ascent 689 -/CapHeight 689 -/Descent -194 -/ItalicAngle 0 -/StemV 50 -/XHeight 430 -/CharSet (/a/b/c/e/five/g/h/i/n/o/one/p/period/r/s/t/three/u/x) -/FontFile 83 0 R ->> -endobj -85 0 obj -<< -/Length1 738 -/Length2 12419 -/Length3 0 -/Length 13157 ->> -stream -%!FontType1-1.0: SFSX1095 0.3 -%%CreationDate: Wed Sep 12 2001 -% Copyright (c) 2001 Vladimir Volovich <vvv@vsu.ru>. -% See the file COPYING (GNU General Public License) for license conditions. -% Converted from METAFONT EC/TC and LH fonts: -% ecsx1095, tcsx1095, lasx1095, lbsx1095, lcsx1095, rxsx1095. -11 dict begin -/FontInfo 6 dict dup begin -/version (0.3) def -/FullName (Computer Modern Sans Serif Bold Extended) def -/FamilyName (Computer Modern) def -/ItalicAngle 0 def -/isFixedPitch false def -/Weight (Bold) def -end readonly def -/FontName /FKLUEV+SFSX1095 def -/Encoding StandardEncoding def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] def -/FontBBox{-229 -332 1765 914}readonly def -currentdict end -currentfile eexec -oc;j~EЪ+`U+1;[ihd_Twρb=I"aě!]#g~Q^VmcNtقP*4Jq=G1`ސnG)]'Ze+hb?%_hpY5(9>(&sـ1
7_lu~N 7cG2~VhwdO_Fh-J&(jrqQ<
+V\@RxL -6}f *|s5 -پQp~!֘Iqyd!L"0L|8(;uԒb -2%nS`sg|wvq+,Yʞ
t\3}h cs*aV\% y9Hw EOdW&!677߫A/RFj߬inM«L'{rUzo@eA>!7o7b!j'N&(_N~<-k!~;dqS]%
:A871oGE||43 -JUcc'z`/j;p/4?=d9 -$rXudư -{|`t}c72f,WFǦ$|`.2DsVRf[fg|jiCTjk}θn_{?Kp9ô0yzf9gC]OI[+̚Gѣ*$3W t]*Te$"N6 -.iUX,o$[*EF՝Uj1n6͐Cb<']aEۧ~$fTM#<-G,+t+*xzm=B`Zkz1T0 t*>@3+iRM3+w˼83`o} ;rJ6wQύN0t6p{9ȑ]WeO]ln%VD1y r^`es%]UTfrFr ʛ'|qvYCOIx1Z5!q~dgFX#h,_1bx J-Ȟo -[ 1HsǞ#H-ѸEa"b(k"=oθ%s'g3>G}4g#gReL=>K-W"n` jzȘ֦\)CmLWY$VPodo{篛{'0
rwTz[cmJQY xV &\:,L*w
;B,ĠQ -6[uk\zs'Y`1
A=%ܾV9n`xl^!sb<PhGZclo}M4:jݴAq35:c˱ɧ᭮g1ؠ
't{hOy3))<tq9N҆c"a3l*Թ(O,0Wz_Gj'|}Lh8.K}x>Ս2\$+6I%m;gj)|\h%Uϙ7xtW>U.b - pw;&1Pa9M<NimG0ԡݰC٩ͅޖЖ1\Ay$ȉYRBщn>.DUh M4#RHdzNo| 얾|zFpSVixD|a>WrMKEe?$iERhF<83l= jphfZ;?uEB?M2`
3Q<7ru6CbXDG#\<H\8B9))Q^e\.T>%7U1Wf<'[h4x6UKe-Plw/Nz̫.1즓X{^a){5uPy|FЀ͞mS9N5SCCx5|`S<S1BXO(Ъy[>ThD!U]K)!!ʕ;qn] ߐ2 -==vN~dG{R iб a@cqCO~wa*969vN歹dLϯ\se"\8ǨzYpe,rI -3ykNOXpD*g ȤQFX'Xl7l%%LN#eH!{0G
R= {o 14!@םx4F,4|yZTYX%_V -I؇X\Ѣ,{"PoX/`\3~KZ@W̢=O4mG3UǀQbyh$?:+YJ~0^,g?=G -j'd?v^a+YIZ_UxWWgYj#% >Z kBT5Dm -uܶuP.,Gk캳T
@&F]g -P-qrKT#/~Az=/Le ~ޫ;Zl]u!b=V߂-u/ba -7Ney{@R!h:
Xr$ճw0x0k3nj4B^,ybl-JRk2yPzmQ~6V -OlY6_[V%FKD' -3mnCG -sάͩ5 -͏hj`מ3feيx]_i?h)8ܨ{̮?@F+<hbGӋ\6#w -xH -Qxy4hดOrPkJjuƛLB!̀r$ɲhUe\::'%T*sE`_Xe~}KcNmM9{r.˜Uu8n}IAF<P8jʠk/WgI_feu+oaSJ33ȌpI1R}L]"9+ttU+ -#ڿn^Aa7ȉu$/,*4HºJ~P0d.ݓ`uݩO@8
Ӛ?L/؆[prTuST;6%ˌ(If +է -HdUνA?G!ɭ_0E)Y(܊AhO5f`J_<9FE*j
0)o~PMGT/!t=]U-ZWJ7kw.՜byraЮ\=OLEeo<UW3;B{GVE$ŘN}zu@gWugқYD>5O<郁f$d\</͵A TBoe%O|<(.OHn!:ҢvxSD(T{^NgҖA`]U]81z;|iSP~q2y(d_ď7/]9hji#\ ,RuGQS{l4=2.4\aZ}XiU3_b(ݽ P\eh]U1*iI,N6-3_O>&(2wPVˠj\;|=(P+2\ -hI,JTY -)>GRQs䙿|2pq#5BI#OCU -8Ծ=Mm!>[h?ۘs`dž[ -TCG}P].K%NL3;M$7YSB/؇%2x$7PAA[%hE4%rBbTv&Z -va<':t́FRԸn/'-+n{*vx -X{blɮhK -<dL
- Hq8mNT?^G_OdSXLJ1_%e$CҊgBɶ"v& -nOvՃeM~Y -|gA8LmIr<*,?e'5Rsk2:yn'k- pOOX/p9,3ljsst
mxri6'rq,<j-'OoIt'aHdzNi -ZC^s&0lV1śMpSVP(=譾|dT([T{~>\R C[$iJ+fV qI%w2b-ז?1҆U{m^YZ{%.LwjJUUpu+a^D;G,ajh_j#J8Vqct]8 a'БO['yCux*1KnBAQ厅Ea34gvK%g~fː4o3gIaV(7̶>@A#Xɱ*wNq
+rcݮ4K#XCulIӨj%12륽~)$H58!"+HUgOLw&Ѧ >kscA -endstream -endobj -86 0 obj -<< -/Type /FontDescriptor -/FontName /FKLUEV+SFSX1095 -/Flags 4 -/FontBBox [-229 -332 1765 914] -/Ascent 729 -/CapHeight 694 -/Descent -193 -/ItalicAngle 0 -/StemV 50 -/XHeight 459 -/CharSet (/b/c/e/i/n/o/s/t/u) -/FontFile 85 0 R ->> -endobj -87 0 obj -<< -/Length1 738 -/Length2 12694 -/Length3 0 -/Length 13432 ->> -stream -%!FontType1-1.0: SFSX1200 0.3 -%%CreationDate: Wed Sep 12 2001 -% Copyright (c) 2001 Vladimir Volovich <vvv@vsu.ru>. -% See the file COPYING (GNU General Public License) for license conditions. -% Converted from METAFONT EC/TC and LH fonts: -% ecsx1200, tcsx1200, lasx1200, lbsx1200, lcsx1200, rxsx1200. -11 dict begin -/FontInfo 6 dict dup begin -/version (0.3) def -/FullName (Computer Modern Sans Serif Bold Extended) def -/FamilyName (Computer Modern) def -/ItalicAngle 0 def -/isFixedPitch false def -/Weight (Bold) def -end readonly def -/FontName /KKGAAD+SFSX1200 def -/Encoding StandardEncoding def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] def -/FontBBox{-232 -329 1767 915}readonly def -currentdict end -currentfile eexec -oc;j~EЪ+`U+1;[ihd_Twρb=I"aě!]#g~Q^VmcNtقP*4Jq=G1`ސnG)]'Ze+hb?%_hpY5(97B2]C2Oazݐ*u]QDnX*vZXBĴ,B/4`b8}&PdJؑ!Ics\yFjA2)z-L<i!"qZ
@&M҄R -3,ab<ΌzmTbScMk}X#1dNuH(iKyvdpxˌoj <mod W!k<0nv_][!QЄNVyj۳sҺ[Ʃ -VP{8%T - JV'^LB|<B{"KK -殖މ<2T3)4XOF"QLknS"ۖuFhi,Gh -!$t43tH6hj1D<Q<5EB_r{]Ya?{%((/NRqv##= -FyhA6BJb[R`͆cO]p3cJg>P/!)|pw5IZEh]BU>[X8-64qכ>(FuJzQ.;аE\]2ޞY4]7Yw!*q&H;
tAve4|?hK <ș_<쥱A/fĜ'HQFiȭ~OAr1Z{~+ZQqt`fN*[6W[Qt%g -Y:{MW沨ڙG^P]FJpύA{~#MJ
kʕm0
m |N,3* ?(O><Lex.6)bHEM\/b}`_7UL]T{"nfwN! >؏+` ~Iud]AOy0{4XWK-Ʃ|>8Q"Rhf -o۰;-O1b#60<IS%a!iyEjglE?Y ~z%tZQ}Q$O+tO% -u_ẁdLMKL7%]>z~ 9N<\|]x19]E}5 -띯tnDy8{1.Q@6:N\+P%%[n;%k_X -^ϱp?wofӧ8 -(>T0$'>},OmX'.,$/1NYYrһN!1^{U'XDUrp}8*&_zwhJЩʔ>R#Bu6@G|Hk@ݨ(V?Lz`L0Rш|tʟ]~,T{5fe93Q"}l!7`/*2)}[A2c>4 rTim{:(-0yD% U&fTtnoM3%YI3OǸ&Ð-Q0G?rly[Ϟx99!|8 -_{m_kL~čCG%M͋?rMczrm`|*D;WY`i{?~:jȟ)PS;due|xR%zNMŞp?Fv -V4-0 kYH?,K_d;7U0J0E>Jk)'uc3E*FQtbދuIѩܐDiHc^qWh !MxI͐];Ƌ`Qg)ACT\"pikpk"X`yii L:9å54n!
nd*4"Nx0'o9ɇD -92J~ -1e -op -FsICe./L[N3` -֣rg̚WO=N"Bi;&o7ŵ^' ?yHp؍vKߒm!Q͕VI{HXj -JM[Omg1P̩e_d#'ܞ\хn#5?*|.$XC5Y]4nuA&H"()閬 26Q]ȖDStr&^1kl-b?a,}h8(\yr S!ٮ`[Zr+mX#
$SHx\|ce"jԜ:)C#m%D/X]+.iK܁]w.%Q 'ѧ]I01)m"*䯞*' 7#{:½`)ZUy_y;O6n. UmyÐ,Q 3<8Wր42L)z2<zB=Jvbi -Vuq*+1;#F dзxq\|(ct|#N4m9BPԹyqY8oH#ag*J_4Ǧ-bMHtx;MN['3 jBz\{wX&7u"p] -~mS_zWs妾WtkZ]֠2Llv+8p(;Xŷܲ:_%e%K8=@G'?UM][m w,[n:?8k`@>x_}U#ͨ*)s3=n9I:5ijr{QWJaNi3)ItlKuO
@OmiöqK!1۾xJCHǨYn^;[*}AQ5|%->O<kbb\Bn͔8j*8Xnˉ
+E*4!Db -oiAvu&bEҘpztYI@kzgfZpe<c&!>lɦ+J4 -QNpa|I.2Q%V%)ْFk;\2M8ՀXrvBi/m6E9]6\HEx[_U1]ưYSAFՑ ?XghSpip\Y=yٖ?CxEH&DRgu+n`+sJ,6cS]:yOKS<I3 -L7.LLIޞsA?;|TܾGR=(r4D[ye5/,tDk!ث%GD?K0*
PUVN!so9@* -Mfq݆EJ#GZd@)g -CDûu~cM%Q59zwj0_`/]߿.?
~M6xw5|ٟv!*A!iE쟑lf;쭹<JdZ|KłI9XO-٩!xRhhy<Ϸ̓Km5b>{<!^ErfJ>\@NWa x$%aQf텣;\ :4C1iK,_ 5d01B)})LgzԈ :~Mnt=.-<2f&~赍Wuޔ|rT_ңB;6~<8'V`?S+-һN\lRy\8W{}&KJ|FQ3%sϙtKC -Zs b<OAoiͲ%?A PpB2Zm}|n;2,mOA"6%@k9{;г&}ez -n.1WSUXtڐ,f -ߎ2M1o%>pKݫAѷszcAXOэk}ĥ;]NM2D7}k-Q6wT"FLc)4})<vp"w{9s٭MQ2}fѓc(S@-9ϕHBF=q\ϬmUF.YzF",.o/oXߘAܿ=IPVZtr8cfmb1
u7QIǑġn腜Ɉ\#̼$i9_;?ed\gB";YAㄶi88&3qZ\Ax|"<yu>Q;z6Ceŋ|9%4Ÿc{sNfdQvRFEan0zduhrJ!Bу-`ȓ -? UI6C5l,_DjglE?Y ~z%9^9̫*B$C:Z0`P#vu<¬c =ĵ&_grr@>(\fpP;;+m̙V]$CQL)Ln<C(R}K?;q,!['8*Gv8 ^hQ%=/A8c~q) -gs V!&7
2IUÁz;rB~у1.=PPȕTJ4Ae{f) -i
v?uh
pbqhdm"E{FCeAڑ+T:؟ZJD8/oUQvЊ*ӃKi v DQ@ <Y}魿bՂt -90-3r%iޏ!2Ĝ5 '37\>lKt iͺg_B3OD'*15v\2S&`bV½VІ?5ZFZw -:/!V l͊=vzv
H0ptxU(H߱X氡S~dfCBW$YOk34ګ]Yz ?q/Zm6RVgSkBi6ҧnD[U)&qY`-)o:UhrJ3ET0F, 1JCt~`xqK`RlGq$o -ahSs'B6.+wi$P -Dkt:l>"{N8ymhJNT -l1"$_ί
R-N.6A)uKJl,j!41>'J涋˓&m`+6 K -IR4o X[|#,?;.ҠR -n\XM -`x.&'RQa:[ZDTνR\\p9UcX#4_ޛ{CFv-e2u`usO9 -. 1K[?wα_bKt{JOWwN
b
~ -0'AxH`i_ts@bh*i*Uڿs9',HAR08a9\/f -ګɗ0?1`*
θ1W%*+6%' -endstream -endobj -88 0 obj -<< -/Type /FontDescriptor -/FontName /KKGAAD+SFSX1200 -/Flags 4 -/FontBBox [-232 -329 1767 915] -/Ascent 729 -/CapHeight 694 -/Descent -194 -/ItalicAngle 0 -/StemV 50 -/XHeight 458 -/CharSet (/b/c/e/i/n/o/one/period/s/t/u) -/FontFile 87 0 R ->> -endobj -89 0 obj -<< -/Length1 738 -/Length2 11968 -/Length3 0 -/Length 12706 ->> -stream -%!FontType1-1.0: SFSX1440 0.3 -%%CreationDate: Wed Sep 12 2001 -% Copyright (c) 2001 Vladimir Volovich <vvv@vsu.ru>. -% See the file COPYING (GNU General Public License) for license conditions. -% Converted from METAFONT EC/TC and LH fonts: -% ecsx1440, tcsx1440, lasx1440, lbsx1440, lcsx1440, rxsx1440. -11 dict begin -/FontInfo 6 dict dup begin -/version (0.3) def -/FullName (Computer Modern Sans Serif Bold Extended) def -/FamilyName (Computer Modern) def -/ItalicAngle 0 def -/isFixedPitch false def -/Weight (Bold) def -end readonly def -/FontName /RQIEES+SFSX1440 def -/Encoding StandardEncoding def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] def -/FontBBox{-238 -326 1844 909}readonly def -currentdict end -currentfile eexec -oc;j~EЪ+`U+1;[ihd_Twρb=I"aě!]#g~Q^VmcNtقP*4Jq=G1`ސnG)]'Ze+hb?%_hpZePEY}κH=-g0Q LyfYԙ >#N
>iyMզxbt,rEk](1ۄ84C+jj苑JXrIoce3f
lf%/5lZlKK˥O:emphM|_Zm+Fԫjkb);;S&wxgtsHVT}q3Ja_7rGjm -J[H]~xuAE2t|.5_0pŘF>}GC@ZSҟWN >Z0[<?8s۞-vă唊Fs3H+Ex)e^ -}#f^9<!:Zԣݷ+d{x΅[4]"ikgrnO\k|x#M-!~R)*oG3~ngr#L*ڌNݏ cdT=h4q$GF%t0K[3fqBVi$.O\ -+BإoR22iV_zr PC@Rv#L9"be3` a߹e_/ -GeUCWRw.Ք ?}-Tr[w,JR&g:yB
>a6Q4SY*dz~9w:)6@yiX_Wby -yFnxyהMQ[̍$!}lsR':{n=B1=;EeE6e.[rLcp:c$cwmI}HհyVp!p{6By"{Jy$dݦa\<xЛWSDŁ -'tі0!.\H:u*Aڬx^w{wkTm/X<ڃr"-P^B:27b3;x&USJ?-GA<HEsϕ%p] -@U)RLU -
@90!2 -#b@P5\Bk6Z_yr2p,#^:'{ -5iP+/@mŘb}ڱF -6q̈x%.4P#b6@=}y"B%R8zX^&kUyKc;pKY5;_B1jp3soTh]"LKtr'^〭⌡=;@jW<.Z`Gb^AQr3tmJiO-<8COTcaQhƐk"U(RuQu.EUJ10<:cﰬHK_]f2Nx]P\GRÇYsO -jhkZM0,:5F8 fEYL1i4ײj'[?#l]FF0];YI9b8oKL@""8eD"Ȇs$R`2YyScJ
i酇cӭ%ssx-`&?Zln0Uf+ٵ |Y9MBd3u ]9>$IPsźFgG`,S\v^<~#0'D -p}LC!&B'EguΰORHC3|D}NRUQx̰1N>1rEI3TJ IhSߟp"Y-hYV,gHb%;Z J1rPvwi3ј2\oI@M6aaQn'm9NNvq" ۪N'`k9Γ.P*ɣ+6*WNv%ɪ*qcU$ǰqIrH1BYQt8_TBg,C!"+uCȵH7l#VK`jXW?_2j}4I9
L6ʡ+<P=+A%YY>>D~ڄI/I['NfsUݴûR.Ъ<%qt!e5naXb"#y7K_ʓx>HzU-Eyj`W@RDs8
w?c5Bkj'/v"`SɃ<27dHF`cyO>
$W;1/^ҏLJs0;G*TP{gY1
;gD%B]Pm\MEsX -wsߧ+]B6i_qOҟj&P03zvedRl ;ڥ81xv9rL> - -VΕIq -PA -p{oWacEM@wYӋ-LbHEP -bUY0w{\)b*4{a1 6
X)E>ҍ$4مs3m_I|+E
.1*}Md6}F/{
GQ.J]9o/J' )/U9xU$ԉ桟un*:%G@˭ -0mgLO0jTzxz<iu skʧސ۵%F}!eՉ=D*#r 'VhTT)ZY~ѥ1wE&>1zL-uJt)6ΝY<jD' -UtvVjf5^)CRO4ɫ=DgitTJ LLYa%T(*UM_m$""L7QT/= --ToP7K!+*mz560(L$bБ"d{*m
DE^Рm -a% čkx
']T9zuVK-^9|ۄB:fZb%u=gkgHb8vT84jOA:Vkt$l+O_G9"/Ǔ<~!h5'WpLƋQ˜b+ rKV:添I{#3n{{^41EjsFk)hu-+x|EhS%CLMh#8ZkA\)>!fаZj$\\C(+9;1KlW$,-ZCld< -lNh:GYfX"s0x%!1F GD?l*`ӢE1.#
n>z\>W27qKo;mRQ*D"09O<& -N .xǷhͱ@0uɜ*Uۗo?؉,ȽDWDpNFaTƍ\܂oЮ [A!Y$M UW)OSPoT.R<UCuL)1?V;@6͢K^2Fm~UN~ECW2ٲ{U7Kdΰ6>oI?9gwXftxpXNHO4Mq190 *~Bl{4
A*{L)$ -I̾0*ҩ".yBf5)!xcR82(HtIX&{t 3!sGj:0esA|ԫu2 #7Ha)Xi%
dhg-i-bPu$B/'cizvV 8Q/,ϫ*W}lA<7
n7c -[WŶxF>N,Pr $ -z*9Z
3mEW#mpe0ʜ,uQA h9ɑxԮ؇zĪ9NZv>/ʐeD6[[#SU-]jGilu~ә*9m}MDF?)&+& -%,@۞BLvDdlUq=:&$c,׆!FL;&N7C[*,4|/G~p/3%[\rڝXeCQ-rS3BʗW<
)xw0*N)MpPLV]3ڸ鱃v[qq|e8rBmrPVgYj#8wUG8j+xJgjK._,`.(QU:DpIqmm -h#y/}]96_D3HIz&:7{ns"c 4m;0f^O;P3lV*_9wF>Xigo%q:~)4Ƽص&J*U -r6C\]:Z>EPot4'jЃ>3-i iaf,9cNfɶuy,2vHnJJtZ2R?;)r:Z0<l8:YQԝ百5ڢ۽gVNzAãuXdMuIp'=h|Va65&|HJLct7{7u/~laDROzSVOIҏ\ ߢskWiNݛaی&FWGRRR64JH#PkXKkQqJ*õEgf0~3Z!O.ԗ݇.3DmOs@mt{BF_)Y{, <fO
4S7XUn3*>F@ex*%63@Cw+w6>oI??Uŧbs@)(&S_ga"$rg!6%
S5)Nbu86K*y=>(
ı~)098ls
`_m^7W5=RR8k$u~V,hJ.XɗJv4Ek!9C[Ȳi#H6)؝JqCRGqr`e$Y:?oBFNUE%~(ը~믐fBaG)SԊpt-'] mI/fR4]B6 ߡfL^!Ě=<4>HҪ -M`8#E7JLuhw[N .h#7MV^jr؟] |h+SPx7JJ=!&#_Z#+ܳ"KJz\!zfz7¨M-,vn DN Wئ ЍY%\"#pLA1t.BBƺp
ĝz^n!0k$X\LI_L+0Oaatj&qQ -
5:\}V-PNyŃqpCt1l+uy &U*1?Ivݮ8|Jmc&9ICycjMȍ -?pʐczw -ԞN*'1cXd"}c8AH:4?80RLgī5 -Mz -t[s&p*ձ$7!Bjg%Eie$Kzԫzuls[Pzsu_ȭ`5?\1?d^yE_q1~=mچ`Qi -i[ R0X?H*ѮaZWH&M*993Ysh a>ߜԣJ`Lq~$jiU"nU?hrd6G@:}{|C׳.ymWSrhޖ!!j+>Y}%i - 3_3.#&mk5;/5qsƚL/:qlV2薿&P)4-|y=SrbQm?_zRc]srܦ*>eX#dB)iɧNX!RePϓf֩dLu <'9S}Cvex@wGT卖%B#0#011+{
'Rrx\[mmtoz.*l -uoCpMcQ؋6lԁa:@k L5̚ \\C< -endstream -endobj -90 0 obj -<< -/Type /FontDescriptor -/FontName /RQIEES+SFSX1440 -/Flags 4 -/FontBBox [-238 -326 1844 909] -/Ascent 709 -/CapHeight 686 -/Descent -194 -/ItalicAngle 0 -/StemV 50 -/XHeight 451 -/CharSet (/c/e/i/n/o/one/period/s/t) -/FontFile 89 0 R ->> -endobj -91 0 obj -<< -/Length1 738 -/Length2 8972 -/Length3 0 -/Length 9710 ->> -stream -%!FontType1-1.0: SFSX2074 0.3 -%%CreationDate: Wed Sep 12 2001 -% Copyright (c) 2001 Vladimir Volovich <vvv@vsu.ru>. -% See the file COPYING (GNU General Public License) for license conditions. -% Converted from METAFONT EC/TC and LH fonts: -% ecsx2074, tcsx2074, lasx2074, lbsx2074, lcsx2074, rxsx2074. -11 dict begin -/FontInfo 6 dict dup begin -/version (0.3) def -/FullName (Computer Modern Sans Serif Bold Extended) def -/FamilyName (Computer Modern) def -/ItalicAngle 0 def -/isFixedPitch false def -/Weight (Bold) def -end readonly def -/FontName /FEKEGK+SFSX2074 def -/Encoding StandardEncoding def -/PaintType 0 def -/FontType 1 def -/FontMatrix [0.001 0 0 0.001 0 0] def -/FontBBox{-234 -319 1740 892}readonly def -currentdict end -currentfile eexec -oc;j~EЪ+`U+1;[ihd_Twρb=I"aě!]#g~Q^VmcNtقP*4Jq=G1`ސnG)]'Ze+hb?%_hpZr=Ш6(YAĪvr%lݐrh-`=J2`pzJPJ&G,
xYMcɩ1Dj1ET}g&38|{iӐFZvEГTN}:6OY=^au@A_ظ(gɍO*N0݆0ݵ6dmBY'qp0 |D8PG9 &ߣU<vKcE8RIt:.'3k_mo_"lrW'g6 - -a4cq84n.j!}f_]X0OM=o,^em}+]qQL0햯zu?8V&v 28S?Ggާ#
IO++ -:䁩n3tv2<
Yy
[eFxZ >vKHI J_>\:| -YG)uxNDOy|oMKz>سfrV]++e:":!JD,3x9 z/ZP.4kD1+EgQ>OQ+ -c3l/KD|n>B#^4:KO(,q.L*֣a&UЫe2!qu6Ϛmn}f)D#40-͟uå=^<آˏٹJ4jDk"BD,k]2,¨, Ϻb)R& -_D<&F_?'%;%.2Y=hc&`n|[_͵j}wr+P>?R v8 4;^M|+={m<Z~w&Y_A;@DlH~뼸@2Yd2_}XwمO0@r@K[WM35d3.vN!y -b3{/cWO|>v{zŊVS0\5 bm֨b9y+_[r'-#}:e|}w\7'3K_[(Rӿ~AyGףasOi1y3V2ԣv&yqzֶX],D[l}P~%i+@ -1;deUӎHX(22U msPL6ɀרQ7+<dkqX -K9O0䪫ٓ7Ј6p,;?r>!ă"$]+<`GLyiTݦ,Ta
5 ~-S:
7IȮY
"<:iFȞ!<[5rM=/^NU;!W"9ەc3aa̩\dU{EpY!#WSPJ ->rz1Eq$S8{*9hQSt#NHcoϱ r,(^4a4OHAKL\G^ - ;!^B"!Qrɣ\7]O+p#W(GCfLL9V&PHP|,n@wpMdz,uշ,|YtxKMIa[0"E5;*nP ,K_y+.51t퇍vPSvc@=OjH9^9"]^Jv6#Uz@R;|"" "o0/}*<A+1)$"lBS?<EB6d*F&Ya]p1M2HbR -ݱ}32Vjb(٠ -c.^%/AURnSk`<iĄt}n])A몷*? -f44T;oQ">]QELy<JBXa|mcw??bDa3#UOf-u=;GKCr -? -DC u]oи5ͼRW9Q%!W:SyJFF\)iЍV(tCGF}z婊7QTG_]"LmAud뿺W5DG70Im\." l?hBaf3cHkmk|u#{0X.zTϵ|BO\ycHO9:hh=wX^z%A,S\[ u>bԵ4$
Nas\]Q7V.Ɗ=d"M?̛9Tccvt]kƜ}!6YD~K,Qrp_|!Rkbʆ_DA4.^%WR)=S8 -1Y \sOst3Ah]hl&X $$GHCkNFL;;~y*a -EÏ -r=̩ۺaW,Y(m#Ukڋ,fw ~`TGL*'cTObxKc(AEk mw$;*6CNxu๏ܿ>ull`n>^l+/>FNRstt -Q2'wL
,#%rk`=ڠk-%DFlzSyES^[ ǂdDS'' -=ѷfŁV+eoVwArTS$R[
ԺO'xJ6՜IuD>6G4BfѦOhxZc): mx)k#?pq[}w/n0!=u@E ,<T>MSMr|$ڵ" ejz:TJ̦)NV*m'Qx#B)kPGm:ڧ羘B]mtp-9ǰ7>"/Bg|RIKZw83y&58;t!rױ( [ڔIqvP܄ct1,ZX;N/c{?
/AB2p|lrD#lYWHHbo&ҦH@+VH5*>CD-WCɛɅuBUԁl@A@Z<.8K[Kϙ!sXF`8bXp)`6-k
-mOz(6:_w>a^ɔ22OG'\R4SdxRلzn9}9捶-wPNٵȭ~]NCQE -NA:\0q`~ނ,"@w, -l,Wr)}}jJ{W81:t -VIb"U{ސ?FzmT mIRSMW+dz5Jy+m0ɠu.\(_j6$W3t(E)U`֜B̦HJ#[rX1~}P9۰u?͍c -tu7J#n긂)7WTxEgskfu|h\7Y*}ai -hxrQ\ ]n:D;y*kXb6yH:]!@m̆U A>GϼZMެ[^z/|i -㈬q9ًhPR!uBI"jl->4
=k-wѫoRYmOV -)bfZr؆L51N4H
k -!u{l?G+ko2zQ${1F ~cEZ]CW`(D0ߦ*n_2
UiF;`ln*uɌe{z -vJ:h|VAhK0>pWGs>LpU$Y0.wmʌ،zDQ*Pt--LLGIȥ {LЩDK}ޤ6̟; *ǹn |N>tzvruTBxViRo -B4CZHh|8cxH?B3&>Otݹ[F[>)ΘԠ72K0qt8쮖A$sdReQ$0 -D%3[#_X*@7 -endstream -endobj -92 0 obj -<< -/Type /FontDescriptor -/FontName /FEKEGK+SFSX2074 -/Flags 4 -/FontBBox [-234 -319 1740 892] -/Ascent 712 -/CapHeight 686 -/Descent -192 -/ItalicAngle 0 -/StemV 50 -/XHeight 447 -/CharSet (/C/a/c/e/h/n/o/one/p/r/s/t) -/FontFile 91 0 R ->> -endobj -77 0 obj -<< -/Type /Encoding -/Differences [46/period 49/one 51/three 53/five 67/C 97/a/b/c 101/e 103/g/h/i 110/n/o/p 114/r/s/t/u 120/x] ->> -endobj -93 0 obj -<< -/Length 1996 ->> -stream -%!PS-Adobe-3.0 Resource-CMap -%%DocumentNeededResources: ProcSet (CIDInit) -%%IncludeResource: ProcSet (CIDInit) -%%BeginResource: CMap (TeX-ecrm1095-cm-super-t1-0) -%%Title: (TeX-ecrm1095-cm-super-t1-0 TeX ecrm1095-cm-super-t1 0) -%%Version: 1.000 -%%EndComments -/CIDInit /ProcSet findresource begin -12 dict begin -begincmap -/CIDSystemInfo -<< /Registry (TeX) -/Ordering (ecrm1095-cm-super-t1) -/Supplement 0 ->> def -/CMapName /TeX-ecrm1095-cm-super-t1-0 def -/CMapType 2 def -1 begincodespacerange -<00> <FF> -endcodespacerange -11 beginbfrange -<0E> <0F> <2039> -<10> <12> <201C> -<15> <16> <2013> -<21> <26> <0021> -<28> <5F> <0028> -<61> <7E> <0061> -<98> <99> <0178> -<C0> <D6> <00C0> -<D8> <DE> <00D8> -<E0> <F6> <00E0> -<F8> <FE> <00F8> -endbfrange -94 beginbfchar -<00> <0060> -<01> <00B4> -<02> <02C6> -<03> <02DC> -<04> <00A8> -<05> <02DD> -<06> <02DA> -<07> <02C7> -<08> <02D8> -<09> <00AF> -<0A> <02D9> -<0B> <00B8> -<0C> <02DB> -<0D> <201A> -<13> <00AB> -<14> <00BB> -<17> <200C> -<19> <0131> -<1A> <0237> -<1B> <00660066> -<1C> <00660069> -<1D> <0066006C> -<1E> <006600660069> -<1F> <00660066006C> -<20> <2423> -<27> <2019> -<60> <2018> -<7F> <002D> -<80> <0102> -<81> <0104> -<82> <0106> -<83> <010C> -<84> <010E> -<85> <011A> -<86> <0118> -<87> <011E> -<88> <0139> -<89> <013D> -<8A> <0141> -<8B> <0143> -<8C> <0147> -<8D> <014A> -<8E> <0150> -<8F> <0154> -<90> <0158> -<91> <015A> -<92> <0160> -<93> <015E> -<94> <0164> -<95> <0162> -<96> <0170> -<97> <016E> -<9A> <017D> -<9B> <017B> -<9C> <0132> -<9D> <0130> -<9E> <0111> -<9F> <00A7> -<A0> <0103> -<A1> <0105> -<A2> <0107> -<A3> <010D> -<A4> <010F> -<A5> <011B> -<A6> <0119> -<A7> <011F> -<A8> <013A> -<A9> <013E> -<AA> <0142> -<AB> <0144> -<AC> <0148> -<AD> <014B> -<AE> <0151> -<AF> <0155> -<B0> <0159> -<B1> <015B> -<B2> <0161> -<B3> <015F> -<B4> <0165> -<B5> <0163> -<B6> <0171> -<B7> <016F> -<B8> <00FF> -<B9> <017A> -<BA> <017E> -<BB> <017C> -<BC> <0133> -<BD> <00A1> -<BE> <00BF> -<BF> <00A3> -<D7> <0152> -<DF> <00530053> -<F7> <0153> -<FF> <00DF> -endbfchar -endcmap -CMapName currentdict /CMap defineresource pop -end -end -%%EndResource -%%EOF - -endstream -endobj -43 0 obj -<< -/Type /Font -/Subtype /Type1 -/BaseFont /HHSFZO+SFRM1095 -/FontDescriptor 84 0 R -/FirstChar 46 -/LastChar 120 -/Widths 81 0 R -/Encoding 77 0 R -/ToUnicode 93 0 R ->> -endobj -94 0 obj -<< -/Length 1996 ->> -stream -%!PS-Adobe-3.0 Resource-CMap -%%DocumentNeededResources: ProcSet (CIDInit) -%%IncludeResource: ProcSet (CIDInit) -%%BeginResource: CMap (TeX-ecsx1095-cm-super-t1-0) -%%Title: (TeX-ecsx1095-cm-super-t1-0 TeX ecsx1095-cm-super-t1 0) -%%Version: 1.000 -%%EndComments -/CIDInit /ProcSet findresource begin -12 dict begin -begincmap -/CIDSystemInfo -<< /Registry (TeX) -/Ordering (ecsx1095-cm-super-t1) -/Supplement 0 ->> def -/CMapName /TeX-ecsx1095-cm-super-t1-0 def -/CMapType 2 def -1 begincodespacerange -<00> <FF> -endcodespacerange -11 beginbfrange -<0E> <0F> <2039> -<10> <12> <201C> -<15> <16> <2013> -<21> <26> <0021> -<28> <5F> <0028> -<61> <7E> <0061> -<98> <99> <0178> -<C0> <D6> <00C0> -<D8> <DE> <00D8> -<E0> <F6> <00E0> -<F8> <FE> <00F8> -endbfrange -94 beginbfchar -<00> <0060> -<01> <00B4> -<02> <02C6> -<03> <02DC> -<04> <00A8> -<05> <02DD> -<06> <02DA> -<07> <02C7> -<08> <02D8> -<09> <00AF> -<0A> <02D9> -<0B> <00B8> -<0C> <02DB> -<0D> <201A> -<13> <00AB> -<14> <00BB> -<17> <200C> -<19> <0131> -<1A> <0237> -<1B> <00660066> -<1C> <00660069> -<1D> <0066006C> -<1E> <006600660069> -<1F> <00660066006C> -<20> <2423> -<27> <2019> -<60> <2018> -<7F> <002D> -<80> <0102> -<81> <0104> -<82> <0106> -<83> <010C> -<84> <010E> -<85> <011A> -<86> <0118> -<87> <011E> -<88> <0139> -<89> <013D> -<8A> <0141> -<8B> <0143> -<8C> <0147> -<8D> <014A> -<8E> <0150> -<8F> <0154> -<90> <0158> -<91> <015A> -<92> <0160> -<93> <015E> -<94> <0164> -<95> <0162> -<96> <0170> -<97> <016E> -<9A> <017D> -<9B> <017B> -<9C> <0132> -<9D> <0130> -<9E> <0111> -<9F> <00A7> -<A0> <0103> -<A1> <0105> -<A2> <0107> -<A3> <010D> -<A4> <010F> -<A5> <011B> -<A6> <0119> -<A7> <011F> -<A8> <013A> -<A9> <013E> -<AA> <0142> -<AB> <0144> -<AC> <0148> -<AD> <014B> -<AE> <0151> -<AF> <0155> -<B0> <0159> -<B1> <015B> -<B2> <0161> -<B3> <015F> -<B4> <0165> -<B5> <0163> -<B6> <0171> -<B7> <016F> -<B8> <00FF> -<B9> <017A> -<BA> <017E> -<BB> <017C> -<BC> <0133> -<BD> <00A1> -<BE> <00BF> -<BF> <00A3> -<D7> <0152> -<DF> <00530053> -<F7> <0153> -<FF> <00DF> -endbfchar -endcmap -CMapName currentdict /CMap defineresource pop -end -end -%%EndResource -%%EOF - -endstream -endobj -75 0 obj -<< -/Type /Font -/Subtype /Type1 -/BaseFont /FKLUEV+SFSX1095 -/FontDescriptor 86 0 R -/FirstChar 98 -/LastChar 117 -/Widths 78 0 R -/Encoding 77 0 R -/ToUnicode 94 0 R ->> -endobj -95 0 obj -<< -/Length 1996 ->> -stream -%!PS-Adobe-3.0 Resource-CMap -%%DocumentNeededResources: ProcSet (CIDInit) -%%IncludeResource: ProcSet (CIDInit) -%%BeginResource: CMap (TeX-ecsx1200-cm-super-t1-0) -%%Title: (TeX-ecsx1200-cm-super-t1-0 TeX ecsx1200-cm-super-t1 0) -%%Version: 1.000 -%%EndComments -/CIDInit /ProcSet findresource begin -12 dict begin -begincmap -/CIDSystemInfo -<< /Registry (TeX) -/Ordering (ecsx1200-cm-super-t1) -/Supplement 0 ->> def -/CMapName /TeX-ecsx1200-cm-super-t1-0 def -/CMapType 2 def -1 begincodespacerange -<00> <FF> -endcodespacerange -11 beginbfrange -<0E> <0F> <2039> -<10> <12> <201C> -<15> <16> <2013> -<21> <26> <0021> -<28> <5F> <0028> -<61> <7E> <0061> -<98> <99> <0178> -<C0> <D6> <00C0> -<D8> <DE> <00D8> -<E0> <F6> <00E0> -<F8> <FE> <00F8> -endbfrange -94 beginbfchar -<00> <0060> -<01> <00B4> -<02> <02C6> -<03> <02DC> -<04> <00A8> -<05> <02DD> -<06> <02DA> -<07> <02C7> -<08> <02D8> -<09> <00AF> -<0A> <02D9> -<0B> <00B8> -<0C> <02DB> -<0D> <201A> -<13> <00AB> -<14> <00BB> -<17> <200C> -<19> <0131> -<1A> <0237> -<1B> <00660066> -<1C> <00660069> -<1D> <0066006C> -<1E> <006600660069> -<1F> <00660066006C> -<20> <2423> -<27> <2019> -<60> <2018> -<7F> <002D> -<80> <0102> -<81> <0104> -<82> <0106> -<83> <010C> -<84> <010E> -<85> <011A> -<86> <0118> -<87> <011E> -<88> <0139> -<89> <013D> -<8A> <0141> -<8B> <0143> -<8C> <0147> -<8D> <014A> -<8E> <0150> -<8F> <0154> -<90> <0158> -<91> <015A> -<92> <0160> -<93> <015E> -<94> <0164> -<95> <0162> -<96> <0170> -<97> <016E> -<9A> <017D> -<9B> <017B> -<9C> <0132> -<9D> <0130> -<9E> <0111> -<9F> <00A7> -<A0> <0103> -<A1> <0105> -<A2> <0107> -<A3> <010D> -<A4> <010F> -<A5> <011B> -<A6> <0119> -<A7> <011F> -<A8> <013A> -<A9> <013E> -<AA> <0142> -<AB> <0144> -<AC> <0148> -<AD> <014B> -<AE> <0151> -<AF> <0155> -<B0> <0159> -<B1> <015B> -<B2> <0161> -<B3> <015F> -<B4> <0165> -<B5> <0163> -<B6> <0171> -<B7> <016F> -<B8> <00FF> -<B9> <017A> -<BA> <017E> -<BB> <017C> -<BC> <0133> -<BD> <00A1> -<BE> <00BF> -<BF> <00A3> -<D7> <0152> -<DF> <00530053> -<F7> <0153> -<FF> <00DF> -endbfchar -endcmap -CMapName currentdict /CMap defineresource pop -end -end -%%EndResource -%%EOF - -endstream -endobj -74 0 obj -<< -/Type /Font -/Subtype /Type1 -/BaseFont /KKGAAD+SFSX1200 -/FontDescriptor 88 0 R -/FirstChar 46 -/LastChar 117 -/Widths 79 0 R -/Encoding 77 0 R -/ToUnicode 95 0 R ->> -endobj -96 0 obj -<< -/Length 1996 ->> -stream -%!PS-Adobe-3.0 Resource-CMap -%%DocumentNeededResources: ProcSet (CIDInit) -%%IncludeResource: ProcSet (CIDInit) -%%BeginResource: CMap (TeX-ecsx1440-cm-super-t1-0) -%%Title: (TeX-ecsx1440-cm-super-t1-0 TeX ecsx1440-cm-super-t1 0) -%%Version: 1.000 -%%EndComments -/CIDInit /ProcSet findresource begin -12 dict begin -begincmap -/CIDSystemInfo -<< /Registry (TeX) -/Ordering (ecsx1440-cm-super-t1) -/Supplement 0 ->> def -/CMapName /TeX-ecsx1440-cm-super-t1-0 def -/CMapType 2 def -1 begincodespacerange -<00> <FF> -endcodespacerange -11 beginbfrange -<0E> <0F> <2039> -<10> <12> <201C> -<15> <16> <2013> -<21> <26> <0021> -<28> <5F> <0028> -<61> <7E> <0061> -<98> <99> <0178> -<C0> <D6> <00C0> -<D8> <DE> <00D8> -<E0> <F6> <00E0> -<F8> <FE> <00F8> -endbfrange -94 beginbfchar -<00> <0060> -<01> <00B4> -<02> <02C6> -<03> <02DC> -<04> <00A8> -<05> <02DD> -<06> <02DA> -<07> <02C7> -<08> <02D8> -<09> <00AF> -<0A> <02D9> -<0B> <00B8> -<0C> <02DB> -<0D> <201A> -<13> <00AB> -<14> <00BB> -<17> <200C> -<19> <0131> -<1A> <0237> -<1B> <00660066> -<1C> <00660069> -<1D> <0066006C> -<1E> <006600660069> -<1F> <00660066006C> -<20> <2423> -<27> <2019> -<60> <2018> -<7F> <002D> -<80> <0102> -<81> <0104> -<82> <0106> -<83> <010C> -<84> <010E> -<85> <011A> -<86> <0118> -<87> <011E> -<88> <0139> -<89> <013D> -<8A> <0141> -<8B> <0143> -<8C> <0147> -<8D> <014A> -<8E> <0150> -<8F> <0154> -<90> <0158> -<91> <015A> -<92> <0160> -<93> <015E> -<94> <0164> -<95> <0162> -<96> <0170> -<97> <016E> -<9A> <017D> -<9B> <017B> -<9C> <0132> -<9D> <0130> -<9E> <0111> -<9F> <00A7> -<A0> <0103> -<A1> <0105> -<A2> <0107> -<A3> <010D> -<A4> <010F> -<A5> <011B> -<A6> <0119> -<A7> <011F> -<A8> <013A> -<A9> <013E> -<AA> <0142> -<AB> <0144> -<AC> <0148> -<AD> <014B> -<AE> <0151> -<AF> <0155> -<B0> <0159> -<B1> <015B> -<B2> <0161> -<B3> <015F> -<B4> <0165> -<B5> <0163> -<B6> <0171> -<B7> <016F> -<B8> <00FF> -<B9> <017A> -<BA> <017E> -<BB> <017C> -<BC> <0133> -<BD> <00A1> -<BE> <00BF> -<BF> <00A3> -<D7> <0152> -<DF> <00530053> -<F7> <0153> -<FF> <00DF> -endbfchar -endcmap -CMapName currentdict /CMap defineresource pop -end -end -%%EndResource -%%EOF - -endstream -endobj -73 0 obj -<< -/Type /Font -/Subtype /Type1 -/BaseFont /RQIEES+SFSX1440 -/FontDescriptor 90 0 R -/FirstChar 46 -/LastChar 116 -/Widths 80 0 R -/Encoding 77 0 R -/ToUnicode 96 0 R ->> -endobj -97 0 obj -<< -/Length 1996 ->> -stream -%!PS-Adobe-3.0 Resource-CMap -%%DocumentNeededResources: ProcSet (CIDInit) -%%IncludeResource: ProcSet (CIDInit) -%%BeginResource: CMap (TeX-ecsx2074-cm-super-t1-0) -%%Title: (TeX-ecsx2074-cm-super-t1-0 TeX ecsx2074-cm-super-t1 0) -%%Version: 1.000 -%%EndComments -/CIDInit /ProcSet findresource begin -12 dict begin -begincmap -/CIDSystemInfo -<< /Registry (TeX) -/Ordering (ecsx2074-cm-super-t1) -/Supplement 0 ->> def -/CMapName /TeX-ecsx2074-cm-super-t1-0 def -/CMapType 2 def -1 begincodespacerange -<00> <FF> -endcodespacerange -11 beginbfrange -<0E> <0F> <2039> -<10> <12> <201C> -<15> <16> <2013> -<21> <26> <0021> -<28> <5F> <0028> -<61> <7E> <0061> -<98> <99> <0178> -<C0> <D6> <00C0> -<D8> <DE> <00D8> -<E0> <F6> <00E0> -<F8> <FE> <00F8> -endbfrange -94 beginbfchar -<00> <0060> -<01> <00B4> -<02> <02C6> -<03> <02DC> -<04> <00A8> -<05> <02DD> -<06> <02DA> -<07> <02C7> -<08> <02D8> -<09> <00AF> -<0A> <02D9> -<0B> <00B8> -<0C> <02DB> -<0D> <201A> -<13> <00AB> -<14> <00BB> -<17> <200C> -<19> <0131> -<1A> <0237> -<1B> <00660066> -<1C> <00660069> -<1D> <0066006C> -<1E> <006600660069> -<1F> <00660066006C> -<20> <2423> -<27> <2019> -<60> <2018> -<7F> <002D> -<80> <0102> -<81> <0104> -<82> <0106> -<83> <010C> -<84> <010E> -<85> <011A> -<86> <0118> -<87> <011E> -<88> <0139> -<89> <013D> -<8A> <0141> -<8B> <0143> -<8C> <0147> -<8D> <014A> -<8E> <0150> -<8F> <0154> -<90> <0158> -<91> <015A> -<92> <0160> -<93> <015E> -<94> <0164> -<95> <0162> -<96> <0170> -<97> <016E> -<9A> <017D> -<9B> <017B> -<9C> <0132> -<9D> <0130> -<9E> <0111> -<9F> <00A7> -<A0> <0103> -<A1> <0105> -<A2> <0107> -<A3> <010D> -<A4> <010F> -<A5> <011B> -<A6> <0119> -<A7> <011F> -<A8> <013A> -<A9> <013E> -<AA> <0142> -<AB> <0144> -<AC> <0148> -<AD> <014B> -<AE> <0151> -<AF> <0155> -<B0> <0159> -<B1> <015B> -<B2> <0161> -<B3> <015F> -<B4> <0165> -<B5> <0163> -<B6> <0171> -<B7> <016F> -<B8> <00FF> -<B9> <017A> -<BA> <017E> -<BB> <017C> -<BC> <0133> -<BD> <00A1> -<BE> <00BF> -<BF> <00A3> -<D7> <0152> -<DF> <00530053> -<F7> <0153> -<FF> <00DF> -endbfchar -endcmap -CMapName currentdict /CMap defineresource pop -end -end -%%EndResource -%%EOF - -endstream -endobj -42 0 obj -<< -/Type /Font -/Subtype /Type1 -/BaseFont /FEKEGK+SFSX2074 -/FontDescriptor 92 0 R -/FirstChar 49 -/LastChar 116 -/Widths 82 0 R -/Encoding 77 0 R -/ToUnicode 97 0 R ->> -endobj -44 0 obj -<< -/Type /Pages -/Count 5 -/Kids [12 0 R 46 0 R 50 0 R 55 0 R 59 0 R] ->> -endobj -98 0 obj -<< -/Type /Catalog -/Pages 44 0 R -/MarkInfo 76 0 R/Lang (en-US)/StructTreeRoot 5 0 R ->> -endobj -99 0 obj -<< -/Producer (pdfTeX-1.40.23) -/Creator (TeX) -/CreationDate (D:20210713163210+02'00') -/ModDate (D:20210713163210+02'00') -/Trapped /False -/PTEX.Fullbanner (This is pdfTeX, Version 3.141592653-2.6-1.40.23 (TeX Live 2021/W32TeX) kpathsea version 6.3.3) ->> -endobj -xref -0 100 -0000000002 65535 f -0000007831 00000 n -0000000003 00000 f -0000000004 00000 f -0000000000 00000 f -0000011814 00000 n -0000008990 00000 n -0000009204 00000 n -0000009355 00000 n -0000009375 00000 n -0000009498 00000 n -0000000015 00000 n -0000006042 00000 n -0000009591 00000 n -0000009682 00000 n -0000009768 00000 n -0000000046 00000 n -0000009863 00000 n -0000000077 00000 n -0000009956 00000 n -0000000108 00000 n -0000010057 00000 n -0000010136 00000 n -0000000139 00000 n -0000010229 00000 n -0000000170 00000 n -0000010330 00000 n -0000010416 00000 n -0000000201 00000 n -0000010511 00000 n -0000000232 00000 n -0000010604 00000 n -0000000263 00000 n -0000010705 00000 n -0000010791 00000 n -0000000294 00000 n -0000010886 00000 n -0000000325 00000 n -0000010980 00000 n -0000000357 00000 n -0000006184 00000 n -0000000389 00000 n -0000090532 00000 n -0000081600 00000 n -0000090710 00000 n -0000006697 00000 n -0000006555 00000 n -0000006483 00000 n -0000011082 00000 n -0000006755 00000 n -0000007033 00000 n -0000006786 00000 n -0000007175 00000 n -0000006817 00000 n -0000007525 00000 n -0000007383 00000 n -0000007311 00000 n -0000011210 00000 n -0000007583 00000 n -0000008532 00000 n -0000011303 00000 n -0000007614 00000 n -0000007645 00000 n -0000011431 00000 n -0000007676 00000 n -0000007707 00000 n -0000011559 00000 n -0000007738 00000 n -0000007769 00000 n -0000011687 00000 n -0000007800 00000 n -0000008674 00000 n -0000007878 00000 n -0000088299 00000 n -0000086066 00000 n -0000083833 00000 n -0000008954 00000 n -0000079400 00000 n -0000011918 00000 n -0000012036 00000 n -0000012479 00000 n -0000012917 00000 n -0000013368 00000 n -0000013790 00000 n -0000028759 00000 n -0000029030 00000 n -0000042285 00000 n -0000042522 00000 n -0000056052 00000 n -0000056300 00000 n -0000069104 00000 n -0000069348 00000 n -0000079155 00000 n -0000079545 00000 n -0000081778 00000 n -0000084011 00000 n -0000086244 00000 n -0000088477 00000 n -0000090797 00000 n -0000090899 00000 n -trailer -<< /Size 100 -/Root 98 0 R -/Info 99 0 R -/ID [<A273A391B74CA8F331548AD088A757DA> <A273A391B74CA8F331548AD088A757DA>] >> -startxref -91167 -%%EOF diff --git a/macros/latex/contrib/tagpdf/ex-patch-sectioning-memoir.pdf b/macros/latex/contrib/tagpdf/ex-patch-sectioning-memoir.pdf Binary files differindex 6ba2eec79e..ee9b314f4f 100644 --- a/macros/latex/contrib/tagpdf/ex-patch-sectioning-memoir.pdf +++ b/macros/latex/contrib/tagpdf/ex-patch-sectioning-memoir.pdf diff --git a/macros/latex/contrib/tagpdf/ex-softhyphen.pdf b/macros/latex/contrib/tagpdf/ex-softhyphen.pdf Binary files differindex 8f7271a6e6..d5dea39b12 100644 --- a/macros/latex/contrib/tagpdf/ex-softhyphen.pdf +++ b/macros/latex/contrib/tagpdf/ex-softhyphen.pdf diff --git a/macros/latex/contrib/tagpdf/ex-spaceglyph-listings.pdf b/macros/latex/contrib/tagpdf/ex-spaceglyph-listings.pdf Binary files differindex 1d4b5312e9..a045fae9fa 100644 --- a/macros/latex/contrib/tagpdf/ex-spaceglyph-listings.pdf +++ b/macros/latex/contrib/tagpdf/ex-spaceglyph-listings.pdf diff --git a/macros/latex/contrib/tagpdf/ex-spaceglyph-listings.tex b/macros/latex/contrib/tagpdf/ex-spaceglyph-listings.tex index d04f8824fb..affcdff51d 100644 --- a/macros/latex/contrib/tagpdf/ex-spaceglyph-listings.tex +++ b/macros/latex/contrib/tagpdf/ex-spaceglyph-listings.tex @@ -1,10 +1,11 @@ % !Mode:: "TeX:DE:UTF-8:Main" -\RequirePackage{pdfmanagement-testphase} -\DeclareDocumentMetadata{uncompress,} +\IfFormatAtLeastTF{2022-06-01}{} + {\RequirePackage{pdfmanagement-testphase}} +\DocumentMetadata{uncompress,testphase=tagpdf} \documentclass{article} \usepackage{amsmath} \usepackage[ngerman]{babel} -\usepackage{tagpdf,listings} +\usepackage{listings} \makeatletter %\def\lst@outputspace{\pdffakespace\ } %not so good % this here works fine with luatex, if the font has a space glyph: @@ -12,11 +13,11 @@ \def\lst@visiblespace{\lst@ttfamily{\char32}{\char32}} % with pdftex this could work %\def\lst@visiblespace{\lst@ttfamily{\pdffakespace\ }{\pdffakespace\ }} -\tagpdfsetup{activate,interwordspace=on,show-spaces,log=v} +\tagpdfsetup{show-spaces,log=v} \begin{document}\pagestyle{empty} -\tagmcbegin{tag=P} + \begin{lstlisting}[showspaces] aaa aaa xxxx \end{lstlisting} -\tagmcend + \end{document}
\ No newline at end of file diff --git a/macros/latex/contrib/tagpdf/ex-structure-luatex.pdf b/macros/latex/contrib/tagpdf/ex-structure-luatex.pdf Binary files differdeleted file mode 100644 index fce47848aa..0000000000 --- a/macros/latex/contrib/tagpdf/ex-structure-luatex.pdf +++ /dev/null diff --git a/macros/latex/contrib/tagpdf/ex-structure.tex b/macros/latex/contrib/tagpdf/ex-structure-obsolete.tex index 8ce5b624b8..1070b7c46d 100644 --- a/macros/latex/contrib/tagpdf/ex-structure.tex +++ b/macros/latex/contrib/tagpdf/ex-structure-obsolete.tex @@ -1,4 +1,9 @@ % !Mode:: "TeX:DE:UTF-8:Main" + +%!!!!!!! +% obsolete in part (paratagging will interfere) +% don't expect a correct output! +% \RequirePackage{pdfmanagement-testphase} \DeclareDocumentMetadata{pdfversion=1.7,uncompress} @@ -27,7 +32,6 @@ \pagestyle{fancy} \fancyhf{} -\cfoot{\tagmcbegin{artifact=pagination}\thepage\tagmcend} \begin{document} \tagstructbegin{tag=Sect} diff --git a/macros/latex/contrib/tagpdf/ex-tagpdf-template.pdf b/macros/latex/contrib/tagpdf/ex-tagpdf-template.pdf Binary files differindex 699f824495..337c049d53 100644 --- a/macros/latex/contrib/tagpdf/ex-tagpdf-template.pdf +++ b/macros/latex/contrib/tagpdf/ex-tagpdf-template.pdf diff --git a/macros/latex/contrib/tagpdf/ex-tagpdf-template.tex b/macros/latex/contrib/tagpdf/ex-tagpdf-template.tex index a2b0db1164..c59ff33da3 100644 --- a/macros/latex/contrib/tagpdf/ex-tagpdf-template.tex +++ b/macros/latex/contrib/tagpdf/ex-tagpdf-template.tex @@ -2,15 +2,22 @@ %this is more or less minimal template that can be used as starting point %it doesn't set everything that would be needed! -\RequirePackage{pdfmanagement-testphase} -\DeclareDocumentMetadata - { - uncompress, - pdfversion=2.0 - } + +% \DocumentMetadata requires a new pdfmanagement-testphase version! Older versions +% should use \DeclareDocumentMetadata + +% with a new LaTeX it will not longer be needed to load pdfmanagment-testphase! +\IfFormatAtLeastTF{2022-06-01}{} + {\RequirePackage{pdfmanagement-testphase}} +\DocumentMetadata + {uncompress, + pdfversion=2.0, + testphase=tagpdf %load and activate tagpdf + } + \documentclass{scrartcl} \usepackage[english]{babel} -\usepackage{tagpdf} + \usepackage{iftex} \iftutex \usepackage{fontspec} @@ -21,9 +28,6 @@ \tagpdfsetup { tabsorder=structure, - activate, %adds Document structure - paratagging, %activates tagging of paragraphs. - interwordspace %actives interword spaces (lualatex, pdflatex) } \begin{document} \pagestyle{empty} % diff --git a/macros/latex/contrib/tagpdf/example-input-file.tex b/macros/latex/contrib/tagpdf/example-input-file.tex deleted file mode 100644 index b85cfea571..0000000000 --- a/macros/latex/contrib/tagpdf/example-input-file.tex +++ /dev/null @@ -1,5 +0,0 @@ -%% LaTeX2e file `example-input-file.tex' -%% generated by the `filecontents' environment -%% from source `ex-AF-file' on 2021/02/23. -%% -Additional info! diff --git a/macros/latex/contrib/tagpdf/tagpdf-backend.dtx b/macros/latex/contrib/tagpdf/tagpdf-backend.dtx index f28a02ea6e..dcf7afb823 100644 --- a/macros/latex/contrib/tagpdf/tagpdf-backend.dtx +++ b/macros/latex/contrib/tagpdf/tagpdf-backend.dtx @@ -2,7 +2,7 @@ % %% File: tagpdf-backend.dtx % -% Copyright (C) 2019-2021 Ulrike Fischer +% Copyright (C) 2019-2022 Ulrike Fischer % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -51,13 +51,13 @@ % }^^A % } % -% \date{Version 0.92, released 2021-08-27} +% \date{Version 0.93, released 2022-01-13} % \maketitle % \begin{implementation} % \begin{macrocode} %<@@=tag> %<*luatex> -\ProvidesExplFile {tagpdf-luatex.def} {2021-08-27} {0.92} +\ProvidesExplFile {tagpdf-luatex.def} {2022-01-13} {0.93} {tagpdf~driver~for~luatex} % \end{macrocode} % \section{Loading the lua} @@ -161,8 +161,8 @@ local ProvidesLuaModule = { name = "tagpdf", - version = "0.92", --TAGVERSION - date = "2021-08-27", --TAGDATE + version = "0.93", --TAGVERSION + date = "2022-01-13", --TAGDATE description = "tagpdf lua code", license = "The LATEX Project Public License 1.3c" } @@ -739,11 +739,6 @@ end ltx.@@.func.markspaceoff=@@_deactivate_mark_space % \end{macrocode} % \end{macro} -% \begin{macro} -% { -% default_space_char, -% default_fontid, -% } % We need two local variable to setup a default space char. % \begin{macrocode} local default_space_char = node.new(GLYPH) @@ -751,7 +746,6 @@ local default_fontid = font.id("TU/lmr/m/n/10") default_space_char.char = 32 default_space_char.font = default_fontid % \end{macrocode} -% \end{macro} % \begin{macro} % { % @@_space_chars_shipout, diff --git a/macros/latex/contrib/tagpdf/tagpdf-checks.dtx b/macros/latex/contrib/tagpdf/tagpdf-checks.dtx index 5cdbc60cf6..53f97383f8 100644 --- a/macros/latex/contrib/tagpdf/tagpdf-checks.dtx +++ b/macros/latex/contrib/tagpdf/tagpdf-checks.dtx @@ -2,7 +2,7 @@ % %% File: tagpdf-checks.dtx % -% Copyright (C) 2019-2021 Ulrike Fischer +% Copyright (C) 2019-2022 Ulrike Fischer % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -52,7 +52,7 @@ % }^^A % } % -% \date{Version 0.92, released 2021-08-27} +% \date{Version 0.93, released 2022-01-13} % \maketitle % \begin{documentation} % \section{Commands} @@ -245,13 +245,60 @@ % INFO PARENTTREE-NUMENTRY & 3 \\ % INFO PARENTTREE-STRUCT-OBJREF & 4 % \end{longtable} - +% +% \subsection{Debug mode messages and code} +% If the package tagpdf-debug is loaded a number of commands are redefined and +% enhanced with additional commands which can be used to output debug messages or +% collect statistics. The commands are present but do nothing if the log-level is zero. +% \begin{tabular}{llll} +% command & name & action & remark\\\hline +% |\tag_mc_begin:n| & mc-begin-insert & msg \\ +% & mc-begin-ignore & msg & if inactive \\ +% \end{tabular} +% +% \subsection{Messages} +% \begin{function}{ +% mc-nested, +% mc-tag-missing, +% mc-label-unknown, +% mc-used-twice, +% mc-used-twice, +% mc-not-open, +% mc-pushed, +% mc-popped, +% mc-current} +% Various messages related to mc-chunks. TODO document their meaning. +% \end{function} +% \begin{function}{struct-no-objnum,struct-faulty-nesting, +% struct-missing-tag,struct-used-twice,struct-label-unknown,struct-show-closing} +% Various messages related to structure. TODO document their meaning. +% \end{function} +% +% \begin{function}{attr-unknown} +% Message if an attribute i sunknown. +% \end{function} +% +% \begin{function}{role-missing,role-unknown,role-unknown-tag,role-tag,new-tag} +% Messages related to role mapping. +% \end{function} +% +% \begin{function}{tree-mcid-index-wrong} +% Used in the tree code, typically indicates the document must be rerun. +% \end{function} +% +% \begin{function}{sys-no-interwordspace} +% Message if an engine doesn't support inter word spaces +% \end{function} +% +% \begin{function}{para-hook-count-wrong} +% Message if the number of begin paragraph and end paragraph differ. This normally means faulty structure. +% \end{function} % \end{documentation} % \begin{implementation} % \begin{macrocode} %<@@=tag> %<*header> -\ProvidesExplPackage {tagpdf-checks-code} {2021-08-27} {0.92} +\ProvidesExplPackage {tagpdf-checks-code} {2022-01-13} {0.93} {part of tagpdf - code related to checks, conditionals, debugging and messages} %</header> % \end{macrocode} @@ -791,5 +838,88 @@ % \begin{macrocode} %</package> % \end{macrocode} +% \begin{macrocode} +%<*debug> +% \end{macrocode} +% Code for tagpdf-debug. This will probably change over time. +% At first something for the mc commands. +% \begin{macrocode} +\msg_new:nnn { tag / debug } {mc-begin} { MC~begin~#1~with~options:~\tl_to_str:n{#2}~[\msg_line_context:] } +\msg_new:nnn { tag / debug } {mc-end} { MC~end~#1~[\msg_line_context:] } + +\cs_new_protected:Npn \@@_debug_mc_begin_insert:n #1 + { + \int_compare:nNnT { \l_@@_loglevel_int } > {0} + { + \msg_note:nnnn { tag / debug } {mc-begin} {inserted} { #1 } + } + } +\cs_new_protected:Npn \@@_debug_mc_begin_ignore:n #1 + { + \int_compare:nNnT { \l_@@_loglevel_int } > {0} + { + \msg_note:nnnn { tag / debug } {mc-begin } {ignored} { #1 } + } + } +\cs_new_protected:Npn \@@_debug_mc_end_insert: + { + \int_compare:nNnT { \l_@@_loglevel_int } > {0} + { + \msg_note:nnn { tag / debug } {mc-end} {inserted} + } + } +\cs_new_protected:Npn \@@_debug_mc_end_ignore: + { + \int_compare:nNnT { \l_@@_loglevel_int } > {0} + { + \msg_note:nnn { tag / debug } {mc-end } {ignored} + } + } +% \end{macrocode} +% And now something for the structures +% \begin{macrocode} +\msg_new:nnn { tag / debug } {struct-begin} + { + Struct~begin~#1~with~options:~\tl_to_str:n{#2}~[\msg_line_context:] + } +\msg_new:nnn { tag / debug } {struct-end} + { + Struct~end~#1~[\msg_line_context:] + } + +\cs_new_protected:Npn \@@_debug_struct_begin_insert:n #1 + { + \int_compare:nNnT { \l_@@_loglevel_int } > {0} + { + \msg_note:nnnn { tag / debug } {struct-begin} {inserted} { #1 } + \seq_log:N \g_@@_struct_tag_stack_seq + } + } +\cs_new_protected:Npn \@@_debug_struct_begin_ignore:n #1 + { + \int_compare:nNnT { \l_@@_loglevel_int } > {0} + { + \msg_note:nnnn { tag / debug } {struct-begin } {ignored} { #1 } + } + } +\cs_new_protected:Npn \@@_debug_struct_end_insert: + { + \int_compare:nNnT { \l_@@_loglevel_int } > {0} + { + \msg_note:nnn { tag / debug } {struct-end} {inserted} + \seq_log:N \g_@@_struct_tag_stack_seq + } + } +\cs_new_protected:Npn \@@_debug_struct_end_ignore: + { + \int_compare:nNnT { \l_@@_loglevel_int } > {0} + { + \msg_note:nnn { tag / debug } {struct-end } {ignored} + } + } +% \end{macrocode} +% \begin{macrocode} +%</debug> +% \end{macrocode} % \end{implementation} % \PrintIndex diff --git a/macros/latex/contrib/tagpdf/tagpdf-code.pdf b/macros/latex/contrib/tagpdf/tagpdf-code.pdf Binary files differindex 46d3a425fd..6f92329af5 100644 --- a/macros/latex/contrib/tagpdf/tagpdf-code.pdf +++ b/macros/latex/contrib/tagpdf/tagpdf-code.pdf diff --git a/macros/latex/contrib/tagpdf/tagpdf-code.tex b/macros/latex/contrib/tagpdf/tagpdf-code.tex index 5d29d0ba6b..d51c209929 100644 --- a/macros/latex/contrib/tagpdf/tagpdf-code.tex +++ b/macros/latex/contrib/tagpdf/tagpdf-code.tex @@ -34,8 +34,15 @@ % version data. \usepackage{longtable} \usepackage{tagpdf} - - +\makeatletter +%\def\@setupverbvisiblespace{} +%\def\verb{\relax\ifmmode\hbox\else\leavevmode\null\fi +% \bgroup +% \verb@eol@error \let\do\@makeother \dospecials +% \verbatim@font\@noligs +% \language\l@nohyphenation +% \@ifstar\@verb\@verb} +\makeatother \begin{document} \GetFileInfo{tagpdf.sty} diff --git a/macros/latex/contrib/tagpdf/tagpdf-mc-generic.dtx b/macros/latex/contrib/tagpdf/tagpdf-mc-generic.dtx index 903b38d5a3..994e3b0b85 100644 --- a/macros/latex/contrib/tagpdf/tagpdf-mc-generic.dtx +++ b/macros/latex/contrib/tagpdf/tagpdf-mc-generic.dtx @@ -2,7 +2,7 @@ % %% File: tagpdf-mc.dtx % -% Copyright (C) 2019-2021 Ulrike Fischer +% Copyright (C) 2019-2022 Ulrike Fischer % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -50,7 +50,7 @@ % }^^A % } % -% \date{Version 0.92, released 2021-08-27} +% \date{Version 0.93, released 2022-01-13} % \maketitle % \begin{documentation} % \end{documentation} @@ -59,9 +59,13 @@ % \begin{macrocode} %<@@=tag> %<*generic> -\ProvidesExplPackage {tagpdf-mc-code-generic} {2021-08-27} {0.92} +\ProvidesExplPackage {tagpdf-mc-code-generic} {2022-01-13} {0.93} {part of tagpdf - code related to marking chunks - generic mode} %</generic> +%<*debug> +\ProvidesExplPackage {tagpdf-debug-generic} {2022-01-13} {0.93} + {part of tagpdf - debugging code related to marking chunks - generic mode} +%</debug> % \end{macrocode} % %\subsection{Variables} @@ -653,6 +657,7 @@ % It is use by the get command. % \begin{macrocode} \cs_new:Nn \@@_get_data_mc_tag: { \g_@@_mc_key_tag_tl } +%</generic> % \end{macrocode} % \end{macro} % @@ -663,10 +668,20 @@ % the state is passed to the end command through a global var and % a global boolean. % \begin{macrocode} +%<*generic|debug> +%<*generic> \cs_new_protected:Npn \tag_mc_begin:n #1 %#1 keyval { \@@_check_if_active_mc:T { +%</generic> +%<*debug> +\cs_set_protected:Npn \tag_mc_begin:n #1 %#1 keyval + { + \@@_check_if_active_mc:TF + { + \@@_debug_mc_begin_insert:n { #1 } +%</debug> \group_begin: %hm \@@_check_mc_if_nested: \bool_gset_true:N \g_@@_in_mc_bool @@ -695,18 +710,38 @@ } \group_end: } +%<*debug> + { + \@@_debug_mc_begin_ignore:n { #1 } + } +%</debug> } +%<*generic> \cs_new_protected:Nn \tag_mc_end: { \@@_check_if_active_mc:T { +%</generic> +%<*debug> +\cs_set_protected:Nn \tag_mc_end: + { + \@@_check_if_active_mc:TF + { + \@@_debug_mc_end_insert: +%</debug> \@@_check_mc_if_open: \bool_gset_false:N \g_@@_in_mc_bool \tl_gset:Nn \g_@@_mc_key_tag_tl { } \@@_mc_emc: \@@_mc_end_marks: } +%<*debug> + { + \@@_debug_mc_end_ignore: + } +%</debug> } +%</generic|debug> % \end{macrocode} % \end{macro} @@ -717,12 +752,15 @@ % we assume that their values are safe. % \begin{macro} % { -% tag,raw, -% alttext, -% actualtext, -% label,artifact +% tag (mc-key), +% raw (mc-key), +% alttext (mc-key), +% actualtext (mc-key), +% label (mc-key), +% artifact (mc-key) % } % \begin{macrocode} +%<*generic> \keys_define:nn { @@ / mc } { tag .code:n = % the name (H,P,Span) etc diff --git a/macros/latex/contrib/tagpdf/tagpdf-mc-luacode.dtx b/macros/latex/contrib/tagpdf/tagpdf-mc-luacode.dtx index 2698b7ad59..d8dba57fd1 100644 --- a/macros/latex/contrib/tagpdf/tagpdf-mc-luacode.dtx +++ b/macros/latex/contrib/tagpdf/tagpdf-mc-luacode.dtx @@ -2,7 +2,7 @@ % %% File: tagpdf-mc.dtx % -% Copyright (C) 2019-2021 Ulrike Fischer +% Copyright (C) 2019-2022 Ulrike Fischer % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -50,9 +50,8 @@ % }^^A % } % -% \date{Version 0.92, released 2021-08-27} +% \date{Version 0.93, released 2022-01-13} % \maketitle - % \begin{implementation} % The code is splitted into three parts: code shared by all engines, % code specific to luamode and code not used by luamode. @@ -91,7 +90,7 @@ % \begin{macrocode} %<@@=tag> %<*luamode> -\ProvidesExplPackage {tagpdf-mc-code-lua} {2021-08-27} {0.92} +\ProvidesExplPackage {tagpdf-mc-code-lua} {2022-01-13} {0.93} {tagpdf - mc code only for the luamode } %</luamode> % \end{macrocode} @@ -159,7 +158,7 @@ \cs_new_protected:Npn \@@_add_missing_mcs_to_stream:Nn #1#2 {} % \end{macrocode} % \end{macro} -% \begin{macro}{\@@_mc_if_in:,\tag_mc_if_in:} +% \begin{macro}[pTF]{\@@_mc_if_in:,\tag_mc_if_in:} % This tests, if we are in an mc, for attributes % this means to check against a number. % \begin{macrocode} @@ -358,10 +357,12 @@ % \subsection{Key definitions} % \begin{macro} % { -% tag,raw, -% alttext, -% actualtext, -% label,artifact +% tag (mc-key), +% raw (mc-key), +% alttext (mc-key), +% actualtext (mc-key), +% label (mc-key), +% artifact (mc-key) % } % TODO: check conversion, check if local/global setting is right. % \begin{macrocode} diff --git a/macros/latex/contrib/tagpdf/tagpdf-mc-shared.dtx b/macros/latex/contrib/tagpdf/tagpdf-mc-shared.dtx index 17f6df0fcf..852f1d0846 100644 --- a/macros/latex/contrib/tagpdf/tagpdf-mc-shared.dtx +++ b/macros/latex/contrib/tagpdf/tagpdf-mc-shared.dtx @@ -2,7 +2,7 @@ % %% File: tagpdf-mc.dtx % -% Copyright (C) 2019-2021 Ulrike Fischer +% Copyright (C) 2019-2022 Ulrike Fischer % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -50,7 +50,7 @@ % }^^A % } % -% \date{Version 0.92, released 2021-08-27} +% \date{Version 0.93, released 2022-01-13} % \maketitle % \begin{documentation} % \section{Public Commands} @@ -120,7 +120,7 @@ % The following keys can be used with |\tag_mc_begin:n|, |\tagmcbegin|, % |\tag_mc_begin_pop:n|, % -% \begin{function}{tag} +% \begin{function}{tag (mc-key)} % This key is required, unless artifact is used. % The value is a tag like |P| or |H1| without a slash at the begin, % this is added by the code. @@ -131,7 +131,7 @@ % (some ascii with numbers like \texttt{H4} is fine). % \end{function} % -% \begin{function}{artifact} +% \begin{function}{artifact (mc-key)} % This will setup the marked content as an artifact. The key should be used % for content that should be ignored. % The key can take one of the values |pagination|, @@ -139,33 +139,33 @@ % (this is the default). % \end{function} % -% \begin{function}{raw} +% \begin{function}{raw (mc-key)} % This key allows to add more entries to the properties dictionary. % The value must be correct, low-level PDF. E.g. % \verb+raw=/Alt (Hello)+ will insert an alternative Text. % \end{function} % -% \begin{function}{alttext} +% \begin{function}{alttext (mc-key)} % This key inserts an \texttt{/Alt} value in the property dictionary of the BDC operator. % The value is handled as verbatim string, commands are not expanded. % The value will be expanded first once. % \end{function} % -% \begin{function}{actualtext} +% \begin{function}{actualtext (mc-key)} % This key inserts an \texttt{/ActualText} value in the property dictionary % of the BDC operator. The value is handled as verbatim string, % commands are not expanded. % The value will be expanded first once. % \end{function} % -% \begin{function}{label} +% \begin{function}{label (mc-key)} % This key sets a label by which one can call the marked content % later in another structure % (if it has been stashed with the |stash| key). % Internally the label name will start with \texttt{tagpdf-}. % \end{function} % -% \begin{function}{stash} +% \begin{function}{stash (mc-key)} % This \enquote{stashes} an mc-chunk: it is not inserted into the current structure. % It should be normally be used along with a label to be able to use the mc-chunk % in another place. @@ -178,7 +178,7 @@ % \begin{macrocode} %<@@=tag> %<*header> -\ProvidesExplPackage {tagpdf-mc-code-shared} {2021-08-27} {0.92} +\ProvidesExplPackage {tagpdf-mc-code-shared} {2022-01-13} {0.93} {part of tagpdf - code related to marking chunks - code shared by generic and luamode } %</header> @@ -407,7 +407,7 @@ % \subsection{Keys} % This are the keys where the code can be shared between the modes. % -% \begin{macro}{stash,__artifact-bool,__artifact-type} +% \begin{macro}{stash (mc-key),__artifact-bool,__artifact-type} % the two internal artifact keys are use to define the public |artifact|. % For now we add support for the subtypes Header and Footer. % Watermark,PageNum, LineNum,Redaction,Bates will be added if some use case diff --git a/macros/latex/contrib/tagpdf/tagpdf-roles.dtx b/macros/latex/contrib/tagpdf/tagpdf-roles.dtx index 78dccdc02a..f8b0589bb5 100644 --- a/macros/latex/contrib/tagpdf/tagpdf-roles.dtx +++ b/macros/latex/contrib/tagpdf/tagpdf-roles.dtx @@ -2,7 +2,7 @@ % %% File: tagpdf-roles.dtx % -% Copyright (C) 2019-2021 Ulrike Fischer +% Copyright (C) 2019-2022 Ulrike Fischer % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -50,13 +50,48 @@ % }^^A % } % -% \date{Version 0.92, released 2021-08-27} +% \date{Version 0.93, released 2022-01-13} % \maketitle +% \begin{documentation} +% \begin{function} +% { +% add-new-tag (setup-key), +% tag (rolemap-key), +% namespace (rolemap-key), +% role (rolemap-key), +% role-namespace (rolemap-key) +% } +% This key can be used in \cs{tagpdfsetup} to declare and rolemap new tags. +% It takes as value a key-value list or a simple |new-tag/old-tag|. +% +% The key-value list knows the following keys: +% \begin{description} +% \item[\texttt{tag}] This is the name of the new type as it should then be used in \cs{tagstructbegin}. +% \item[\texttt{namespace}] This is the namespace of the new type. +% The value should be a shorthand of a namespace. +% The allowed values are currently |pdf|, |pdf2|, |mathml| and |user|. +% The default value (and recommended value for a new tag) is |user|. +% The public name of the user namespace is |tag/NS/user|. This can be used to reference +% the namespace e.g. in attributes. +% \item[\texttt{role}] This is the type the tag should be mapped too. +% In a PDF 1.7 or earlier this is normally a type from the |pdf| set, +% in PDF 2.0 from the |pdf|, |pdf2| and |mathml| set. +% It can also be a user type, or a still unknown type. +% The PDF format allows mapping to be done transitively. +% But tagpdf can't/won't check such unusual role mapping. +% \item[\texttt{role-namespace}] If the role is a known type +% the default value is the default namespace of this type. +% If the role is unknown, |user| is used and +% the code hopes that the type will be defined later. With this key a specific +% namespace can be forced. +% \end{description} +% \end{function} +% \end{documentation} % \begin{implementation} % \begin{macrocode} %<@@=tag> %<*header> -\ProvidesExplPackage {tagpdf-roles-code} {2021-08-27} {0.92} +\ProvidesExplPackage {tagpdf-roles-code} {2022-01-13} {0.93} {part of tagpdf - code related to roles and structure names} %</header> % \end{macrocode} @@ -631,9 +666,15 @@ % \end{macrocode} % \end{macro} % \subsection{Key-val user interface} -% The user interface use the key |add-new-tag|, which takes either a +% The user interface uses the key |add-new-tag|, which takes either a % keyval list as argument, or a tag/role. -% \begin{macro}{tag,tag-namespace,role,role-namespace,add-new-tag} +% \begin{macro} +% { +% tag (rolemap-key), +% tag-namespace (rolemap-key), +% role (rolemap-key), +% role-namespace (rolemap-key), +% add-new-tag (setup-key)} % \begin{macrocode} \keys_define:nn { @@ / tag-role } { diff --git a/macros/latex/contrib/tagpdf/tagpdf-space.dtx b/macros/latex/contrib/tagpdf/tagpdf-space.dtx index c2a999cc1b..40c4367ba2 100644 --- a/macros/latex/contrib/tagpdf/tagpdf-space.dtx +++ b/macros/latex/contrib/tagpdf/tagpdf-space.dtx @@ -2,7 +2,7 @@ % %% File: tagpdf-space.dtx % -% Copyright (C) 2019-2021 Ulrike Fischer +% Copyright (C) 2019-2022 Ulrike Fischer % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -50,13 +50,25 @@ % }^^A % } % -% \date{Version 0.92, released 2021-08-27} +% \date{Version 0.93, released 2022-01-13} % \maketitle +% \begin{documentation} +% \begin{function}{interwordspace (setup-key)} +% This key allows to activate/deactivate the real space chars if the engine supports +% it. The allowed values are |true|, |on|, |false|, |off|. +% \end{function} +% \begin{function}{show-spaces (setup-key)} +% This key works only with luatex and shows with small red +% bars where spaces have been inserted. This is only for debugging and +% is not completly reliable (and change affect other literals and tagging), so it +% should be used with care. +% \end{function} +% \end{documentation} % \begin{implementation} % \begin{macrocode} %<@@=tag> %<*header> -\ProvidesExplPackage {tagpdf-space-code} {2021-08-27} {0.92} +\ProvidesExplPackage {tagpdf-space-code} {2022-01-13} {0.93} {part of tagpdf - code related to real space chars} %</header> % \end{macrocode} @@ -65,7 +77,7 @@ % support real space chars. Most of the code for luatex which uses attributes % is in the lua code, here are only the keys. % -% \begin{macro}{interwordspace,show-spaces} +% \begin{macro}{interwordspace (setup-key),show-spaces (setup-key)} % \begin{macrocode} %<*package> \sys_if_engine_pdftex:T diff --git a/macros/latex/contrib/tagpdf/tagpdf-struct.dtx b/macros/latex/contrib/tagpdf/tagpdf-struct.dtx index 610d631333..6f03c5ac0f 100644 --- a/macros/latex/contrib/tagpdf/tagpdf-struct.dtx +++ b/macros/latex/contrib/tagpdf/tagpdf-struct.dtx @@ -2,7 +2,7 @@ % %% File: tagpdf-struct.dtx % -% Copyright (C) 2019-2021 Ulrike Fischer +% Copyright (C) 2019-2022 Ulrike Fischer % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -50,7 +50,7 @@ % }^^A % } % -% \date{Version 0.92, released 2021-08-27} +% \date{Version 0.93, released 2022-01-13} % \maketitle % \begin{documentation} % \section{Public Commands} @@ -94,9 +94,9 @@ % \end{function} % \section{Public keys} % \subsection{Keys for the structure commands} -% \begin{function}{tag} +% \begin{function}{tag (struct-key)} % This is required. The value of the key is normally one of the -% standard types listed in section \ref{sec:new-tag}. +% standard types listed in the main tagpdf documentation. % It is possible to setup new tags/types. % The value can also be of the form |type/NS|, where |NS| is the % shorthand of a declared name space. @@ -104,54 +104,54 @@ % This allows to use a different name space than % the one connected by default to the tag. But normally this should not be needed. % \end{function} -% \begin{function}{stash} +% \begin{function}{stash (struct-key)} % Normally a new structure inserts itself as a kid % into the currently active structure. This key prohibits this. % The structure is nevertheless from now on % \enquote{the current active structure} % and parent for following marked content and structures. % \end{function} -% \begin{function}{label} +% \begin{function}{label (struct-key)} % This key sets a label by which % one can use the structure later in another structure. % Internally the label name will start with \texttt{tagpdfstruct-}. % \end{function} -% \begin{function}{title,title-o} +% \begin{function}{title (struct-key),title-o (struct-key)} % This keys allows to set the dictionary entry % \texttt{/Title} in the structure object. % The value is handled as verbatim string and hex encoded. % Commands are not expanded. |title-o| will expand the value once. % \end{function} % -% \begin{function}{alttext} +% \begin{function}{alttext (struct-key)} % This key inserts an \texttt{/Alt} value in the dictionary of structure object. % The value is handled as verbatim string and hex encoded. % The value will be expanded first once. % \end{function} -% \begin{function}{actualtext} +% \begin{function}{actualtext (struct-key)} % This key inserts an \texttt{/ActualText} value in the dictionary of structure object. % The value is handled as verbatim string and hex encoded. % The value will be expanded first once. % \end{function} -% \begin{function}{lang} +% \begin{function}{lang (struct-key)} % This key allows to set the language for a structure element. The value should be a bcp-identifier, % e.g. |de-De|. % \end{function} -% \begin{function}{ref} +% \begin{function}{ref (struct-key)} % This key allows to add references to other structure elements, % it adds the |/Ref| array to the structure. % The value should be a comma separated list of structure labels % set with the |label| key. e.g. |ref={label1,label2}|. % \end{function} -% \begin{function}{E} +% \begin{function}{E (struct-key)} % This key sets the |/E| key, the expanded form of an % abbreviation or an acronym % (I couldn't think of a better name, so I sticked to E). % \end{function} -% \begin{function}{AF,AFinline,AFinline-o} +% \begin{function}{AF (struct-key),AFinline (struct-key),AFinline-o (struct-key)} % \begin{syntax} % AF = \meta{object name}\\ -% AF-inline = \meta{text content} +% AF-inline = \meta{text content}\\ % \end{syntax} % These keys allows to reference an associated file in the structure element. % The value \meta{object name} should be the name of an object pointing @@ -165,9 +165,11 @@ % Future versions will perhaps extend this to more mime types, but it is % still a research task to find out what is really needed. % +% |AF| can be used more than once, to associate more than one file. The inline +% keys can be used only once per structure. Additional calls are ignored. % \end{function} % -% \begin{function}{attribute} +% \begin{function}{attribute (struct-key)} % This key takes as argument a comma list of attribute names % (use braces to protect the commas from the external key-val parser) % and allows to add one or more attribute dictionary entries in @@ -179,7 +181,7 @@ % % \end{function} % -% \begin{function}{attribute-class} +% \begin{function}{attribute-class (struct-key)} % This key takes as argument a comma list of attribute class names % (use braces to protect the commas from the external key-val parser) % and allows to add one or more attribute classes to the structure object. @@ -188,7 +190,7 @@ % must be declared first in \cs{tagpdfsetup}. % \end{function} % \subsection{Setup keys} -% \begin{function}{newattribute} +% \begin{function}{newattribute (setup-key)} % \begin{syntax} % newattribute = \Arg{name}\Arg{Content} % \end{syntax} @@ -206,12 +208,20 @@ % \end{verbatim} % % \end{function} +% \begin{function}{root-AF (setup-key)} +% \begin{syntax} +% root-AF = \meta{object name} +% \end{syntax} +% This key can be used in the setup command \cs{tagpdfsetup} and allows +% to add associated files to the root structure. Like |AF| it can be used more than +% once to add more than one file. +% \end{function} % \end{documentation} % \begin{implementation} % \begin{macrocode} %<@@=tag> %<*header> -\ProvidesExplPackage {tagpdf-struct-code} {2021-08-27} {0.92} +\ProvidesExplPackage {tagpdf-struct-code} {2022-01-13} {0.93} {part of tagpdf - code related to storing structure} %</header> % \end{macrocode} @@ -313,7 +323,8 @@ ParentTreeNextKey, % optional RoleMap, ClassMap, - Namespaces + Namespaces, + AF %pdf 2.0 } \seq_const_from_clist:Nn \c_@@_struct_StructElem_entries_seq @@ -742,11 +753,16 @@ % at the begin. % \begin{macro} % { -% label,stash,tag, -% title,title-o, -% alttext, -% actualtext, -% lang,ref,E +% label (struct-key), +% stash (struct-key), +% tag (struct-key), +% title (struct-key), +% title-o (struct-key), +% alttext (struct-key), +% actualtext (struct-key), +% lang (struct-key), +% ref (struct-key), +% E (struct-key) % } % \begin{macrocode} \keys_define:nn { @@ / struct } @@ -854,22 +870,51 @@ } % \end{macrocode} % \end{macro} -% \begin{macro}{AF,AFinline,AFinline-o} +% \begin{macro}{AF (struct-key),AFinline (struct-key),AFinline-o (struct-key)} % keys for the AF keys (associated files). They use commands from l3pdffile! % The stream variants use txt as extension to get the mimetype. % TODO: check if this should be configurable. For math we will perhaps need another % extension. +% AF is an array and can be used more than once, so we store it in a tl. +% which is expanded. +% AFinline can be use only once (more quite probably doesn't make sense). % \begin{macrocode} +\cs_new_protected:Npn \@@_struct_add_AF:nn #1 #2 % #1 struct num #2 object name + { + \tl_if_exist:cTF + { + g_@@_struct_#1_AF_tl + } + { + \tl_gput_right:cx + { g_@@_struct_#1_AF_tl } + { ~ \pdf_object_ref:n {#2} } + } + { + \tl_new:c + { g_@@_struct_#1_AF_tl } + \tl_gset:cx + { g_@@_struct_#1_AF_tl } + { \pdf_object_ref:n {#2} } + } + } +\cs_generate_variant:Nn \@@_struct_add_AF:nn {en,ee} \keys_define:nn { @@ / struct } { AF .code:n = % AF property { \pdf_object_if_exist:nTF {#1} { + \@@_struct_add_AF:en { \int_eval:n {\c@g_@@_struct_abs_int} }{#1} \@@_prop_gput:cnx { g_@@_struct_\int_eval:n {\c@g_@@_struct_abs_int}_prop } { AF } - { \pdf_object_ref:n {#1} } + { + [ + \tl_use:c + { g_@@_struct_\int_eval:n {\c@g_@@_struct_abs_int}_AF_tl } + ] + } } { @@ -879,16 +924,24 @@ { \group_begin: \pdf_object_if_exist:eF {@@/fileobj\int_use:N\c@g_@@_struct_abs_int} - { - \pdffile_embed_stream:nxx - {#1} - {tag-AFfile\int_use:N\c@g_@@_struct_abs_int.txt} - {@@/fileobj\int_use:N\c@g_@@_struct_abs_int} - } - \@@_prop_gput:cnx - { g_@@_struct_\int_use:N\c@g_@@_struct_abs_int _prop } - { AF } - { \pdf_object_ref:e {@@/fileobj\int_use:N\c@g_@@_struct_abs_int } } + { + \pdffile_embed_stream:nxx + {#1} + {tag-AFfile\int_use:N\c@g_@@_struct_abs_int.txt} + {@@/fileobj\int_use:N\c@g_@@_struct_abs_int} + \@@_struct_add_AF:ee + { \int_eval:n {\c@g_@@_struct_abs_int} } + { @@/fileobj\int_use:N\c@g_@@_struct_abs_int } + \@@_prop_gput:cnx + { g_@@_struct_\int_use:N\c@g_@@_struct_abs_int _prop } + { AF } + { + [ + \tl_use:c + { g_@@_struct_\int_eval:n {\c@g_@@_struct_abs_int}_AF_tl } + ] + } + } \group_end: } ,AFinline-o .code:n = @@ -900,24 +953,63 @@ {#1} {tag-AFfile\int_use:N\c@g_@@_struct_abs_int.txt} {@@/fileobj\int_use:N\c@g_@@_struct_abs_int} + \@@_struct_add_AF:ee + { \int_eval:n {\c@g_@@_struct_abs_int} } + { @@/fileobj\int_use:N\c@g_@@_struct_abs_int } + \@@_prop_gput:cnx + { g_@@_struct_\int_use:N\c@g_@@_struct_abs_int _prop } + { AF } + { + [ + \tl_use:c + { g_@@_struct_\int_eval:n {\c@g_@@_struct_abs_int}_AF_tl } + ] + } } - \@@_prop_gput:cnx - { g_@@_struct_\int_use:N\c@g_@@_struct_abs_int _prop } - { AF } - { \pdf_object_ref:e {@@/fileobj\int_use:N\c@g_@@_struct_abs_int } } \group_end: } } +%</package> +% \end{macrocode} +% \end{macro} +% \begin{macro}{root-AF (setup-key)} +% The root structure can take AF keys too, so we provide a key for it. +% This key is used with |\tagpdfsetup|, not in a structure! +% \begin{macrocode} +\keys_define:nn { @@ / setup } + { + root-AF .code:n = + { + \pdf_object_if_exist:nTF {#1} + { + \@@_struct_add_AF:en { 0 }{#1} + \@@_prop_gput:cnx + { g_@@_struct_0_prop } + { AF } + { + [ + \tl_use:c + { g_@@_struct_0_AF_tl } + ] + } + } + { + + } + }, + } % \end{macrocode} % \end{macro} -% % \section{User commands} % % \begin{macro}{\tag_struct_begin:n,\tag_struct_end:} % \begin{macrocode} -\cs_new_protected:Npn \tag_struct_begin:n #1 %#1 key-val +%<*package|debug> +%<package>\cs_new_protected:Npn \tag_struct_begin:n #1 %#1 key-val +%<debug>\cs_set_protected:Npn \tag_struct_begin:n #1 %#1 key-val { - \@@_check_if_active_struct:T +%<package>\@@_check_if_active_struct:T +%<debug>\@@_check_if_active_struct:TF { \group_begin: \int_gincr:N \c@g_@@_struct_abs_int @@ -970,16 +1062,18 @@ } %\prop_show:c { g_@@_struct_\g_@@_struct_stack_current_tl _prop } %\seq_show:c {g_@@_struct_kids_\l_@@_struct_stack_parent_tmpa_tl _seq} +%<debug> \@@_debug_struct_begin_insert:n { #1 } \group_end: } +%<debug>{ \@@_debug_struct_begin_ignore:n { #1 }} } - - -\cs_new_protected:Nn \tag_struct_end: +%<package>\cs_new_protected:Nn \tag_struct_end: +%<debug>\cs_set_protected:Nn \tag_struct_end: { %take the current structure num from the stack: %the objects are written later, lua mode hasn't all needed info yet %\seq_show:N \g_@@_struct_stack_seq - \@@_check_if_active_struct:T +%<package>\@@_check_if_active_struct:T +%<debug>\@@_check_if_active_struct:TF { \seq_gpop:NN \g_@@_struct_tag_stack_seq \l_@@_tmpa_tl \seq_gpop:NNTF \g_@@_struct_stack_seq \l_@@_tmpa_tl @@ -999,14 +1093,18 @@ { \tl_gset:NV \g_@@_struct_tag_tl \l_@@_tmpa_tl } +%<debug>\@@_debug_struct_end_insert: } +%<debug>{\@@_debug_struct_end_ignore:} } +%</package|debug> % \end{macrocode} % \end{macro} % \begin{macro}{\tag_struct_use:n} % This command allows to use a stashed structure in another place. % TODO: decide how it should be guarded. Probably by the struct-check. % \begin{macrocode} +%<*package> \cs_new_protected:Nn \tag_struct_use:n %#1 is the label { \@@_check_if_active_struct:T @@ -1073,7 +1171,7 @@ % \section{Attributes and attribute classes} % \begin{macrocode} %<*header> -\ProvidesExplPackage {tagpdf-attr-code} {2021-08-27} {0.92} +\ProvidesExplPackage {tagpdf-attr-code} {2022-01-13} {0.93} {part of tagpdf - code related to attributes and attribute classes} %</header> % \end{macrocode} @@ -1101,7 +1199,7 @@ % \end{macrocode} % \end{variable} % \subsection{Commands and keys} -% \begin{macro}{\@@_attr_new_entry:nn,newattribute} +% \begin{macro}{\@@_attr_new_entry:nn,newattribute (setup-key)} % This allows to define attributes. Defined attributes % are stored in a global property. |newattribute| expects % two brace group, the name and the content. The content typically @@ -1132,7 +1230,7 @@ } % \end{macrocode} % \end{macro} -% \begin{macro}{attribute-class} +% \begin{macro}{attribute-class (struct-key)} % attribute-class has to store the used attribute names so that % they can be added to the ClassMap later. % \begin{macrocode} @@ -1172,7 +1270,7 @@ } % \end{macrocode} % \end{macro} -% \begin{macro}{attribute} +% \begin{macro}{attribute (struct-key)} % \begin{macrocode} \keys_define:nn { @@ / struct } { diff --git a/macros/latex/contrib/tagpdf/tagpdf-tree.dtx b/macros/latex/contrib/tagpdf/tagpdf-tree.dtx index b8e1b0d54a..e6964666d9 100644 --- a/macros/latex/contrib/tagpdf/tagpdf-tree.dtx +++ b/macros/latex/contrib/tagpdf/tagpdf-tree.dtx @@ -2,7 +2,7 @@ % %% File: tagpdf-tree.dtx % -% Copyright (C) 2019-2021 Ulrike Fischer +% Copyright (C) 2019-2022 Ulrike Fischer % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -51,13 +51,13 @@ % }^^A % } % -% \date{Version 0.92, released 2021-08-27} +% \date{Version 0.93, released 2022-01-13} % \maketitle % \begin{implementation} % \begin{macrocode} %<@@=tag> %<*header> -\ProvidesExplPackage {tagpdf-tree-code} {2021-08-27} {0.92} +\ProvidesExplPackage {tagpdf-tree-code} {2022-01-13} {0.93} {part of tagpdf - code related to writing trees and dictionaries to the pdf} %</header> % \end{macrocode} diff --git a/macros/latex/contrib/tagpdf/tagpdf-user.dtx b/macros/latex/contrib/tagpdf/tagpdf-user.dtx index 23737dfc29..2b58d81659 100644 --- a/macros/latex/contrib/tagpdf/tagpdf-user.dtx +++ b/macros/latex/contrib/tagpdf/tagpdf-user.dtx @@ -2,7 +2,7 @@ % %% File: tagpdf-user.dtx % -% Copyright (C) 2019-2021 Ulrike Fischer +% Copyright (C) 2019-2022 Ulrike Fischer % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -50,7 +50,7 @@ % }^^A % } % -% \date{Version 0.92, released 2021-08-27} +% \date{Version 0.93, released 2022-01-13} % \maketitle % \begin{documentation} % \section{Setup commands} @@ -60,7 +60,18 @@ % \end{syntax} % This is the main setup command to adapt the behaviour of tagpdf. % It can be used in the preamble and in the document (but not all keys make sense there). +% \end{function} % +% \begin{function}{activate (setup-key)} +% And additional setup key which combine the other activate keys +% |activate-mc|, |activate-tree|, |activate-struct| and additionally +% add a document structure. +% \end{function} +% +% +% \begin{function}{\tagpdfifluatexTF,\tagpdfifluatexT,\tagpdfifpdftexT} +% small wrappers around engine tests. This functions should not be used and will be removed +% in one of the next versions. % \end{function} % % \section{Commands related to mc-chunks} @@ -76,7 +87,7 @@ % and \cs{tagmcend} will issue in horizontal mode an \cs{unskip}. % \end{function} % -% \begin{function}{\tagmcifin} +% \begin{function}{\tagmcifinTF} % \begin{syntax} % \cs{tagmcifin} \Arg{true code}\Arg{false code} % \end{syntax} @@ -112,7 +123,7 @@ % necessarly stops the compilation. The keys and their function are described below. % \end{function} % -% \begin{function}{mc-data} +% \begin{function}{mc-data (show-key)} % \begin{syntax} % |mc-data| = \meta{number} % \end{syntax} @@ -123,7 +134,7 @@ % newpage. The value is a positive integer and sets the first mc-shown. If no value % is given, 1 is used and so all mc-chunks created so far are shown. % \end{function} -% \begin{function}{mc-current} +% \begin{function}{mc-current (show-key)} % \begin{syntax} % |mc-current| % \end{syntax} @@ -131,7 +142,14 @@ % chunk is open it shows only the state of the abs count. It works in all mode, % but the output in luamode looks different. % \end{function} -% \begin{function}{struct-stack} +% \begin{function}{mc-marks (show-key)} +% \begin{syntax} +% |mc-marks| = |show|\verb+|+|use| +% \end{syntax} +% This key helps to debug the page marks. It should only be used at shipout in +% header or footer. +% \end{function} +% \begin{function}{struct-stack (show-key)} % \begin{syntax} % |struct-stack| = |log|\verb+|+|show| % \end{syntax} @@ -163,7 +181,7 @@ % faulty code, e.g. a missing |\par| at the end of a low-level vbox can highly % confuse the tagging. The tags should be carefully checked if this is used. % -% \begin{function}{paratagging,paratagging-show} +% \begin{function}{paratagging (setup-key),paratagging-show (setup-key)} % \begin{syntax} % |paratagging| = |true|\verb+|+|false|\\ % |paratagging-show| = |true|\verb+|+|false|\\ @@ -179,15 +197,34 @@ % faster then |\tagpdfsetup|. But I'm not sure if the names are good. % \end{function} % +% \begin{function}{\tagpdfsuppressmarks} +% This command allows to suppress the creation of the marks. It takes an argument +% which should normally be one of the mc-commands, puts a group around it and +% suppress the marks creation in this group. This command should be used if +% the begin and end command are at different boxing levels. E.g. +% \begin{verbatim} +% \@hangfrom +% { +% \tagstructbegin{tag=H1}% +% \tagmcbegin {tag=H1}% +% #2 +% } +% {#3\tagpdfsuppressmarks{\tagmcend}\tagstructend}% +% \end{verbatim} +% \end{function} +% % \subsection{Header and footer} -% Header and footer are automatically excluded from tagging. This can for -% now to allow debugging be disabled with the following key, but probably -% this key will disappear again. If some real content is in the header and +% Header and footer are automatically excluded from tagging. This can +% be disabled with the following key. +% If some real content is in the header and % footer, tagging must be restarted there explicitly. +% The key accepts the values |true| which surrounds the header with an artifact +% mc-chunk, |false| which disables the automatic tagging, and |pagination| which +% additionally adds an artifact structure with an pagination attribute. % -% \begin{function}{exclude-header-footer} +% \begin{function}{exclude-header-footer (setup-key)} % \begin{syntax} -% |exclude-header-footer| = |true|\verb+|+|false| +% |exclude-header-footer| = |true|\verb+|+|false|\verb+|+pagination % \end{syntax}% % \end{function} @@ -213,7 +250,7 @@ % \begin{macrocode} %<@@=tag> %<*header> -\ProvidesExplPackage {tagpdf-user} {2021-08-27} {0.92} +\ProvidesExplPackage {tagpdf-user} {2022-01-13} {0.93} {tagpdf - user commands} %</header> % \end{macrocode} @@ -288,14 +325,6 @@ % \end{macro} % % -% \begin{macro}{\tagpdfifluatexTF,\tagpdfifluatexT,\tagpdfifpdftexTF} -% I should deprecate them ... -% \begin{macrocode} -\cs_set_eq:NN\tagpdfifluatexTF \sys_if_engine_luatex:TF -\cs_set_eq:NN\tagpdfifluatexT \sys_if_engine_luatex:T -\cs_set_eq:NN\tagpdfifpdftexT \sys_if_engine_pdftex:T -% \end{macrocode} -% \end{macro} % % \section{Debugging} % \begin{macro}{\ShowTagging} @@ -310,7 +339,7 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}{mc-data} +% \begin{macro}{mc-data (show-key)} % This key is (currently?) relevant for lua mode only. % It shows the data of all mc-chunks created so far. % It is accurate only after shipout, so typically should be issued after a @@ -330,7 +359,7 @@ % \end{macrocode} % \end{macro} -% \begin{macro}{mc-current} +% \begin{macro}{mc-current (show-key)} % This shows some info about the current mc-chunk. It works in generic and lua-mode. % \begin{macrocode} \keys_define:nn { @@ / show } @@ -397,7 +426,7 @@ } % \end{macrocode} % \end{macro} -% \begin{macro}{mc-marks} +% \begin{macro}{mc-marks (show-key)} % It maps the mc-marks into the sequences and then shows them. % This allows to inspect the first and last mc-Mark on a page. % It should only be used in the shipout (header/footer). @@ -447,7 +476,7 @@ } % \end{macrocode} % \end{macro} -% \begin{macro}{struct-stack} +% \begin{macro}{struct-stack (show-key)} % \begin{macrocode} \keys_define:nn { @@ / show } { @@ -466,7 +495,7 @@ % This part should be regularly revisited to check if the code should go to a % better place or can be improved. % \subsection{Document structure} -% \begin{macro}{\@@_add_document_structure:n,activate} +% \begin{macro}{\@@_add_document_structure:n,activate (setup-key)} % \begin{macrocode} \cs_new_protected:Npn \@@_add_document_structure:n #1 { @@ -485,6 +514,28 @@ } % \end{macrocode} % \end{macro} +% \subsection{Structure destinations} +% In TeXlive 2022 pdftex and luatex will offer support for structure destinations. +% The pdfmanagement has already backend support. We activate them if the +% prerequisites are there: The pdf version should be 2.0, structures should be activated, +% the code in the pdfmanagement must be there. +% \begin{macrocode} +\AddToHook{begindocument/before} + { + \bool_lazy_all:nT + { + { \g_@@_active_struct_dest_bool } + { \g_@@_active_struct_bool } + { \cs_if_exist_p:N \pdf_activate_structure_destination: } + { ! \pdf_version_compare_p:Nn < {2.0} } + } + { + \tl_set:Nn \l_pdf_current_structure_destination_tl { __tag/struct/\g__tag_struct_stack_current_tl } + \pdf_activate_structure_destination: + } + } +% \end{macrocode} + % \subsection{Fake space} % \begin{macro}{\pdffakespace} % We need a luatex variant for |\pdffakespace|. This should probably go into @@ -518,8 +569,8 @@ % %\begin{macro} % { -% paratagging, -% paratagging-show, +% paratagging (setup-key), +% paratagging-show (setup-key), % } % These keys enable/disable locally paratagging, and the debug modus. % It can affect the typesetting if |paratagging-show| is used. The small numbers @@ -593,7 +644,7 @@ \tl_put_right:Nn \@mult@ptagging@hook { \@@_check_typeout_v:n {====>~In~\string\page@sofar} - \process@cols\mult@gfirstbox + \process@cols\mult@firstbox { \@@_add_missing_mcs_to_stream:Nn \count@ {multicol} } @@ -686,7 +737,41 @@ \bool_gset_eq:NN \g_@@_in_mc_bool\g_@@_saved_in_mc_bool } } +% \end{macrocode} +% This version allows to use an Artifact structure +% \begin{macrocode} +\@@_attr_new_entry:nn {@@/attr/pagination}{/O/Artifact/Type/Pagination} +\cs_new_protected:Npn \@@_exclude_struct_headfoot_begin:n #1 + { + \bool_set_false:N \l_@@_para_bool + \bool_if:NTF \g_@@_mode_lua_bool + { + \tag_mc_end_push: + } + { + \bool_gset_eq:NN \g_@@_saved_in_mc_bool \g_@@_in_mc_bool + \bool_gset_false:N \g_@@_in_mc_bool + } + \tag_struct_begin:n{tag=Artifact,attribute-class=@@/attr/#1} + \tag_mc_begin:n {artifact=#1} + } +\cs_new_protected:Npn \@@_exclude_struct_headfoot_end: + { + \tag_mc_end: + \tag_struct_end: + \bool_if:NTF \g_@@_mode_lua_bool + { + \tag_mc_begin_pop:n{} + } + { + \bool_gset_eq:NN \g_@@_in_mc_bool\g_@@_saved_in_mc_bool + } + } +% \end{macrocode} +% And now the keys +% \begin{macro}{exclude-header-footer (setup-key)} +% \begin{macrocode} \keys_define:nn { @@ / setup } { exclude-header-footer .choice:, @@ -697,6 +782,13 @@ \cs_set_eq:NN \@@_hook_kernel_after_head: \@@_exclude_headfoot_end: \cs_set_eq:NN \@@_hook_kernel_after_foot: \@@_exclude_headfoot_end: }, + exclude-header-footer / pagination .code:n = + { + \cs_set:Nn \@@_hook_kernel_before_head: { \@@_exclude_struct_headfoot_begin:n {pagination} } + \cs_set:Nn \@@_hook_kernel_before_foot: { \@@_exclude_struct_headfoot_begin:n {pagination} } + \cs_set_eq:NN \@@_hook_kernel_after_head: \@@_exclude_struct_headfoot_end: + \cs_set_eq:NN \@@_hook_kernel_after_foot: \@@_exclude_struct_headfoot_end: + }, exclude-header-footer / false .code:n = { \cs_set_eq:NN \@@_hook_kernel_before_head: \prg_do_nothing: @@ -708,7 +800,7 @@ exclude-header-footer .initial:n = true } % \end{macrocode} - +% \end{macro} % \subsection{Links} % We need to close and reopen mc-chunks around links. % Currently we handle URI and GoTo (internal) links. diff --git a/macros/latex/contrib/tagpdf/tagpdf.dtx b/macros/latex/contrib/tagpdf/tagpdf.dtx index 0aeac22d7f..5406505c59 100644 --- a/macros/latex/contrib/tagpdf/tagpdf.dtx +++ b/macros/latex/contrib/tagpdf/tagpdf.dtx @@ -2,7 +2,7 @@ % %% File: tagpdf.dtx % -% Copyright (C) 2019-2021 Ulrike Fischer +% Copyright (C) 2019-2022 Ulrike Fischer % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -23,13 +23,64 @@ % for those people who are interested. % % \fi +% \begin{documentation} +% \begin{function}{\ref_value:nnn} +% This is a temporary definition which will have to +% move to l3ref. It allows to locally set a default value if the label or the attribute +% doesn't exist. See issue \#4 in Accessible-xref. +% \begin{syntax} +% \cs{ref_value:nnn}\Arg{label}\Arg{attribute}\Arg{fallback default} +% \end{syntax} +% \end{function} +% +% \begin{function}{ \tag_stop_group_begin:, \tag_stop_group_end: } +% We need a command to stop tagging in some places. +% This simply switches the two local booleans. +% \end{function} +% +% \begin{function}{activate-space (setup-key)} +% |activate-space| activates the additional parsing needed for +% interword spaces. It is not documented, the parsing is currently +% implicitly activated by the known key |interwordspace|, as the code will +% perhaps move to some other place, now that it is better separated. +% \end{function} +% +% \begin{function}{activate-mc (setup-key), +% activate-tree (setup-key), +% activate-struct (setup-key), +% activate-all (setup-key)} +% Keys to activate the various tagging steps +% \end{function} +%\begin{function}{no-struct-dest (setup-key)} +% The key allows to suppress the creation of structure destinations +% \end{function} +% +% \begin{function}{log (setup-key)} +% The |log| takes currently the values |none|, |v|, |vv|, |vvv|, |all|. +% More details are in \texttt{tagpdf-checks}. +% \end{function} +% +% \begin{function}{tagunmarked (setup-key)} +% This key allows to set if (in luamode) unmarked text should be +% marked up as artifact. The initial value is true. +% \end{function} +% +% \begin{function}{tabsorder (setup-key)} +% This sets the tabsorder on a page. The values are |row|, |column|, |structure| (default) +% or |none|. Currently this is set more or less globally. More finer control can be +% added if needed. +% \end{function} % +% \begin{function}{tagstruct,tagstructobj,tagabspage,tagmcabs,tagmcid} +% These are attributes used by the label/ref system. +% \end{function} +% \end{documentation} % \begin{implementation} % \section{Initialization and test if pdfmanagement is active.} % \begin{macrocode} %<@@=tag> %<*package> -\ProvidesExplPackage {tagpdf} {2021-08-27} {0.92} +\ProvidesExplPackage {tagpdf} {2022-01-13} {0.93} { A package to experiment with pdf tagging } \bool_if:nF @@ -51,18 +102,33 @@ before~\string\documentclass } } +%</package> % \end{macrocode} +%<*debug> +% \begin{macrocode} +\ProvidesExplPackage {tagpdf-debug} {2022-01-13} {0.93} + { debug code for tagpdf } +\@ifpackageloaded{tagpdf}{}{\PackageWarning{tagpdf-debug}{tagpdf~not~loaded,~quitting}\endinput} + \end{macrocode} +%</debug> % We map the internal module name \enquote{tag} to \enquote{tagpdf} in messages. % \begin{macrocode} -\prop_if_exist:NT \g_msg_module_name_prop - { - \prop_gput:Nnn \g_msg_module_name_prop { tag }{ tagpdf } - } +%<*package> +\prop_gput:Nnn \g_msg_module_name_prop { tag }{ tagpdf } +%</package> +% \end{macrocode} +% Debug mode has its special mapping: +% \begin{macrocode} +%<*debug> +\prop_gput:Nnn \g_msg_module_type_prop { tag / debug} {} +\prop_gput:Nnn \g_msg_module_name_prop { tag / debug }{tagpdf~DEBUG} +%</debug> % \end{macrocode} %\section{Package options} % There are only two options to switch for luatex between generic and luamode, % TODO try to get rid of them. % \begin{macrocode} +%<*package> \bool_new:N\g_@@_mode_lua_bool \DeclareOption {luamode} { \sys_if_engine_luatex:T { \bool_gset_true:N \g_@@_mode_lua_bool } } \DeclareOption {genericmode}{ \bool_gset_false:N\g_@@_mode_lua_bool } @@ -105,10 +171,6 @@ % \begin{macro}{\ref_value:nnn} % This allows to locally set a default value if the label or the attribute % doesn't exist. -% See issue \#4 in Accessible-xref. -% \begin{syntax} -% \cs{ref_value:nnn}\Arg{label}\Arg{attribute}\Arg{Fallback default} -% \end{syntax} % \begin{macrocode} \cs_if_exist:NF \ref_value:nnn { @@ -180,7 +242,8 @@ % \g_@@_active_space_bool, % \g_@@_active_mc_bool, % \g_@@_active_tree_bool, -% \g_@@_active_struct_bool +% \g_@@_active_struct_bool, +% \g_@@_active_struct_dest_bool % } % These booleans should help to control the global behaviour of tagpdf. % Ideally it should more or less do nothing if all are false. @@ -190,6 +253,8 @@ % commands, the struct-boolean activates the storing of the structure data. % In a normal document all should be active, the split is only there for % debugging purpose. +% Structure destination will be activated automatically if pdf version 2.0 is detected, +% but with the boolean struct-dest-boolean one can suppress them. % Also we assume currently that they are set only at begin document. But % if some control passing over groups are needed they could be perhaps % used in a document too. @@ -199,6 +264,8 @@ \bool_new:N \g_@@_active_mc_bool \bool_new:N \g_@@_active_tree_bool \bool_new:N \g_@@_active_struct_bool +\bool_new:N \g_@@_active_struct_dest_bool +\bool_gset_true:N \g_@@_active_struct_dest_bool % \end{macrocode} % \end{variable} @@ -369,17 +436,19 @@ % % \begin{macro} % { -% activate-space, -% activate-mc, -% activate-tree, -% activate-struct, -% activate-all, +% activate-space (setup-key), +% activate-mc (setup-key), +% activate-tree (setup-key), +% activate-struct (setup-key), +% activate-all (setup-key), +% no-struct-dest (setup-key) % } % Keys to (globally) activate tagging. % |activate-space| activates the additional parsing needed for % interword spaces. It is not documented, the parsing is currently % implicitly activated by the known key |interwordspace|, as the code will % perhaps move to some other place, now that it is better separated. +% |no-struct-dest| allows to suppress structure destinations. % \begin{macrocode} \keys_define:nn { @@ / setup } { @@ -388,10 +457,12 @@ activate-tree .bool_gset:N = \g_@@_active_tree_bool, activate-struct .bool_gset:N = \g_@@_active_struct_bool, activate-all .meta:n = - {activate-mc,activate-tree,activate-struct}, + {activate-mc={#1},activate-tree={#1},activate-struct={#1}}, + activate-all .default:n = true, + no-struct-dest .bool_gset_inverse:N = \g_@@_active_struct_dest_bool, % \end{macrocode} % \end{macro} -% \begin{macro}{log} +% \begin{macro}{log (setup-key)} % The |log| takes currently the values |none|, |v|, |vv|, |vvv|, |all|. % The description of the log levels is in tagpdf-checks. % \begin{macrocode} @@ -407,7 +478,7 @@ log / all .code:n = {\int_set:Nn \l_@@_loglevel_int { 10 }}, % \end{macrocode} % \end{macro} -% \begin{macro}{tagunmarked} +% \begin{macro}{tagunmarked (setup-key)} % This key allows to set if (in luamode) unmarked text should be % marked up as artifact. The initial value is true. % \begin{macrocode} @@ -415,9 +486,9 @@ tagunmarked .initial:n = true, % \end{macrocode} % \end{macro} -% \begin{macro}{tabsorder} -% This sets the tabsorder one a page. The values are |row|, |column|, |structure| (default) -% or |none|. Currently this is set more or less globally. More finer controll can be +% \begin{macro}{tabsorder (setup-key)} +% This sets the tabsorder on a page. The values are |row|, |column|, |structure| (default) +% or |none|. Currently this is set more or less globally. More finer control can be % added if needed. % \begin{macrocode} tabsorder .choice:, @@ -452,6 +523,15 @@ \RequirePackage {tagpdf-mc-code-generic} % } %</mcloading> +%<*debug> +\bool_if:NTF \g_@@_mode_lua_bool + { + \RequirePackage {tagpdf-debug-lua} + } + { + \RequirePackage {tagpdf-debug-generic} % + } +%</debug> % \end{macrocode} % \end{implementation} % \PrintIndex diff --git a/macros/latex/contrib/tagpdf/tagpdf.ins b/macros/latex/contrib/tagpdf/tagpdf.ins index 583509d4a2..e212ae48b2 100644 --- a/macros/latex/contrib/tagpdf/tagpdf.ins +++ b/macros/latex/contrib/tagpdf/tagpdf.ins @@ -2,7 +2,7 @@ File: tagpdf.ins -Copyright (C) 2019-2021 Ulrike Fischer +Copyright (C) 2019-2022 Ulrike Fischer It may be distributed and/or modified under the conditions of the LaTeX Project Public License (LPPL), either version 1.3c of this @@ -34,7 +34,7 @@ for those people who are interested. \let\MetaPrefix\relax \preamble -Copyright (C) 2019-2021 Ulrike Fischer +Copyright (C) 2019-2022 Ulrike Fischer It may be distributed and/or modified under the conditions of the LaTeX Project Public License (LPPL), either version 1.3c of @@ -59,13 +59,13 @@ and all files in that bundle must be distributed together. { \from{tagpdf.dtx}{package} \from{tagpdf-checks.dtx}{package} - \from{tagpdf-user.dtx}{package} \from{tagpdf-mc-shared.dtx}{shared} \from{tagpdf.dtx}{mcloading} \from{tagpdf-tree.dtx}{package} \from{tagpdf-roles.dtx}{package} \from{tagpdf-struct.dtx}{package}%contains also the attr code. \from{tagpdf-space.dtx}{package} + \from{tagpdf-user.dtx}{package} } } @@ -76,6 +76,26 @@ and all files in that bundle must be distributed together. \generate {\file{tagpdf-mc-code-lua.sty}{\from{tagpdf-mc-luacode.dtx}{luamode}}} +% check later if the mc-code uses debug guards too. +\generate + {\file{tagpdf-debug.sty} + { + \from{tagpdf.dtx}{debug} + \from{tagpdf-checks.dtx}{debug} + \from{tagpdf-user.dtx}{debug} + \from{tagpdf-mc-shared.dtx}{debug} + \from{tagpdf-tree.dtx}{debug} + \from{tagpdf-roles.dtx}{debug} + \from{tagpdf-struct.dtx}{debug}% + \from{tagpdf-space.dtx}{debug} + } + } + +\generate + {\file{tagpdf-debug-generic.sty}{\from{tagpdf-mc-generic.dtx}{debug}}} + +\generate + {\file{tagpdf-debug-lua.sty}{\from{tagpdf-mc-luacode.dtx}{debug}}} \def\MetaPrefix{-- } \def\defaultpostamble{% diff --git a/macros/latex/contrib/tagpdf/tagpdf.pdf b/macros/latex/contrib/tagpdf/tagpdf.pdf Binary files differindex 58004f717f..72892e853c 100644 --- a/macros/latex/contrib/tagpdf/tagpdf.pdf +++ b/macros/latex/contrib/tagpdf/tagpdf.pdf diff --git a/macros/latex/contrib/tagpdf/tagpdf.tex b/macros/latex/contrib/tagpdf/tagpdf.tex index e1d690fc95..af08d81651 100644 --- a/macros/latex/contrib/tagpdf/tagpdf.tex +++ b/macros/latex/contrib/tagpdf/tagpdf.tex @@ -1,12 +1,11 @@ % !Mode:: "TeX:DE:UTF-8:Main" %\PassOptionsToPackage{check-declarations,enable-debug}{expl3} -\RequirePackage{pdfmanagement-testphase} -\DeclareDocumentMetadata{pdfversion=2.0,lang=en-UK} - +%\RequirePackage{pdfmanagement-testphase} +\DocumentMetadata{pdfversion=2.0,lang=en-UK,testphase=phase-II} \makeatletter -\def\UlrikeFischer@package@version{0.92} -\def\UlrikeFischer@package@date{2021-08-27} +\def\UlrikeFischer@package@version{0.93} +\def\UlrikeFischer@package@date{2022-01-13} \makeatother \documentclass[DIV=12,parskip=half-,bibliography=totoc]{scrartcl} @@ -16,6 +15,10 @@ \usepackage{unicode-math} \setmainfont{Heuristica} \usepackage{microtype} +\makeatletter +% see https://github.com/schlcht/microtype/issues/8 +\patchcmd{\MT@get@prot}{\noindent}{\RawNoindent}{}{\fail} +\makeatother \usepackage{scrlayer-scrpage} @@ -46,12 +49,9 @@ commentstyle=\color{green!50!black}\bfseries} -\usepackage{tagpdf} + \tagpdfsetup{ - activate-all, - uncompress, tabsorder=structure, - interwordspace=true, %log=v %show-spaces } @@ -150,6 +150,21 @@ Issues, comments, suggestions should be added as issues to the github tracker: \tableofcontents +\section{Preface to version 0.93} +The main change in the package itself in this version is the support for structure destinations. +This is a new type of destinations in \PDF~2.0. +For pdftex and luatex this requires new binaries. They will be included +in texlive 2022, miktex already has the new pdftex, the new luatex will probably follow soon. + +Beside this mostly some clean up and bug fixes has been done. + +A more important step will be done in \LaTeX{} itself in the next dev-release: The command \cs{DocumentMetadata} will be +added to the format and will take over the role of \cs{DeclareDocumentMetadata} from \pkg{pdfmanagement-testphase} and additionally +will also load the pdf management code. This will simplify the documents as it will no longer be needed to load +a package. + + + \section{Preface to version 0.92} In this version support for page breaks in pdftex has been added. As described in section~\ref{sec:splitpara}, @@ -318,7 +333,7 @@ utf8 is now the required encoding. \item The keys |lang|, |ref| and |E| have been added for structures. \item The new hooks of LaTeX are used to tagged many paragraphs automatically. The small red numbers around paragraphs in the documentation show them in action. The main problem here is not to tag a paragraph, but to avoid to tag too many: paragraphs pop up in many places. -\end{itemize} +\end{itemize} \subsection{Changes in version 0.81} @@ -390,6 +405,25 @@ will now expand once. \end{itemize} +\subsection{Changes in version 0.93} + +\begin{itemize} +\item Support for associated files in the root element (key \texttt{root-AF}) +has been added. This allow e.g. to add a css-file which is be used if the \PDF\ is converted to +html. + +\item First steps have been done to adapt the package to planed changes in \LaTeX{}: The command \cs{DocumentMetadata} will be +added to the format and will take over the role of \cs{DeclareDocumentMetadata} from \pkg{pdfmanagement-testphase}. + +\item The package has now support for \enquote{structure destinations}. +This is a new type of destinations in \PDF~2.0. +For pdftex and luatex this requires new binaries. They will be included +in texlive 2022, miktex already has the new pdftex, the new luatex will probably follow soon. + +\item The commands \cs{tagpdfifluatexT}, \cs{tagpdfifluatexTF} has been removed \cs{tagpdfifpdftexT}, + +\end{itemize} + \subsection{Proof of concept: the tagging of the documentation itself} Starting with version 0.6 the documentation itself has been tagged. The tagging wasn't (and isn't) in no way perfect. The validator from Adobe didn't complain, but PAX3 wanted alternative text for all links (no idea why) and so I put everywhere simple text like \enquote{link} and \enquote{ref}. The links to footnotes gave warnings, so I disabled them. I used types from the \PDF{} version 1.7, mostly as I have no idea what should be used for code in 2.0. Margin notes were simply wrong \ldots @@ -424,15 +458,27 @@ activated like this: } \documentclass{article} \begin{document} -some text +some text \end{document} \end{lstlisting} +With \LaTeX{} 2022-06-01 (or a current \LaTeX-dev) the call will be simpler + +\begin{lstlisting} +\DocumentMetadata + { + testphase = tagpdf, % load + activate + } +\documentclass{article} +\begin{document} +some text +\end{document} +\end{lstlisting} \minisec{Activation needed!} -When the package is loaded it will -- apart from loading more packages and defining a lot of things -- not do much. You will have to activate it with \verb+\tagpdfsetup+ or as shown above in \verb+\DeclareDocumentMetadata+. +When the package is loaded it will -- apart from loading more packages and defining a lot of things -- not do much. You will have to activate it with \verb+\tagpdfsetup+ or as shown above in \verb+\DeclareDocumentMetadata+/\verb+\DocumentMetadata+. Most commands do nothing if tagging is not activated, but in case a test is needed a command (with the usual p,T,F variants) is provided: @@ -478,6 +524,9 @@ The default value is |Document|. Boolean, initially false. Activates the code related to marked content. \item[\PrintKeyName{activate-struct}] Boolean, initially false. Activates the code related to structures. Should be used only if \PrintKeyName{activate-mc} has been used too. +\item[\PrintKeyName{no-struct-dest}] + Starting with version 0.93 \pkg{tagpdf} will create automatically structure destinations (see section~\ref{sec:struct-dest} if \pkg{hyperref} is used, if + the engine supports it and if the pdf version is 2.0. With this key this can be suppressed. \item[\PrintKeyName{activate-tree}] Boolean, initially false. Activates the code related to trees. Should be used only if the two other keys has been used too. \item[\PrintKeyName{add-new-tag}] @@ -794,7 +843,7 @@ The key-val list understands the following keys: This key sets a label by which you can call the marked content later in another structure (if it has been stashed with the previous key). Internally the label name will start with \texttt{tagpdf-}. \item[\PrintKeyName{alttext}] - This key inserts an \texttt{/Alt} value in the property dictionary of the BDC operator. See section~\ref{sec:alttext}. The value is handled as verbatim string, commands are not expanded but the value will be expanded first once (so works like the key \texttt{alttext-o} in previous versions which has been removed). + This key inserts an \texttt{/Alt} value in the property dictionary of the BDC operator. See section~\ref{sec:alttext}. The value is handled as verbatim string, commands are not expanded but the value will be expanded first once (so works like the key \texttt{alttext-o} in previous versions which has been removed). That means that you can do something like in the following listing and it will insert \verb+\frac{a}{b}+ (hex encoded) in the \PDF{}. @@ -809,14 +858,17 @@ The key-val list understands the following keys: \item[\PrintKeyName{actualtext}] This key inserts an \texttt{/ActualText} value in the property dictionary of the BDC operator. See section~\ref{sec:alttext}. The value is handled as verbatim string, commands are not expanded but the value will be expanded first once (so works like the key \texttt{actualtext-o} in previous versions which has been removed). - That means that you can do something like in the following listing and and it will insert \verb+X+ (hex encoded) in the \PDF{}. + That means that you can do something like in the following listing and and it will insert \verb+X+ (hex encoded) in the \PDF{}. \begin{lstlisting} \newcommand\myactualtext{X} - \tagmcbegin{tag=P,actualtext=\myactualtext} + \tagmcbegin{tag=Span,actualtext=\myactualtext} \end{lstlisting} + According to the PDF reference, \texttt{/ActualText} should only be used on marked content sequence of type Span. This is not enforced by the code currently. + + \item[\PrintKeyName{raw}] This key allows you to add more entries to the properties dictionary. The value must be correct, low-level \PDF{}. E.g. \verb+raw=/Alt (Hello)+ will insert an alternative Text. \end{description} @@ -1005,7 +1057,11 @@ repeated on every page at best only once. All this need some thoughts both from providing support for header and footers. For now tagpdf added some first support for automatically tagging: -Starting with version 0.92 header and footer are automatically marked up as (simple) artifacts. +Starting with version 0.92 header and footer are by default automatically marked up as (simple) artifacts. + +With the key \PrintKeyName{exclude-header-footer} the behaviour can be changed: The value \texttt{false} disables the +automatic tagging, the value \texttt{pagination} add additionally an \texttt{/Artifact} structure with the attribute \texttt{/Pagination}. + If some additional markup (or even a structure) is wanted, something like this should be used (here with the syntax of the \pkg{fancyhdr} package) to close the open mc-chunk and restart if after the content: @@ -1299,8 +1355,10 @@ The key-val list understands the following keys: For example: \begin{lstlisting} + \group_begin: \pdfdict_put:nnn {l_pdffile/Filespec} {AFRelationship}{/Supplement} \pdffile_embed_file:nnn{example-input-file.tex}{}{tag/AFtest} + \group_end: \tagstructbegin{tag=P,AF=tag/AFtest} \end{lstlisting} @@ -1311,6 +1369,12 @@ The key-val list understands the following keys: a concept new in PDF 2.0, but the code currently doesn't check the pdf version, it is your responsability to set it (this can be done with the \texttt{pdfversion} key in \verb+\DeclareDocumentMetadata+). + \item[\PrintKeyName{root-AF}] + This key allows to reference an associated file in the root structure element. Using the root + can be e.g. useful to add a css-file. When converting the pdf to a html with e.g. ngpdf this css-file is then + referenced in the head of the html. + + \item[\PrintKeyName{AFinline}] This key allows to embed an associated file with inline content. The value is some text, which is embedded in the PDF as a text file with mime type text/plain. @@ -1586,10 +1650,10 @@ syntax |section/H1| should in most cases do the right thing. \item[\PrintKeyName{tag}] This is the name of the new type as it should then be used in \cs{tagstructbegin}. \item[\PrintKeyName{namespace}] This is the namespace of the new type. The value should be a shorthand of a namespace. The allowed values are currently |pdf|, |pdf2|, |mathml| and |user|. The default value (and recommended value for a new tag) is |user|. The public name of the user namespace is |tag/NS/user|. This can be used to reference the namespace e.g. in attributes. -\item[\PrintKeyName{role}] This is type the tag should be mapped too. In a PDF 1.7 or earlier this is normally a type from the |pdf| set, in PDF 2.0 from the |pdf|, |pdf2| and |mathml| set. It can also be a user type, or a still unknown type. The PDF format allows mapping to be done transitively. But you should be aware that tagpdf can't (or more precisely won't) check such unusual role mapping. It lies in the responsability of the author to ensure here that every type is correctly role mapped. +\item[\PrintKeyName{role}] This is the type the tag should be mapped too. In a PDF 1.7 or earlier this is normally a type from the |pdf| set, in PDF 2.0 from the |pdf|, |pdf2| and |mathml| set. It can also be a user type, or a still unknown type. The PDF format allows mapping to be done transitively. But you should be aware that tagpdf can't (or more precisely won't) check such unusual role mapping. It lies in the responsability of the author to ensure here that every type is correctly role mapped. \item[\PrintKeyName{role-namespace}] If the role is a known type the default value is the default namespace: |pdf2| for all types in this set, |pdf| for the type which exist only in PDF 1.7, |mathml| for the MathML types, and for previously defined user types whatever namespace has been set there. If the role is unknown, |user| is used and the code hopes that the type will be defined later. \item[unknown key] An unknown key is interpreted as a |tag/role|, this preserves the old syntax. So this two calls are equivalent: - + \begin{lstlisting} \tagpdfsetup{add-new-tag = section/H1} \tagpdfsetup{add-new-tag = {tag=section,role=H1}} @@ -1623,6 +1687,43 @@ The key \PrintKeyName{show-spaces} will show lines at the places where in lua mo This is in pdftex a primitive. It inserts the dummy space glyph. \pkg{tagpdf} defines this command also for luatex -- attention if can perhaps insert break points. +\section{Structure destinations}\label{sec:struct-dest} + + Standard destinations (anchors for internal links) + consist of a reference to a page in the pdf and instructions + how to display it---typically they will put a specific coordinate in the left top corner + of the viewer and so give the impression that a link jumped to the word in this place. + But in reality they are not connected to the content. + + Starting with pdf~2.0 destinations can in a tagged PDF also point + to a structure (to a \texttt{/StructElem} object). + GoTo links can then additionally to the \texttt{/D} key which points to a + standard page destination also point to such a structure destination with an \texttt{/SD} key. + Programs that e.g. convert such a PDF to html can then create better links. + (According to the reference, PDF-viewer should prefer the structure destination + over the page destination, but as far as it is known this isn't done yet.) + + Currently structure destinations (and GoTo links making use of it) could natively only + be created with the dvipdfmx backend. With pdftex and lualatex it was only possible to create + a restricted type which used only the \enquote{Fit} mode. Starting with + \TeX{}live 2022 (earlier in miktex) both engines will knew new keywords which allow + to create structure destination easily. + + Support for this has been already added to the pdfmanagement and \pkg{tagpdf} will make + use of it if possible. In most cases it should simply work, but one should be aware + that as one now has a destination that is actually tied to the content it gets more + important to actually consider the context and the place where such destinations + are created. It now makes a difference if the destination is created before the + structure is opened or after so in some cases + code that place destinations should be changed to place them inside the structure they + belong too. . + One also has to consider the pages connected to the destinations: The structure destination + is bound to the page where the structure \emph{begins}, if this differ from the page of the page destination + (e.g. if the destination is created by a \verb+\phantomsection+ in the middle of a longer paragraph) + then be necessary to surround + destinations with a dummy structure (a Span or an Artifact) to + get the right page number. + \section{Accessibility is not only tagging} diff --git a/macros/latex/contrib/tagpdf/tagpdfdocu-patches.sty b/macros/latex/contrib/tagpdf/tagpdfdocu-patches.sty index 6ba1ee8d3f..3c283a8a3e 100644 --- a/macros/latex/contrib/tagpdf/tagpdfdocu-patches.sty +++ b/macros/latex/contrib/tagpdf/tagpdfdocu-patches.sty @@ -1,55 +1,7 @@ %\RequirePackage[enable-debug]{expl3}[2018/06/14] -\ProvidesExplPackage {tagpdfdocu-patches} {2021-08-27} {0.92} +\ProvidesExplPackage {tagpdfdocu-patches} {2022-01-13} {0.93} {patches/commands for the tagpdf documentation} \RequirePackage{etoolbox} -%%%% -% header and footer (now needed as attributes are global again) -%%%% -%% patching \@oddfoot/\@oddhead is nonsense, that is redefined all the time. -%% Using the scrlayer interfaces would probably work -%% but we will need a core latex solution anyway -%% so let's test it here and patch \@outputpage -%% we also disable paratagging, not for the tagging but to avoid that the small -%% numbers gives overfull vbox messages ... -\bool_new:N \g__tag_docu_saved_in_mc_bool -\patchcmd\@outputpage - {\hb@xt@\textwidth{\@thehead}} - { - \hb@xt@\textwidth - { - \bool_set_false:N \l__tag_para_bool - \bool_gset_eq:NN \g__tag_docu_saved_in_mc_bool \g__tag_in_mc_bool - \bool_gset_false:N \g__tag_in_mc_bool - \hfil - \tag_mc_begin:n {artifact=pagination} - \tag_stop_group_begin: - \@thehead - \tag_stop_group_end: - \tag_mc_end: - \bool_gset_eq:NN \g__tag_in_mc_bool\g__tag_docu_saved_in_mc_bool - \hfil - } - } - {}{\fail} -\patchcmd\@outputpage - {\hb@xt@\textwidth{\@thefoot}} - { - \hb@xt@\textwidth - { - \bool_set_false:N \l__tag_para_bool - \bool_gset_eq:NN \g__tag_docu_saved_in_mc_bool \g__tag_in_mc_bool - \bool_gset_false:N \g__tag_in_mc_bool - \hfil - \tag_mc_begin:n {artifact=pagination} - \tag_stop_group_begin: - \@thefoot - \tag_stop_group_end: - \tag_mc_end: - \bool_gset_eq:NN \g__tag_in_mc_bool\g__tag_docu_saved_in_mc_bool - \hfil - } - } - {}{\fail} %%%%% % tableofcontents |