summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/latex-lab/latex-lab-bib.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex/latex-lab/latex-lab-bib.dtx')
-rw-r--r--Master/texmf-dist/source/latex/latex-lab/latex-lab-bib.dtx406
1 files changed, 406 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/latex-lab/latex-lab-bib.dtx b/Master/texmf-dist/source/latex/latex-lab/latex-lab-bib.dtx
new file mode 100644
index 00000000000..9a5ee81720d
--- /dev/null
+++ b/Master/texmf-dist/source/latex/latex-lab/latex-lab-bib.dtx
@@ -0,0 +1,406 @@
+% \iffalse meta-comment
+%
+%% File: latex-lab-bib.dtx (C) Copyright 2023 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
+% license or (at your option) any later version. The latest version
+% of this license is in the file
+%
+% https://www.latex-project.org/lppl.txt
+%
+%
+% The development version of the bundle can be found below
+%
+% https://github.com/latex3/latex2e/required/latex-lab
+%
+% for those people who are interested or want to report an issue.
+%
+%<*driver>
+\documentclass{l3doc}
+\EnableCrossrefs
+\CodelineIndex
+\begin{document}
+ \DocInput{latex-lab-bib.dtx}
+\end{document}
+%</driver>
+%
+% \fi
+%
+% \title{The \textsf{latex-lab-bib} package\\
+% Changes and additions to the kernel related to tagging and links in citations and
+% bibliography entries}
+% \author{\LaTeX{} Project\thanks{Initial implementation done by Ulrike Fischer}}
+% \date{Version 0.81 2023-06-07}
+%
+% \maketitle
+%
+% \newcommand{\xt}[1]{\textsl{\textsf{#1}}}
+% \newcommand{\TODO}[1]{\textbf{[TODO:} #1\textbf{]}}
+% \newcommand{\docclass}{document class \marginpar{\raggedright document class
+% customizations}}
+%
+% \providecommand\hook[1]{\texttt{#1}}
+%
+% \begin{abstract}
+% \end{abstract}
+%
+% \section{Introduction}
+%
+% The followings contains small changes to improve tagging of
+% bibliography entries and citations.
+%
+% The tagging of the standard bibliography is actually quite straightforward:
+% A bibliography is typically a list with a heading and the code which tags sectioning
+% commands and lists handles that.
+%
+% There are here only two problems:
+%
+% \begin{itemize}
+% \item The structure number of the \texttt{LI} element
+% created by a \cs{bibitem} must be recorded somehow to allow to reference it in
+% a \cs{cite}.
+% \item \pkg{hyperref} redefines the item command and so breaks the list structure
+% see \url{https://github.com/latex3/latex2e/discussions/1010#discussioncomment-5565418}
+% \end{itemize}
+%
+% Both problems are rather easy to resolve, but it must be checked if other packages
+% interfere again by redefining the commands.
+%
+% More difficult is the tagging of citation commands. Citations should be inside
+% a Reference structure and contain a /Ref entry pointing to the relevant
+% item in the bibliography. For simple citations like
+% \enquote{[1]} or \enquote{Doody (2023)} this is easy, but it is not obvious how
+% to handle combined citations like \enquote{Doody (2003,2018)} (or even compressed citations
+% like \enquote{[1-3]}). The current implementation follows the links: whatever hyperref would
+% link is set as the reference.
+%
+% There exist various packages which over the years tried to improve and extend
+% the bibliography commands. We discuss here three: natbib, chapterbib and biblatex.
+%
+% \begin{description}
+% \item[natbib] It is rather easy to support natbib: it has hooks for links and the tagging code
+% can follow. Only a bit coordination with hyperref is needed to avoid that hyperref
+% remove the tagging code again.
+%
+% \item[chapterbib] In standard LaTeX every bib entry has an unique label which points to the
+% (mandatory and unique) bibliography and the target created by hyperref
+% has the simple form \texttt{cite.}\meta{key}.
+% If a package that support multiple bibliographies is used (e.g. chapterbib)
+% this is no longer works: a bib entry \texttt{doody}
+% can in one chapter get the label \enquote{[1]}
+% and in the other \enquote{[5]} or even \enquote{Doo19} and naturally links
+% should jump to the relevant chapter bibliography. chapterbib solves this
+% by creating bib keys with a suffix: when reading the \texttt{.aux} files it will
+% create the keys \texttt{doody@-1} and \texttt{doody@-2} where the number is related
+% to the chapter/include, and in the document and in the document \verb+\cite{doody}+
+% will look for \texttt{doody@-1} and \texttt{doody@-2} depending on the number of the
+% current include. For some unknown reason chapterbib uses two commands
+% to handle the suffix: the command \cs{@extra@binfo} is written to the aux-files
+% and used when processing the \cs{bibcite} commands,
+% but in the document \cs{@extra@b@citeb} is used. Supporting this is
+% straightforward: one only has to take care that the tagging code uses
+% \cs{@extra@b@citeb} in the relevant places too.
+%
+% \item[biblatex] biblatex supports multiple bibliographies out-of-the-box.
+% It numbers the link target by refsection and uses then the name
+% \verb+\the\c@refsection @+\meta{key}.
+%
+% Printing a bibliography is not required, in this case you get an engine warning
+% and links jump to the begin of the document:
+% \begin{verbatim}
+% name{cite.0@doody} has been referenced but does not exist
+% \end{verbatim}
+%
+% Bibliographies can be printed more than once by refsection. To avoid duplicated
+% target, biblatex stores the names of the targets in a list and if later
+% it detects that a target name has already been used in a
+% bibliography no new target is created for this item. This means a citation
+% will normally jump to the first bibliography which shows the entry.
+%
+% The tagging code has to mimic this code. This means that it can't label every item,
+% but has to test if this anchor is already known.
+% \end{description}
+%
+%
+% \section{Implementation}
+% \begin{macrocode}
+%<*package>
+%<@@=tag>
+% \end{macrocode}
+% \begin{macrocode}
+\ProvidesExplPackage {latex-lab-testphase-bib} {2023-05-18} {0.8}
+ {Code related to the tagging of bibliography and cite command}
+% \end{macrocode}
+% We need at least the block tagging code.
+% \begin{macrocode}
+\RequirePackage{latex-lab-testphase-block-tagging}
+% \end{macrocode}
+%
+% At first we suppress the patches from hyperref. This will only work with the next
+% hyperref!
+% \begin{macrocode}
+\def\hyper@nopatch@bib{}
+% \end{macrocode}
+
+% \begin{macro}{\@extra@binfo,\@extra@b@citeb}
+% These are taken from hyperref, they are for chapterbib compability (and also
+% signal to chapterbib not to change the citation commands)
+% \begin{macrocode}
+\providecommand*\@extra@binfo{}%
+\providecommand\@extra@b@citeb{}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}{\l_@@_bib_citekey_tl}
+% We can't pass the cite key everywhere as argument so we store it:
+% \begin{macrocode}
+\tl_new:N\l_@@_bib_citekey_tl
+% \end{macrocode}
+% \end{variable}
+%
+%\subsection{Handling the bibliography}
+% \begin{macro}{\@lbibitem}
+% The item command if an optional argument is used.
+%
+% We only prepend some code.
+% \begin{macrocode}
+\AddToHookWithArguments{cmd/@lbibitem/before}
+ {
+% \end{macrocode}
+% we store the target name for the label.
+% \begin{macrocode}
+ \tl_set:Nn\l_@@_bib_citekey_tl{#2}
+ }
+% \end{macrocode}
+% The target is added at the begin of the paragraph. We give that a label as
+% it perhaps need to be removed by packages
+% \begin{macrocode}
+\AddToHookWithArguments{cmd/@lbibitem/before}[latex-lab-testphase-bib/target]
+ {
+ \AddToHookNext{para/begin}
+ {
+ \makebox[0pt][r]{\MakeLinkTarget*{cite.#2\@extra@b@citeb}\hspace{\leftmargin}}
+ }
+ }
+% \end{macrocode}
+% we make a copy to be able to reinstate the definition. This is e.g.
+% currently needed with hyperref.
+% \begin{macrocode}
+\let\@kernel@copy@lbibitem\@lbibitem
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@bibitem}
+% Similar for \cs{@bibitem}.
+% TODO: If hyperref is loaded we will get a second target from the refstepcounter,
+% but this is ignored for now.
+% \begin{macrocode}
+\AddToHookWithArguments{cmd/@bibitem/before}
+ {
+% \end{macrocode}
+% we store the target name for the label.
+% \begin{macrocode}
+ \tl_set:Nn\l_@@_bib_citekey_tl{#1}
+ }
+% \end{macrocode}
+%
+% The target is added at the begin of the paragraph. We give that a label as
+% it perhaps need to be removed by packages
+% \begin{macrocode}
+\AddToHookWithArguments{cmd/@bibitem/before}[latex-lab-testphase-bib/target]
+ {
+ \AddToHookNext{para/begin}
+ {
+ \makebox[0pt][r]{\MakeLinkTarget*{cite.#1\@extra@b@citeb}\hspace{\leftmargin}}
+ }
+ }
+% \end{macrocode}
+% \begin{macrocode}
+\let\@kernel@copy@bibitem\@bibitem
+% \end{macrocode}
+% \end{macro}
+%
+% TODO The LI-structure should set a label, we redefine the internal command locally for
+% now, but perhaps this need a recipe?
+%
+% \begin{macrocode}
+\AddToHook{env/thebibliography/begin}
+ {
+ \cs_set:Npn \__block_list_item_begin:
+ {
+ \tag_struct_begin:n
+ {
+ tag=\LItag,
+ label= cite.\l_@@_bib_citekey_tl\@extra@b@citeb
+ }
+ }
+ }
+% \end{macrocode}
+%
+% \subsection{Handling citation commands}
+% We redefine similar to hyperref the \cs{bibcite} command to inject link and
+% structure. Even if it looks a bit odd it is now used for many years and so
+% hopefully compatible with various packages. But differently to hyperref we use
+% the new hooks with arguments.
+% TODO: consider hook name.
+% \begin{macrocode}
+\NewMirroredHookPairWithArguments{bibcite/before}{bibcite/after}{2}
+\def\bibcite#1#2{%
+ \@newl@bel{b}{#1\@extra@binfo}{%
+ \UseHookWithArguments{bibcite/before}{2}{#1}{#2}
+ #2
+ \UseHookWithArguments{bibcite/after}{2}{#1}{#2}
+ }%
+ }%
+\let\@kernel@copy@bibcite\bibcite
+% \end{macrocode}
+% Now we add the tagging structure.
+% TODO: with the next tagpdf version it should no longer be
+% needed to exand the ref key.
+% \begin{macrocode}
+\AddToHookWithArguments{bibcite/before}
+ {
+ \tag_mc_end_push:
+ \exp_args:Nx\tagstructbegin{tag=Reference,ref=cite.#1\@extra@b@citeb}
+ \tagmcbegin{}
+ }
+\AddToHookWithArguments{bibcite/after}[tag]
+ {
+ \tag_mc_end:
+ \tagstructend
+ \tag_mc_begin_pop:n{}
+ }
+% \end{macrocode}
+% At last the code for hyperref, the link will be inside the reference, but
+% this can be changed with a rule.
+% \begin{macrocode}
+\AddToHook{package/hyperref/after}
+ {
+ \AddToHookWithArguments{bibcite/before}
+ {
+ \hyper@linkstart{cite}{cite.#1\@extra@b@citeb}
+ }
+ \AddToHookWithArguments{bibcite/after}{\hyper@linkend}
+ }
+% \end{macrocode}
+%
+% \subsection{Natbib and biblatex support}
+% When hyperref is loaded, both natbib and biblatex use \cs{hyper@natlinkstart}
+% and \cs{hyper@natlinkend} to handle the links. We can use the generic hooks to
+% add the tagging code (and the link code from hyperref).
+% We need in part different code for both systems:
+% with biblatex we have to take care that only the first
+% structure sets a label, and if
+% hyperref is not loaded (or deactived) we will need additional code
+% but this currently doesn't exist.
+% We assume that no document loads both package -- that will probably break.
+% \begin{macrocode}
+\newcommand\hyper@natlinkstart[1]{}
+\newcommand\hyper@natlinkend{}
+% \end{macrocode}
+% With natbib we need to change the hooks to avoid duplicated target as it sets
+% the anchor too. We can not simply empty \cs{hyper@natanchorstart} as that is
+% used by biblatex.
+% \begin{macrocode}
+\AddToHook{package/natbib/after}
+ {
+ \RemoveFromHook{cmd/@bibitem/before} [latex-lab-testphase-bib/target]
+ \RemoveFromHook{cmd/@lbibitem/before}[latex-lab-testphase-bib/target]
+ }
+% \end{macrocode}
+% This can be shared by both packages: it will work with natbib with and without hyperref.
+% With biblatex it will work without hyperref as long as \cs{@extra@b@citeb} is empty
+% \begin{macrocode}
+\AddToHookWithArguments{cmd/hyper@natlinkstart/before}
+ {
+ \leavevmode
+ \tag_mc_end_push:
+ \exp_args:Nx\tag_struct_begin:n{tag=Reference,ref=cite.#1\@extra@b@citeb}
+ \tag_mc_begin:n{}
+ }
+\AddToHook{cmd/hyper@natlinkend/after}
+ {
+ \tag_mc_end:
+ \tag_struct_end:
+ \tag_mc_begin_pop:n{}
+ }
+
+% \end{macrocode}
+% if hyperref is loaded we have to revert its definition of the natbib hooks
+% and add its code through the generic hooks.
+% TODO: allow to suppress the natbib code in hyperref.
+%
+% \begin{macrocode}
+\AddToHook{package/hyperref/after}
+ {
+ \renewcommand\hyper@natlinkstart[1]{}
+ \renewcommand\hyper@natlinkend{}
+ \AddToHookWithArguments{cmd/hyper@natlinkstart/before}
+ {
+ \Hy@backout{#1}%
+% \end{macrocode}
+% natbib passes the \cs{@extra@b@citeb} in the argument, and biblatex
+% the refsection, so we only need to add the prefix \texttt{cite.}.
+% \begin{macrocode}
+ \hyper@linkstart{cite}{cite.#1}%
+ \def\hyper@nat@current{#1}
+ }
+ \AddToHook{cmd/hyper@natlinkend/after}
+ {
+ \hyper@linkend
+ }
+ }
+
+% \end{macrocode}
+% and now special biblatex code. The list item code has to test if the
+% anchor is already known:
+% \begin{macrocode}
+\AddToHook{cmd/blx@bibinit/after}
+ {
+ \cs_set:Npn \__block_list_item_begin:
+ {
+ \xifinlist{\the\c@refsection @\abx@field@entrykey}{\blx@anchors}
+ {
+ \tag_struct_begin:n
+ {
+ tag=\LItag,
+ }
+ }
+ {
+ \tag_struct_begin:n
+ {
+ tag=\LItag,
+ label= cite.\the\c@refsection @\abx@field@entrykey
+ }
+ }
+ }
+ }
+% \end{macrocode}
+% biblatex without hyperref is currently not supported but we at least avoid that it
+% errors:
+% \begin{macrocode}
+\AddToHook{package/biblatex/after}
+ {
+ \appto\blx@mknohyperref
+ {
+ \let\blx@anchors\@empty
+ \protected\def\blx@anchor{%
+ \xifinlist{\the\c@refsection @\abx@field@entrykey}{\blx@anchors}
+ {}
+ {\listxadd\blx@anchors{\the\c@refsection @\abx@field@entrykey}}}%
+ }
+ }
+% \end{macrocode}
+% \begin{macrocode}
+%</package>
+% \end{macrocode}
+% \begin{macrocode}
+%<*latex-lab>
+\ProvidesFile{bib-latex-lab-testphase.ltx}
+ [2023-05-18 v0.8 code related to the tagging of bib and citations]
+
+\RequirePackage{latex-lab-testphase-bib}
+
+%</latex-lab>
+% \end{macrocode}