% \iffalse meta-comment
%
% File: postnotes.dtx
%
% This file is part of the LaTeX package "postnotes".
%
% Copyright (C) 2022-2023  gusbrs
%
% 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
%
% and version 1.3 or later is part of all distributions of LaTeX
% version 2005/12/01 or later.
%
%
% This work is "maintained" (as per LPPL maintenance status) by gusbrs.
%
% This work consists of the files postnotes.dtx,
%                                 postnotes.ins,
%                                 postnotes-doc.tex,
%                                 postnotes-code.tex,
%                   and the files generated from them.
%
% The released version of this package is available from CTAN.
%
% -----------------------------------------------------------------------
%
% The development version of the package can be found at
%
%    https://github.com/gusbrs/postnotes
%
% for those people who are interested.
%
% -----------------------------------------------------------------------
%
% \fi
%
% \iffalse
%<*driver>
\documentclass{l3doc}

% Have \GetFileInfo pick up date and version data and used in the
% documentation.
\usepackage{postnotes}

\begin{document}

\DocInput{postnotes.dtx}

\end{document}
%</driver>
%
% \fi
%
% \DoNotIndex{\\}
%
% \NewDocumentCommand\githubissue{m}{^^A
%   issue~\href{https://github.com/gusbrs/postnotes/issues/#1}{\##1}}
%
% \NewDocumentCommand\githubPR{m}{^^A
%   PR~\href{https://github.com/gusbrs/postnotes/pull/#1}{\##1}}
%
% \NewDocumentCommand\contributor{m}{#1}
% \NewDocumentCommand\username{m}{`\texttt{#1}'}
%
% \NewDocumentCommand\opt{m}{\texttt{#1}}
%
% \pdfstringdefDisableCommands{^^A
%   \def\opt#1{#1}
% }
%
% \AddToHook{env/macro/after}{\medskip{}}
% \AddToHook{env/variable/after}{\medskip{}}
% \AddToHook{env/function/after}{\medskip{}}
%
%
% ^^A Have the Index at 'section' level rather than 'part'.  Otherwise it is
% ^^A just the same definition from 'l3doc.cls'.
% \IndexPrologue{^^A
%   \section*{Index}
%   \markboth{Index}{Index}
%   \addcontentsline{toc}{section}{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.^^A
% }
%
%
% \GetFileInfo{postnotes.sty}
%
% \title{^^A
%   The \pkg{postnotes} package^^A
%   \texorpdfstring{\\{}\medskip{}}{ - }^^A
%   Code documentation^^A
%   \texorpdfstring{\medskip{}}{}^^A
% }
%
% \author{^^A
%   \texorpdfstring{\texttt{gusbrs}\\[0.8em]
%   \url{https://github.com/gusbrs/postnotes}\\
%   \url{https://www.ctan.org/pkg/postnotes}}{gusbrs}}
%
% \date{Version \fileversion\ -- \filedate}
%
% \maketitle
%
%
% \tableofcontents
%
%
% \clearpage{}
%
% \section{Initial setup}
% Start the \pkg{DocStrip} guards.
%    \begin{macrocode}
%<*package>
%    \end{macrocode}
%
% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention).
%    \begin{macrocode}
%<@@=postnotes>
%    \end{macrocode}
%
%
% The new syntax for file/package hooks, which the package assumes, requires
% kernel 2021-11-15 (\texttt{ltnews34}, \texttt{ltfilehook}).  Furthermore,
% the kernel of 2022-06-01 introduced a couple of very nice features which
% simplifies the relation with \pkg{hyperref} (\texttt{ltnews35},
% \texttt{hyperref-linktarget}): the provision of \cs{MakeLinkTarget} and the
% definition by the kernel of the starred version of \cs{ref}, which we can
% use regardless of \pkg{hyperref} being loaded.  Finally, since we followed
% the move to \texttt{e}-type expansion, to play safe we require the
% 2023-11-01 kernel or newer.
%
%    \begin{macrocode}
\def\postnotes@required@kernel{2023-11-01}
\NeedsTeXFormat{LaTeX2e}[\postnotes@required@kernel]
\providecommand\IfFormatAtLeastTF{\@ifl@t@r\fmtversion}
\IfFormatAtLeastTF{\postnotes@required@kernel}
  {}
  {%
    \PackageError{postnotes}{LaTeX kernel too old}
      {%
        'postnotes' requires a LaTeX kernel \postnotes@required@kernel\space or newer.%
      }%
  }%
%    \end{macrocode}
%
%
%    \begin{macrocode}
\ProvidesExplPackage {postnotes} {2023-12-12} {0.2.8}
  {Endnotes for LaTeX}
%    \end{macrocode}
%
%
% \begin{macro}
%   {
%      \l_@@_tmpa_tl ,
%      \l_@@_tmpb_tl ,
%      \l_@@_tmpa_seq ,
%      \l_@@_tmpa_box ,
%   }
%   Temporary scratch variables.
%    \begin{macrocode}
\tl_new:N \l_@@_tmpa_tl
\tl_new:N \l_@@_tmpb_tl
\seq_new:N \l_@@_tmpa_seq
\box_new:N \l_@@_tmpa_box
%    \end{macrocode}
% \end{macro}
%
%
% \section{Data}
%
%
% \begin{macro}[EXP]{\@@_data_name:n}
%   Returns the name of the property list variable which stores the data of
%   the \cs{postnote} with \meta{note id} number.
%     \begin{syntax}
%       \cs{@@_data_name:n} \Arg{note id}
%     \end{syntax}
%    \begin{macrocode}
\cs_new:Npn \@@_data_name:n #1
  { g_@@_ #1 _data_prop }
\cs_generate_variant:Nn \@@_data_name:n { e }
%    \end{macrocode}
% \end{macro}
%
%
% \pkg{postnotes} provides a number of hooks from the new hook system to grant
% some points of access in key places of the package.  Note that hooks created
% with \cs{NewHook} are meant to be public interfaces (see
% \url{https://chat.stackexchange.com/transcript/message/62955941#62955941},
% and following discussion).
%
%
% \begin{macro}{\@@_store:nn}
%   Stores the metadata and \meta{note content} of \cs{postnote} with ID
%   \meta{note id}, from where it is called.  The
%   \texttt{postnotes/note/store} hook is intended to add further data to the
%   note, when required to support packages with specific needs.
%     \begin{syntax}
%       \cs{@@_store:nn} \Arg{note id} \Arg{note content}
%     \end{syntax}
%    \begin{macrocode}
\NewHook { postnotes/note/store }
\cs_new_protected:Npn \@@_store:nn #1#2
  {
    \prop_new:c { \@@_data_name:e {#1} }
    \prop_gput:cnn { \@@_data_name:e {#1} } { type } { note }
    \prop_gput:cne { \@@_data_name:e {#1} } { mark }
      { \l_@@_mark_tl }
    \prop_gput:cne { \@@_data_name:e {#1} } { counter }
      { \int_use:N \c@postnote }
    \prop_gput:cne { \@@_data_name:e {#1} } { sortnum }
      {
        \bool_if:NTF \l_@@_manual_sortnum_bool
          { \fp_use:N \l_@@_sort_num_fp }
          { \int_use:N \c@postnote }
      }
    \cs_if_exist:cT { chapter }
      {
        \prop_gput:cne { \@@_data_name:e {#1} }
          { thechapter } { \thechapter }
      }
    \prop_gput:cne { \@@_data_name:e {#1} } { thesection }
      { \thesection }
    \prop_gput:cne { \@@_data_name:e {#1} } { pnsectname }
      { \g_@@_section_name_tl }
    \prop_gput:cne { \@@_data_name:e {#1} } { pnsectid }
      { \int_use:N \g_@@_sectid_int }
    \prop_gput:cne { \@@_data_name:e {#1} } { multibool }
      { \bool_to_str:N \l_@@_maybe_multi_bool }
    \prop_gput:cnn { \@@_data_name:e {#1} } { content } {#2}
    \UseHook { postnotes/note/store }
  }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\@@_store_section:nn}
%   Stores the metadata and \meta{note content} of \cs{postnotesection} with
%   ID \meta{note id}, from where it is called.
%     \begin{syntax}
%       \cs{@@_store_section:nn} \Arg{note id} \Arg{note content}
%     \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_store_section:nn #1#2
  {
    \prop_new:c { \@@_data_name:e {#1} }
    \prop_gput:cnn { \@@_data_name:e {#1} } { type } { section }
    \cs_if_exist:cT { chapter }
      {
        \prop_gput:cne { \@@_data_name:e {#1} }
          { thechapter } { \thechapter }
      }
    \prop_gput:cne { \@@_data_name:e {#1} } { thesection }
      { \thesection }
    \prop_gput:cnn { \@@_data_name:e {#1} } { content } {#2}
  }
\cs_generate_variant:Nn \@@_store_section:nn { ne }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}
%   {
%     \@@_prop_get:nnN ,
%     \@@_prop_item:nn ,
%     \@@_prop_gclear:n ,
%   }
%   Convenience functions to retrieve and clear data from a note based on the
%   ID number.
%     \begin{syntax}
%       \cs{@@_prop_get:nnN} \Arg{note id} \Arg{property} \Arg{tl var to set}
%       \cs{@@_prop_item:nn} \Arg{note id} \Arg{property}
%       \cs{@@_prop_gclear:n} \Arg{note id}
%     \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_prop_get:nnN #1#2#3
  {
    \prop_get:cnNF { \@@_data_name:e {#1} } {#2} #3
      { \tl_clear:N #3 }
  }
\cs_new:Npn \@@_prop_item:nn #1#2
  { \prop_item:cn { \@@_data_name:e {#1} } {#2} }
\cs_new_protected:Npn \@@_prop_gclear:n #1
  { \prop_gclear:c { \@@_data_name:e {#1} } }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}[int]{\post@note}
%   The \cs{newlabel} equivalent for \pkg{postnotes}.  Based on the kernel's
%   \cs{@newl@bel} so that we get \LaTeX{} checks for multiple and changed
%   references for free (procedure learnt from \pkg{zref}).  \cs{post@note},
%   when the \file{.aux} file is read, defines macros named
%   \texttt{\textbackslash{}postnote@r@\meta{label name}}, according to the
%   prefix set by \cs{c_@@_ref_prefix_tl}.
%     \begin{syntax}
%       \cs{post@note} \Arg{label name} \Arg{label content}
%     \end{syntax}
%    \begin{macrocode}
\tl_const:Nn \c_@@_ref_prefix_tl { postnote@r }
\cs_new_protected:Npe \post@note #1#2
  { \exp_not:N \@newl@bel { \c_@@_ref_prefix_tl } {#1} {#2} }
%    \end{macrocode}
% \end{macro}
%
% And ensure \cs{post@note} is defined in the \file{.aux} file.  The hooks are
% the same used by \pkg{hyperref} for similar purpose.
%
%    \begin{macrocode}
\AddToHook { begindocument }
  {
    \legacy_if:nT { @filesw }
      {
        \iow_now:Ne \@mainaux
          { \token_to_str:N \providecommand \token_to_str:N \post@note [2]{} }
      }
  }
\AddToHook { include/before }
  {
    \legacy_if:nT { @filesw }
      {
        \iow_now:Ne \@partaux
          { \token_to_str:N \providecommand \token_to_str:N \post@note [2]{} }
      }
  }
%    \end{macrocode}
%
%
% \begin{macro}
%   {
%     \@@_set_label:nn ,
%     \@@_set_mark_page_label:n ,
%     \@@_set_text_page_label:n ,
%     \@@_set_print_page_label:n ,
%   }
%   Label setting functions for each pertinent context.  They must use
%   \cs{iow_shipout_x:Nn}, since the main information we are interested in is
%   the \texttt{page}.
%     \begin{syntax}
%       \cs{@@_set_label:nn} \Arg{label name} \Arg{value}
%       \cs{@@_set_mark_page_label:n} \Arg{note id}
%       \cs{@@_set_text_page_label:n} \Arg{note id}
%       \cs{@@_set_print_page_label:n} \Arg{note id}
%     \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_set_label:nn #1#2
  {
    \legacy_if:nT { @filesw }
      {
        \iow_shipout_x:Nn \@auxout
          { \token_to_str:N \post@note { #1 } { #2 } }
      }
  }
\cs_new_protected:Npn \@@_set_mark_page_label:n #1
  { \@@_set_label:nn { mark@ #1 } { \thepage } }
\cs_generate_variant:Nn \@@_set_mark_page_label:n { e }
\cs_new_protected:Npn \@@_set_text_page_label:n #1
  { \@@_set_label:nn { text@ #1 } { \int_use:N \c@page } }
\cs_generate_variant:Nn \@@_set_text_page_label:n { e }
\cs_new_protected:Npn \@@_set_print_page_label:n #1
  { \@@_set_label:nn { print@ #1 } { \int_use:N \c@page } }
\cs_generate_variant:Nn \@@_set_print_page_label:n { e }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}
%   {
%     \@@_get_pageref:Nn ,
%     \@@_extract_pageref:n ,
%   }
%   Reference data extraction functions.
%     \begin{syntax}
%       \cs{@@_get_pageref:Nn} \Arg{tl var to set} \Arg{label name}
%       \cs{@@_extract_pageref:n} \Arg{label name}
%     \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_get_pageref:Nn #1#2
  {
    \cs_if_exist:cTF { \c_@@_ref_prefix_tl @ #2 }
      { \tl_set:Nv #1 { \c_@@_ref_prefix_tl @ #2 } }
      { \tl_clear:N #1 }
  }
\cs_generate_variant:Nn \@@_get_pageref:Nn { Ne }
\cs_new:Npn \@@_extract_pageref:n #1
  {
    \cs_if_exist:cTF { \c_@@_ref_prefix_tl @ #1 }
      { \exp_not:v { \c_@@_ref_prefix_tl @ #1 } }
      { \c_empty_tl }
  }
\cs_generate_variant:Nn \@@_extract_pageref:n { e }
%    \end{macrocode}
% \end{macro}
%
%
% \section{Options}
%
% \subsection*{\opt{heading} option}
%
%    \begin{macrocode}
\keys_define:nn { postnotes/setup }
  {
    heading .cs_set_protected:Np = \pnheading ,
    heading .value_required:n = true ,
  }
%    \end{macrocode}
%
% \begin{macro}[int]{\pnheading}
%   Provide default value for \cs{pnheading}.
%    \begin{macrocode}
\cs_if_exist:cTF { chapter }
  {
    \cs_new_protected:Npn \pnheading
      {
        \chapter*{\pntitle}
        \@mkboth{\pnheaderdefault}{\pnheaderdefault}
      }
  }
  {
    \cs_new_protected:Npn \pnheading
      {
        \section*{\pntitle}
        \@mkboth{\pnheaderdefault}{\pnheaderdefault}
      }
  }
%    \end{macrocode}
% \end{macro}
%
%
% \subsection*{\opt{format} option}
%
%    \begin{macrocode}
\tl_new:N \l_@@_print_format_tl
\keys_define:nn { postnotes/setup }
  {
    format .tl_set:N = \l_@@_print_format_tl ,
    format .initial:n = { \small } ,
    format .value_required:n = true ,
  }
%    \end{macrocode}
%
%
% \subsection*{\opt{listenv} option}
%
%    \begin{macrocode}
\tl_new:N \l_@@_print_env_tl
\bool_new:N \l_@@_print_as_list_bool
\keys_define:nn { postnotes/setup }
  {
    listenv .code:n =
      {
        \tl_if_eq:nnTF {#1} { none }
          {
            \bool_set_false:N \l_@@_print_as_list_bool
            \tl_set:Nn \l_@@_post_printnote_tl { \par }
%    \end{macrocode}
% A sensible default just in case.  It should not get to be used though.
%    \begin{macrocode}
            \tl_set:Nn \l_@@_print_env_tl { itemize }
          }
          {
            \bool_set_true:N \l_@@_print_as_list_bool
            \tl_set:Nn \l_@@_print_env_tl {#1}
          }
      } ,
    listenv .initial:n = { postnoteslist } ,
    listenv .value_required:n = true ,
  }
%    \end{macrocode}
%
%
% A couple of built-in list environments provided for convenience, and
% \texttt{postnoteslist} as default.  The horizontal setup of the label in
% these lists is based on the \texttt{description} environment of the standard
% classes (see the \emph{The \LaTeX{} Companion}).
%
%    \begin{macrocode}
\NewDocumentEnvironment { postnoteslist } { }
  {
    \list { }
      {
        \setlength { \leftmargin }    { 0pt }
        \setlength { \labelwidth }    { 0pt }
        \setlength { \itemindent }    { .5\parindent }
        \cs_set_eq:NN \makelabel \@@_list_makelabel:n
        \setlength { \rightmargin }   { 0pt }
        \setlength { \listparindent } { \parindent }
        \setlength { \parsep }    { \parskip }
        \setlength { \itemsep }   { 0pt }
        \setlength { \topsep }    { .5\topsep }
        \setlength { \partopsep } { .5\partopsep }
      }
  }
  { \endlist }
\NewDocumentEnvironment { postnoteslisthang } { }
  {
    \list { }
      {
        \setlength { \leftmargin }    { 1em }
        \setlength { \labelwidth }    { -\leftmargin }
        \setlength { \itemindent }    { -2\leftmargin }
        \cs_set_eq:NN \makelabel \@@_list_makelabel:n
        \setlength { \rightmargin }   { 0pt }
        \setlength { \listparindent } { \parindent }
        \setlength { \parsep }    { \parskip }
        \setlength { \itemsep }   { 0pt }
        \setlength { \topsep }    { .5\topsep }
        \setlength { \partopsep } { .5\partopsep }
      }
  }
  { \endlist }
\cs_new:Npn \@@_list_makelabel:n #1
  { \hspace { \labelsep } \normalfont ~ #1 }
%    \end{macrocode}
%
%
% \subsection*{\opt{makemark} and \opt{maketextmark} options}
%
% The arguments are: \texttt{\#1} is the mark, \texttt{\#2} and \texttt{\#3}
% are, respectively, the start and the end of the backlink.
%
%    \begin{macrocode}
\keys_define:nn { postnotes/setup }
  {
    makemark .cs_set:Np = \@@_make_mark:nnn #1#2#3 ,
    makemark .value_required:n = true ,
%    \end{macrocode}
% From the default kernel definition of \cs{@makefnmark}.
%    \begin{macrocode}
    makemark .initial:n =
      { #2 \hbox { \@textsuperscript { \normalfont #1 } } #3 } ,
    maketextmark .cs_set:Np = \@@_make_text_mark:nnn #1#2#3  ,
    maketextmark .value_required:n = true ,
    maketextmark .initial:n = { #2 #1 . #3 } ,
  }
%    \end{macrocode}
%
%
% \subsection*{\opt{pretextmark}, \opt{posttextmark}, \opt{postprintnote} options}
%
%    \begin{macrocode}
\tl_new:N \l_@@_pre_textmark_tl
\tl_new:N \l_@@_post_textmark_tl
\tl_new:N \l_@@_post_printnote_tl
\keys_define:nn { postnotes/setup }
  {
    pretextmark .tl_set:N = \l_@@_pre_textmark_tl ,
    pretextmark .value_required:n = true ,
    posttextmark .tl_set:N = \l_@@_post_textmark_tl ,
    posttextmark .value_required:n = true ,
    postprintnote .tl_set:N = \l_@@_post_printnote_tl ,
    postprintnote .value_required:n = true ,
  }
%    \end{macrocode}
%
%
% \subsection*{\opt{hyperref} and \opt{backlink} options}
%
%    \begin{macrocode}
\bool_new:N \l_@@_hyperlink_bool
\bool_new:N \l_@@_hyperref_warn_bool
\bool_new:N \l_@@_backlink_bool
\keys_define:nn { postnotes/setup }
  {
    hyperref .choice: ,
    hyperref / auto .code:n =
      {
        \bool_set_true:N \l_@@_hyperlink_bool
        \bool_set_false:N \l_@@_hyperref_warn_bool
      } ,
    hyperref / true .code:n =
      {
        \bool_set_true:N \l_@@_hyperlink_bool
        \bool_set_true:N \l_@@_hyperref_warn_bool
      } ,
    hyperref / false .code:n =
      {
        \bool_set_false:N \l_@@_hyperlink_bool
        \bool_set_false:N \l_@@_hyperref_warn_bool
      } ,
    hyperref .initial:n = auto ,
    hyperref .default:n = true ,
    backlink .bool_set:N = \l_@@_backlink_bool ,
    backlink .initial:n = true ,
    backlink .default:n = true ,
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\AddToHook { begindocument }
  {
    \IfPackageLoadedTF { hyperref }
      { }
      {
        \bool_if:NT \l_@@_hyperref_warn_bool
          { \msg_warning:nn { postnotes } { missing-hyperref } }
        \bool_set_false:N \l_@@_hyperlink_bool
      }
    \keys_define:nn { postnotes/setup }
      {
        hyperref .code:n =
          {
            \msg_warning:nnn { postnotes }
              { option-preamble-only } { hyperref }
          } ,
        backlink .code:n =
          {
            \msg_warning:nnn { postnotes }
              { option-preamble-only } { backlink }
          } ,
      }
  }
\msg_new:nnn { postnotes } { option-preamble-only }
  { Option~'#1'~only~available~in~the~preamble~\msg_line_context:. }
\msg_new:nnn { postnotes } { missing-hyperref }
  { Missing~'hyperref'~package.~Setting~'hyperref=false'. }
%    \end{macrocode}
%
%
% \subsection*{\opt{sort} option}
%
%    \begin{macrocode}
\bool_new:N \l_@@_sort_bool
\keys_define:nn { postnotes/setup }
  {
    sort .bool_set:N = \l_@@_sort_bool ,
    sort .initial:n = true ,
    sort .default:n = true ,
  }
%    \end{macrocode}
%
%
% \subsection*{\opt{style} option}
%
%    \begin{macrocode}
\keys_define:nn { postnotes/setup }
  {
    style .choice: ,
    style / endnotes .meta:n =
      {
        listenv = none ,
        format =
          {
            \footnotesize
            \setlength { \rightskip } { 0pt   }
            \setlength { \leftskip  } { 0pt   }
            \setlength { \parindent } { 1.8em }
          } ,
        pretextmark = { \par } ,
%    \end{macrocode}
% \pkg{endnotes} uses a zero width box to get the desired alignment to the
% right, but that does not play well with the backlinks, so we have a little
% more work to do to get this right.
%    \begin{macrocode}
        maketextmark =
         {
           \hbox_set:Nn \l_@@_tmpa_box
             { \@textsuperscript { \normalfont ##1 } }
           \skip_horizontal:n { - \box_wd:N \l_@@_tmpa_box }
           ##2 \box_use:N \l_@@_tmpa_box ##3
         } ,
      } ,
    style / pagenote .meta:n =
      {
        listenv = none ,
        format = { } ,
        pretextmark = { \par\noindent } ,
        maketextmark = { { \normalfont ##2 ##1 . ##3 } } ,
        posttextmark = { ~ } ,
      } ,
  }
%    \end{macrocode}
%
%
% \subsection*{\cs{postnotesetup}}
%
%
% \begin{macro}[int]{\postnotesetup}
%   Provide \cs{postnotesetup}.
%   \begin{syntax}
%     \cs{postnotesetup}\marg{options}
%   \end{syntax}
%    \begin{macrocode}
\NewDocumentCommand \postnotesetup { m }
  { \keys_set:nn { postnotes/setup } {#1} }
%    \end{macrocode}
% \end{macro}
%
%
% \section{\cs{postnote}}
%
% Different from the traditional \cs{footnotemark} / \cs{footnotetext} system,
% in the context of end notes, the functionality which corresponds to
% \cs{footnotetext} is simply to store the data to be typeset later.  Hence,
% some of the problems that afflict footnotes do not apply to end notes.
% Namely, and as far as I can tell, they can be used in ``inner horizontal
% mode'' (\cs{mbox} etc.), and in math mode, and if the ``text'' will be
% typeset in the same page as the ``mark'' is of little concern.
%
% However, the separation between ``mark'' and ``text'' is still useful in
% other contexts: floats and contexts where multiple typesetting passes are
% performed.  \contributor{David Carlisle} and \contributor{Ulrike Fischer}
% shared some thoughts on the matter at the TeX.SX chat:
% \url{https://chat.stackexchange.com/transcript/message/60754383#60754383}.
%
% The interesting questions here are: if they are replaceable in their roles
% in these contexts and how much would we lose by providing them.  In
% analyzing this, we have to distinguish two situations: when
% \cs{footnotemark} is called with no argument (and thus steps the counter),
% and when it is called with the optional argument (and thus refrains from
% stepping the counter).
%
% For floats, the problem they pose is that they may disturb the
% \emph{ordering} of the notes.  This particular issue can be solved by using
% \cs{footnotemark} without argument, and manually adjusting the counter on
% subsequent calls to \cs{footnotetext}.  A good example of the technique is
% \url{https://tex.stackexchange.com/a/43694}.  True, a user may wish to
% specify the mark explicitly, but doesn't necessarily need to do it to solve
% the ordering issue.
%
% Multiple typesetting passes of content are much harder.  And they abound:
% the standard classes' \cs{caption} typesets the caption once, if it is
% short, but twice if it is longer than a line; \pkg{amsmath}'s math
% environments perform a measuring pass before actually typesetting the
% equations; \pkg{amsmath}'s \cs{text} macro runs the contents through
% \cs{mathchoice} (which typesets the contents four times) when in math mode;
% \pkg{tabularx} and \pkg{tabularray} also perform measuring passes of their
% tables; so does \pkg{csquotes}' blockquotes; and certainly more that I'm
% unaware.  A number of these places offer some one or another way to mitigate
% the issue: \pkg{amsmath}, \pkg{tabularx}, \pkg{csquotes} and (optionally)
% \pkg{tabularray} restore counter values after measuring steps; \pkg{amsmath}
% offers a boolean to indicate when it is a measuring pass; \pkg{csquotes}
% offers further handles.  But the standard \cs{caption} offers none, and
% neither does \pkg{amsmath}'s \cs{text} macro.  Well, the pkg{caption}
% package can disable the multiple passes for \cs{caption} with the option
% \opt{singlelinecheck}, but it is not reasonable to require it for our
% purposes, so we must assume the worst case.
%
% Enrico Gregorio is categorical in stating that \cs{endnotemark} and
% \cs{endnotetext} are required for \pkg{enotez} to handle \cs{caption}, which
% apparently it didn't offer originally: ``The package should implement
% \cs{endnotemark} and \cs{endnotetext} for this case.  According to the
% documentation, the author deems them to not be needed: he's wrong.''
% (\url{https://tex.stackexchange.com/a/314937}).  See also
% \url{https://tex.stackexchange.com/a/43794} and
% \url{https://tex.stackexchange.com/a/358207}.
%
% In this scenario, when there's no way around the multiple passes,
% \cs{footnotemark} can only handle the general case if used with an argument,
% precisely because it inhibits the stepping of the counter.  Otherwise the
% counter is stepped multiple times, and we'd get the wrong number (and mark).
% In some circumstances, if we know the number of passes is deterministic, we
% might get away by adjusting the counter manually (\cs{caption} may be dealt
% with this way: if we know it to be two lines, we can decrement the counter
% before it and get correct results, even hyperlinked).  But in cases which
% adjusting the counter is sufficient, end notes can be dealt with in the same
% way, and doesn't need the separation between ``mark'' and ``text''.  So,
% what is distinctive of the kernel's footnote apparatus, which allows it as
% much flexibility as one would like, is receiving an arbitrary number as
% argument and not stepping the counter.  And as far as \cs{footnotemark} and
% \cs{footnotetext}) are concerned, the main point of the optional argument is
% really to ``manually establish the relation'' between the two of them.  So,
% if \emph{not stepping the counter} is what is needed to handle the general
% case, is it viable to do so? What would we loose in so doing?
%
% When receiving an arbitrary number as argument, as the kernel functionality
% for footnotes and other endnotes packages do, this value is expected to the
% printed as such, hence it must correspond to the \texttt{postnote} counter
% (in our case).  But this counter is in the hands of the user, and can be
% reset along the document, thus its uniqueness cannot be ensured.  But not
% stepping \texttt{postnote} is perfectly viable, as it just aims at storing
% how the mark is to be typeset.  However, not stepping the ID counter would
% complicate things considerably.  Not doing so implies we'd lose the
% connection we have between the ``mark'' and the corresponding ``text''.  We
% might add the ``text'' to the queue, but all the metadata would be lost,
% including the \pkg{hyperref} anchor, but really the set of data without
% which the kind of functionality offered would be nonviable, or severely
% hampered.  Not stepping \texttt{postnote} but stepping the ID counter also
% is not sufficient, because we'd get a note in duplicity.  We could naively
% think that a gap in the ID is not a problem, and just not add the duplicate
% to the queue.  But how could we tell the difference between a legitimate and
% an illegitimate step of the ID counter?
%
% I have not been able to devise a way to ``reconnect'' ``text'' and ``mark''
% in the absence of the unique ID counter.  The most promising idea was to
% have mandatory arguments to \cs{postnotemark} and \cs{postnotetext}
% receiving a \meta{label} which we could use to identify their counterparts,
% but I was not able to go through with this, and the attempts all increased
% complexity considerably.  It is not just a label/ref system, there's got to
% be a one-to-one correspondence between the sets, uniqueness has to be
% ensured on both sides, and there cannot be ``lone'' marks or texts (a
% bijection).  Besides, this label based system of identification would have
% to live side-by-side with the one based on the counter.  So, even if we'd
% have unique IDs, we wouldn't know beforehand in what form it comes.
% Considering the ID is used to build the variable name in which we store the
% note's information, this would also complicate things.
%
% Besides, there are ways to get things working with multiple passes without
% the ``mark''/``text'' partition.  As mentioned, there are a number of cases
% which offer some kind of ``handle'' or way to identify the multiple passes.
% \pkg{csquotes} has a dedicated hook that can be used.  \pkg{amsmath} sets
% the \texttt{measuring@} boolean (which \pkg{hyperref} also defines).  So,
% not all cases are as tricky as \cs{caption} or \cs{text}, and even that can
% be decently dealt with without a separation between ``mark'' and ``text''.
% Besides, in difficult cases, the package offers a \opt{nomark} option to
% \cs{postnote} to place a note, but typeset no mark.  Then we can typeset a
% mark with \cs{postnoteref} referring to a \cs{label} in the note of
% interest.  This would result in a correct mark without duplicity, and in a
% correct link from there to the note's text at \cs{printpostnotes}.  The
% drawback is that the placement of \cs{postnote} would be important, and
% results sensitive to it.  All the metadata is collected at the point of
% \cs{postnote}, anchor included, not at the point of \cs{postnoteref}.  So
% the consequences are a slightly off backlink, possibly imprecise metadata,
% etc.  Considering \pkg{hyperref} itself shies away completely from linking
% \cs{footnotemark} with an argument, I'd say there's some gain.
%
% The truth is there are some trade-offs, there's no ``ideal'' solution.
% Still, all in all, my judgment is that the unique ID counter is worth more
% than the inconveniences of an ocasional \texttt{\cs{postnote}[nomark]}
% referenced with \cs{postnoteref}, and even that should not be needed much.
% So, for the time being, until something else shakes this balance, I won't be
% offering \cs{postnotemark} and \cs{postnotetext}.
%
% \bigskip{}
%
% For the \pkg{hyperref} support for cross-references in \cs{postnote}, I've
% moved back and forth quite a lot.  One of the ideas I fancied was using
% \cs{refstepcounter} and let \pkg{hyperref} do its job.  But, since I want to
% have control of the anchor/destination name on both ``sides'', I'd have to
% set \cs{theHpostnote} locally before calling \cs{refstepcounter}, otherwise
% results might sensitive to user calls to \cs{counterwithin} (see
% \url{https://github.com/latex3/hyperref/issues/230}, thanks
% \contributor{Ulrike Fischer}).  However, even if that worked well for the
% default case, we still had to setup things manually, in case of a manually
% supplied mark.  All in all, I'm just calling \cs{stepcounter}, setting the
% relevant cross-reference variables once and setting the anchor manually.
%
%
% \bigskip{}
%
% \texttt{postnote} is the public, user facing, counter for \cs{postnote}.  It
% determines how the note's mark gets to be typeset.  It can be reset, set,
% and have its printed representation changed.  Of course, whether those are
% meaningful is up to the user.
%
%    \begin{macrocode}
\newcounter { postnote }
%    \end{macrocode}
%
% \begin{macro}
%   {
%     \g_@@_note_id_int ,
%     \l_postnotes_note_id_tl ,
%     \g_@@_queue_seq ,
%   }
%   \cs{g_@@_note_id_int} is the internal, unique counter which provides the
%   ID number of each note.  It ties ``mark'' and ``text'' together, is also
%   the connection between each note and its data, including the content,
%   which is stored in a property list named according to \cs{@@_data_name:n}
%   and the ID number.  \cs{l_postnotes_note_id_tl} is a convenience variable
%   storing the counter's value.  \cs{g_@@_queue_seq} stores the sequence of
%   notes' IDs to be processed by the next call of \cs{printpostnotes}.
%    \begin{macrocode}
\int_new:N \g_@@_note_id_int
\tl_new:N \l_postnotes_note_id_tl
\tl_set:Nn \l_postnotes_note_id_tl { \int_use:N \g_@@_note_id_int }
\seq_new:N \g_@@_queue_seq
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}[int]{\postnote}
%   Provide \cs{postnote}.
%   \begin{syntax}
%     \cs{postnote} \oarg{options} \marg{note text}
%   \end{syntax}
%    \begin{macrocode}
\NewDocumentCommand \postnote { O { } +m }
  { \@@_note:nn {#1} {#2} }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\@@_note:nn}
%   The internal version of \cs{postnote}.  The \texttt{postnotes/note/begin}
%   hook is meant to provide a place from where some additional setup for the
%   note can be performed.  This is being used for adding support for some
%   features/packages, but can also be used, for example, to add an extra
%   local property for \pkg{zref}.
%   \begin{syntax}
%     \cs{@@_note:nn}\oarg{options}\marg{note content}
%   \end{syntax}
%    \begin{macrocode}
\NewHook { postnotes/note/begin }
\cs_new_protected:Npn \@@_note:nn #1#2
  {
    \group_begin:
    \keys_set:nn { postnotes/note } {#1}
    \@@_inhibit_note:F
      {
        \int_gincr:N \g_@@_note_id_int
        \tl_if_empty:NT \l_@@_mark_tl
          {
            \stepcounter { postnote }
            \tl_set:Ne \l_@@_mark_tl { \thepostnote }
          }
        \seq_gput_right:Ne \g_@@_queue_seq
          { \l_postnotes_note_id_tl }
        \UseHook { postnotes/note/begin }
        \cs_set:Npn \@currentcounter { postnote }
        \cs_set:Npe \@currentlabel { \p@postnote \l_@@_mark_tl }
        \MakeLinkTarget* { postnote. \l_postnotes_note_id_tl .mark }
        \@@_set_mark_page_label:e { \l_postnotes_note_id_tl }
        \@@_set_user_labels:
        \bool_if:NF \l_@@_nomark_bool
          {
            \@@_typeset_mark:eV
              { \l_postnotes_note_id_tl } \l_@@_mark_tl
          }
        \@@_store:nn { \l_postnotes_note_id_tl } {#2}
      }
    \group_end:
  }
%    \end{macrocode}
% \end{macro}
%
%
% Options for \cs{postnote}.
%
%    \begin{macrocode}
\tl_new:N \l_@@_mark_tl
\bool_new:N \l_@@_nomark_bool
\fp_new:N \l_@@_sort_num_fp
\tl_new:N \l_@@_note_label_tl
\bool_new:N \l_@@_manual_sortnum_bool
\bool_new:N \l_@@_maybe_multi_bool
\keys_define:nn { postnotes/note }
  {
    markstr .tl_set:N = \l_@@_mark_tl ,
    markstr .value_required:n = true ,
    sortnum .code:n =
      {
        \fp_set:Nn \l_@@_sort_num_fp {#1}
        \bool_set_true:N \l_@@_manual_sortnum_bool
      } ,
    sortnum .value_required:n = true ,
    mark .meta:n =
      {
        markstr = {#1} ,
        sortnum = {#1} ,
      } ,
    mark .value_required:n = true ,
    nomark .bool_set:N = \l_@@_nomark_bool ,
    nomark .default:n = true ,
    label .tl_set:N = \l_@@_note_label_tl ,
    label .value_required:n = true ,
  }
%    \end{macrocode}
%
%
% \begin{macro}{\@@_inhibit_note:TF}
%   In contexts of multiple passes of content, it may be needed, or preferred,
%   to inhibit the note altogether to avoid side effects and duplicity.  This
%   conditional, obviously, will always return the true branch unless
%   something is done in the \texttt{postnotes/note/inhibit} hook.  This hook
%   is meant to handle support for packages or features which may justify note
%   inhibition, and the code there should set \cs{l_@@_inhibit_note_bool},
%   \cs{l_@@_print_plain_mark_bool} and
%   \cs{l_@@_print_plain_mark_stepcounter_bool} as appropriate to the case.
%    \begin{macrocode}
\bool_new:N \l_@@_inhibit_note_bool
\bool_new:N \l_@@_print_plain_mark_bool
\bool_new:N \l_@@_print_plain_mark_stepcounter_bool
\NewHook { postnotes/note/inhibit }
\prg_new_protected_conditional:Npnn \@@_inhibit_note: { F }
  {
    \bool_set_false:N \l_@@_inhibit_note_bool
    \bool_set_false:N \l_@@_print_plain_mark_bool
    \bool_set_false:N \l_@@_print_plain_mark_stepcounter_bool
    \UseHook { postnotes/note/inhibit }
%    \end{macrocode}
% Printing a plain mark here may be needed because, if we are inhibiting the
% note in a ``measuring context'' and omit it completely, the measuring being
% performed will be off by the size of the mark.  So, to ensure the measuring
% can be done correctly, we place the mark.  What to do with the counter
% itself, depends on the situation.  In places that are known to restore the
% counter values after the measuring pass, we can let the counter be stepped.
% And, actually we should do so, for example, in a \env{tabularx} with
% multiple postnotes, if we don't step the counter, all the measuring will be
% done with the number of the first note.  Otherwise, we don't actually step
% the counter but, to typeset correctly the mark that would be printed if the
% counter had been stepped, we increment \cs{c@postnote} locally and grouped,
% and smuggle \cs{thepostnote} out of the group.
%    \begin{macrocode}
    \bool_if:NT \l_@@_print_plain_mark_bool
      {
        \tl_if_empty:NT \l_@@_mark_tl
          {
            \bool_if:NTF \l_@@_print_plain_mark_stepcounter_bool
              {
                \stepcounter { postnote }
                \tl_set:Ne \l_@@_mark_tl { \thepostnote }
              }
              {
                \group_begin:
                \int_incr:N \c@postnote
                \exp_args:NNNe
                  \group_end:
                  \tl_set:Nn \l_@@_mark_tl { \thepostnote }
              }
          }
        \@@_typeset_mark_wrapper:n
          { \@@_make_mark:nnn { \l_@@_mark_tl } { } { } }
      }
    \bool_if:NTF \l_@@_inhibit_note_bool
      { \prg_return_true:  }
      { \prg_return_false: }
  }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}
%   {
%     \@@_typeset_mark:nn ,
%     \@@_typeset_mark_wrapper:n ,
%   }
%   Auxiliary functions for mark typesetting in \cs{@@_note:nn}.
%   \cs{@@_typeset_mark_wrapper:n} is based on the definition of
%   \cs{@footnotemark} in the kernel.
%   \begin{syntax}
%     \cs{@@_typeset_mark:nn} \Arg{note id} \Arg{mark}
%     \cs{@@_typeset_mark_wrapper:n} \Arg{mark}
%   \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_typeset_mark:nn #1#2
  {
    \@@_typeset_mark_wrapper:n
      {
        \bool_if:NTF \l_@@_hyperlink_bool
          {
            \@@_make_mark:nnn {#2}
              { \hyper@linkstart { link } { postnote. #1 .text } }
              { \hyper@linkend }
          }
          { \@@_make_mark:nnn {#2} { } { } }
      }
  }
\cs_generate_variant:Nn \@@_typeset_mark:nn { eV }
\tl_new:N \l_@@_saved_spacefactor_tl
\cs_new_protected:Npn \@@_typeset_mark_wrapper:n #1
  {
    \mode_leave_vertical:
    \mode_if_horizontal:T
      {
        \tl_set:Ne \l_@@_saved_spacefactor_tl { \the\spacefactor }
        \nobreak
      }
    #1
    \mode_if_horizontal:T
      { \spacefactor \l_@@_saved_spacefactor_tl }
    \scan_stop:
  }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\@@_set_user_labels:}
%   Auxiliary function for user label setting in \cs{@@_note:nn}.  Supports
%   the \opt{label} and \opt{zlabel} options of \cs{postnote}.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_set_user_labels:
  {
    \tl_if_empty:NF \l_@@_note_label_tl
      { \exp_args:NV \label \l_@@_note_label_tl }
   \tl_if_empty:NF \l_@@_note_zlabel_tl
      { \exp_args:NV \zlabel \l_@@_note_zlabel_tl }
  }
%    \end{macrocode}
% \end{macro}
%
%
% \section{\cs{postnoteref}}
%
% \begin{macro}[int]{\postnoteref}
%   Provide \cs{postnoteref}.
%   \begin{syntax}
%     \cs{postnoteref}\meta{*}\marg{label}
%   \end{syntax}
%    \begin{macrocode}
\NewDocumentCommand \postnoteref { s m }
  { \@@_note_ref:nn {#1} {#2} }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_note_ref:nn}
%   The internal version of \cs{postnoteref}.
%   \begin{syntax}
%     \cs{@@_note_ref:nn} \Arg{star bool} \Arg{label}
%   \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_note_ref:nn #1#2
  {
    \group_begin:
    \@@_typeset_mark_wrapper:n
      {
        \bool_lazy_and:nnTF
          { ! #1 }
          { \l_@@_hyperlink_bool }
          {
            \hyperref [#2]
              { \@@_make_mark:nnn { \ref*{#2} } { } { } }
          }
          { \@@_make_mark:nnn { \ref*{#2} } { } { } }
      }
    \group_end:
  }
%    \end{macrocode}
% \end{macro}
%
%
% \section{\cs{postnotesection}}
%
% \begin{macro}[int]
%   {
%     \postnotesection ,
%     \postnotesectionx ,
%   }
%   Provide \cs{postnotesection} and \cs{postnotesectionx}.
%   \begin{syntax}
%     \cs{postnotesection}\oarg{options}\marg{section content}
%     \cs{postnotesectionx}\oarg{options}\marg{section content}
%   \end{syntax}
%    \begin{macrocode}
\NewDocumentCommand \postnotesection { O { } +m }
  { \@@_section:nn {#1} {#2} }
\NewDocumentCommand \postnotesectionx { O { } +m }
  {
    % NOTE Command deprecated in 2022-12-27 for v0.2.0.
    \msg_warning:nn { postnotes } { postnotesectionx-deprecated }
    \postnotesection [ #1 , exp ] {#2}
  }
\msg_new:nnn { postnotes } { postnotesectionx-deprecated }
  {
    '\iow_char:N\\postnotesectionx'~is~deprecated~\msg_line_context:.~
    Use~the~'exp'~option~of~'\iow_char:N\\postnotesection'~instead.
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_section:nn}
%   The internal version of \cs{postnotesection}.
%   \begin{syntax}
%     \cs{@@_section:nn} \Arg{options} \Arg{content}
%   \end{syntax}
%    \begin{macrocode}
\int_new:N \g_@@_sectid_int
\cs_new_protected:Npn \@@_section:nn #1#2
  {
    \group_begin:
    \int_gincr:N \g_@@_sectid_int
    \int_gincr:N \g_@@_note_id_int
    \seq_gput_right:Ne \g_@@_queue_seq { \l_postnotes_note_id_tl }
    \tl_gclear:N \g_@@_section_name_tl
    \keys_set:nn { postnotes/section } {#1}
    \bool_if:NTF \l_@@_section_exp_bool
      { \@@_store_section:ne { \l_postnotes_note_id_tl } {#2} }
      { \@@_store_section:nn { \l_postnotes_note_id_tl } {#2} }
    \group_end:
  }
%    \end{macrocode}
% \end{macro}
%
%
% Options for \cs{postnotesection}.  Actually, I would have preferred to use
% ``label'' for the \opt{name} option, but I feared I might need it further
% down the road for the traditional meaning.
%
%    \begin{macrocode}
\tl_new:N \g_@@_section_name_tl
\bool_new:N \l_@@_section_exp_bool
\keys_define:nn { postnotes/section }
  {
    name .tl_gset:N = \g_@@_section_name_tl ,
    name .value_required:n = true ,
    exp .bool_set:N = \l_@@_section_exp_bool ,
    exp .initial:n = false ,
    exp .default:n = true ,
  }
%    \end{macrocode}
%
%
% \section{\cs{printpostnotes}}
%
% \begin{macro}[int]{\printpostnotes}
%   Provide \cs{printpostnotes}.
%   \begin{syntax}
%     \cs{printpostnotes}
%   \end{syntax}
%    \begin{macrocode}
\NewDocumentCommand \printpostnotes { }
  { \@@_print_notes: }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}[int]
%   {
%     \pnthechapter ,
%     \pnthesection ,
%     \pnthechapternextnote ,
%     \pnthesectionnextnote ,
%     \pnthepage ,
%     \pnidnextnote ,
%   }
%   User facing variables, aimed at making available some of the notes' and
%   sections' metadata for the user at specific contexts.
%    \begin{macrocode}
\tl_new:N \pnthechapter
\tl_new:N \pnthesection
\tl_new:N \pnidnextnote
\tl_new:N \pnthechapternextnote
\tl_new:N \pnthesectionnextnote
\tl_new:N \pnthepage
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}
%   {
%     \g_@@_print_postnotes_int ,
%     \l_postnotes_print_note_id_tl ,
%     \l_@@_print_note_id_next_tl ,
%     \l_@@_print_counter_tl ,
%     \l_@@_print_mark_tl ,
%     \l_@@_print_type_curr_tl ,
%     \l_@@_print_type_next_tl ,
%     \l_@@_print_type_prev_tl ,
%     \l_@@_print_content_tl ,
%     \l_@@_clear_queue_seq ,
%   }
%   Auxiliary variables for \cs{@@_print_notes:}.
%    \begin{macrocode}
\int_new:N \g_@@_print_postnotes_int
\tl_new:N \l_postnotes_print_note_id_tl
\tl_new:N \l_@@_print_note_id_next_tl
\tl_new:N \l_@@_print_counter_tl
\tl_new:N \l_@@_print_mark_tl
\tl_new:N \l_@@_print_type_curr_tl
\tl_new:N \l_@@_print_type_next_tl
\tl_new:N \l_@@_print_type_prev_tl
\tl_new:N \l_@@_print_content_tl
\seq_new:N \l_@@_clear_queue_seq
%    \end{macrocode}
% \end{macro}
%
%
% \cs{@@_print_notes:} hooks.  Both meant at providing points of entry for
% additional setup, specially to add support to packages and features which
% require it.  The \texttt{postnotes/print/begin} hook is run early in
% \cs{@@_print_notes:} and only once per call, after the user options have
% been processed.  The \texttt{postnotes/print/note/begin} hook is run once
% for each note, at the point where environment variables are being set or
% restored, before the typesetting of either the mark or the text, but within
% a group of its own of each note.
%
%    \begin{macrocode}
\NewHook { postnotes/print/begin }
\NewHook { postnotes/print/note/begin }
%    \end{macrocode}
%
%
% The \texttt{postnotetext} is a counter used to restore the original value of
% \texttt{postnote} at the time of printing, for the purposes of
% cross-referencing, it should be different from \texttt{postnote} if a note
% may occur inside \cs{printpostnotes}.  The \texttt{postnotesection} is a
% counter which is stepped for every postnote section which gets to be
% actually typeset.  It's aim is to provide a valid ``enclosing counter'' to
% \texttt{postnote} in the context of \cs{printpostnotes}.  Since we don't
% know where \texttt{postnote} may have been reset along the document, in the
% general case, we can't rely on any other preexisting counter.  This means
% that the particular value of \texttt{postnotesection} is of little practical
% meaning, it really is just meant to provide recognizable ``bounds'' for
% \texttt{postnote} along the printing of the notes.  Indeed, it is
% initialized to a very high value (larger than the conceivable number of
% postnote sections in a document), so that ``marks'' and ``texts'' don't mix
% in the same reference list, which would occur if the enclosing counters of
% both belonged to the same range, and with somewhat arbitrary results, since
% we cannot ensure the step of the enclosing counter along the document
% matches \texttt{postnotesection}.  This is actually a tricky problem from
% the cross-referencing standpoint: two different things, which should be of
% the same type, are reset along the document, but shouldn't really be mixed
% together.  They are both \LaTeXe{} counters, since they may be required
% externally.  Their main intended use case is to support \pkg{zref-clever},
% but in principle they can be of general use.
%
%    \begin{macrocode}
\newcounter { postnotetext }
\newcounter { postnotesection }
\setcounter { postnotesection } { 10000 }
%    \end{macrocode}
%
%
% \begin{macro}{\@@_print_notes:}
%   The internal version of \cs{printpostnotes}.
%   \begin{syntax}
%     \cs{@@_print_notes:}
%   \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_print_notes:
  {
    \group_begin:
    \int_gincr:N \g_@@_print_postnotes_int
    \seq_if_empty:NTF \g_@@_queue_seq
      { \msg_warning:nn { postnotes } { empty-printpostnotes } }
      {
        \pnheading
        \UseHook { postnotes/print/begin }
        \tl_set:Nn \l_@@_print_type_prev_tl { open }
        \seq_set_eq:NN \l_@@_clear_queue_seq \g_@@_queue_seq
        \@@_verify_multipass:N \g_@@_queue_seq
        \bool_if:NT \l_@@_sort_bool
          { \@@_sort_queue:N \g_@@_queue_seq }
        \bool_gset_true:N \g_@@_header_vars_next_bool
        \@@_get_headers_data:N \g_@@_queue_seq
        \@@_set_headers_vars_first:
%    \end{macrocode}
% Ensure the first note after a heading has paragraph indentation when
% \opt{listenv} is \texttt{none}.  \pkg{endnotes} uses a workaroundish
% solution in \cs{enoteheading}, setting a box and then skipping back a line.
% Enrico Gregorio is correct, though, in criticizing it at
% \url{https://tex.stackexchange.com/q/575905#comment1450213_575915}, and
% suggests the use of \cs{@afterindenttrue}, which is what \pkg{indentfirst}
% does (we do the same, just locally).
%    \begin{macrocode}
        \bool_if:NF \l_@@_print_as_list_bool
          {
            \cs_set_eq:NN \@afterindentfalse \@afterindenttrue
            \@afterindenttrue
          }
        \bool_until_do:nn { \seq_if_empty_p:N \g_@@_queue_seq }
          {
            \seq_gpop_left:NN \g_@@_queue_seq
              \l_postnotes_print_note_id_tl
            \@@_prop_get:nnN { \l_postnotes_print_note_id_tl }
              { type } \l_@@_print_type_curr_tl
            \tl_if_eq:NnTF \l_@@_print_type_curr_tl { section }
              { % type_curr = `section'
                \seq_if_empty:NTF \g_@@_queue_seq
                  {
                    \tl_set:Nn \l_@@_print_note_id_next_tl { noid }
                    \tl_set:Nn \l_@@_print_type_next_tl { close }
                  }
                  {
                    \seq_get_left:NN \g_@@_queue_seq
                      \l_@@_print_note_id_next_tl
                    \@@_prop_get:nnN
                      { \l_@@_print_note_id_next_tl }
                      { type } \l_@@_print_type_next_tl
                  }
%    \end{macrocode}
% We only process the entry if \texttt{type_next} is \texttt{note}: here are
% skipped empty sections.
%    \begin{macrocode}
                \tl_if_eq:NnT \l_@@_print_type_next_tl { note }
                  {
                    \stepcounter { postnotesection }
                    \group_begin:
                    \@@_prop_get:nnN
                      { \l_postnotes_print_note_id_tl }
                      { thechapter } \pnthechapter
                    \@@_prop_get:nnN
                      { \l_postnotes_print_note_id_tl }
                      { thesection } \pnthesection
                    \tl_set:NV \pnidnextnote \l_@@_print_note_id_next_tl
                    \@@_prop_get:nnN
                      { \l_@@_print_note_id_next_tl }
                      { thechapter } \pnthechapternextnote
                    \@@_prop_get:nnN
                      { \l_@@_print_note_id_next_tl }
                      { thesection } \pnthesectionnextnote
                    \@@_prop_get:nnN
                      { \l_postnotes_print_note_id_tl }
                      { content } \l_@@_print_content_tl
                    \l_@@_print_content_tl
                    \group_end:
%    \end{macrocode}
% Set \texttt{type_prev} for the next iteration.
%    \begin{macrocode}
                    \tl_set:NV \l_@@_print_type_prev_tl
                      \l_@@_print_type_curr_tl
                  }
              }
              { % type_curr = `note'
                \tl_if_eq:NnF \l_@@_print_type_prev_tl { note }
                  {
                    \bool_if:NTF \l_@@_print_as_list_bool
                      { \exp_args:Ne \begin { \l_@@_print_env_tl } }
                      { \group_begin: }
                    \l_@@_print_format_tl
                  }
                \group_begin:
                \UseHook { postnotes/print/note/begin }
                \@@_get_pageref:Ne \pnthepage
                  { mark@ \l_postnotes_print_note_id_tl }
                \@@_prop_get:nnN
                  { \l_postnotes_print_note_id_tl }
                  { mark } \l_@@_print_mark_tl
                \@@_prop_get:nnN
                  { \l_postnotes_print_note_id_tl }
                  { counter } \l_@@_print_counter_tl
                \@@_prop_get:nnN
                  { \l_postnotes_print_note_id_tl }
                  { content } \l_@@_print_content_tl
                \cs_set:Npn \@currentcounter { postnotetext }
                \int_set:Nn \c@postnotetext
                  { \l_@@_print_counter_tl }
                \cs_set:Npe \@currentlabel
                  { \p@postnote \l_@@_print_mark_tl }
                \@@_text_mark_wrapper:n
                  {
                    \MakeLinkTarget*
                      { postnote. \l_postnotes_print_note_id_tl .text }
                    \@@_set_text_page_label:e
                      { \l_postnotes_print_note_id_tl }
                    \@@_typeset_text_mark:eV
                      { \l_postnotes_print_note_id_tl }
                      \l_@@_print_mark_tl
                  }
                \l_@@_print_content_tl
                \l_@@_post_printnote_tl
                \group_end:
%    \end{macrocode}
% For notes, query for next note's type \texttt{after} the current note was
% typeset, to handle possible nesting.  Even if nesting is not a feature, this
% should avoid hard crashes related to ``lonely \cs{item}'' or ``extra
% \cs{endgroup}'' errors, in case it occurs.
%    \begin{macrocode}
                \seq_if_empty:NTF \g_@@_queue_seq
                  {
                    \tl_set:Nn \l_@@_print_note_id_next_tl { noid }
                    \tl_set:Nn \l_@@_print_type_next_tl { close }
                  }
                  {
                    \seq_get_left:NN \g_@@_queue_seq
                      \l_@@_print_note_id_next_tl
                    \@@_prop_get:nnN
                      { \l_@@_print_note_id_next_tl }
                      { type } \l_@@_print_type_next_tl
                  }
                \tl_if_eq:NnF \l_@@_print_type_next_tl { note }
                  {
                    \bool_if:NTF \l_@@_print_as_list_bool
                      { \exp_args:Ne \end { \l_@@_print_env_tl } }
                      { \group_end: }
%    \end{macrocode}
% Ensure \cs{par} at the end of \cs{printopostnotes} (see
% \url{https://github.com/u-fischer/tagpdf/issues/68#issuecomment-1587343876},
% thanks \contributor{Ulrike Fischer}).
%    \begin{macrocode}
                    \par
                  }
%    \end{macrocode}
% Set \texttt{type_prev} for the next iteration.
%    \begin{macrocode}
                \tl_set:NV \l_@@_print_type_prev_tl
                  \l_@@_print_type_curr_tl
              }
          }
        \AddToHookNext { shipout/after }
          { \bool_gset_false:N \g_@@_header_vars_next_bool }
%    \end{macrocode}
% We won't use the variables anymore, clear them to reduce memory usage.
% Given how we populated \cs{l_@@_clear_queue_seq}, this won't catch nested
% notes.  But it's not worth to conditionally add new items along the way
% (testing it every iteration) for this.  Again, not a feature.
%    \begin{macrocode}
        \seq_map_inline:Nn \l_@@_clear_queue_seq
          { \@@_prop_gclear:n { ##1 } }
      }
    \group_end:
  }
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
\msg_new:nnn { postnotes } { empty-printpostnotes }
  { Empty~'\iow_char:N\\printpostnotes'~\msg_line_context:. }
%    \end{macrocode}
%
%
% \begin{macro}
%   {
%     \@@_typeset_text_mark:nn ,
%     \@@_text_mark_wrapper:n ,
%   }
%   Auxiliary functions for mark typesetting in \cs{@@_print_notes:}.
%   \begin{syntax}
%     \cs{@@_typeset_text_mark:nn} \Arg{note id} \Arg{mark}
%     \cs{@@_text_mark_wrapper:n} \Arg{mark}
%   \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_typeset_text_mark:nn #1#2
  {
    \bool_lazy_and:nnTF
      { \l_@@_hyperlink_bool }
      { \l_@@_backlink_bool  }
      {
        \@@_make_text_mark:nnn {#2}
          { \hyper@linkstart { link } { postnote. #1 .mark } }
          { \hyper@linkend }
      }
      { \@@_make_text_mark:nnn {#2} { } { } }
  }
\cs_generate_variant:Nn \@@_typeset_text_mark:nn { eV }
\cs_new_protected:Npn \@@_text_mark_wrapper:n #1
  {
    \bool_if:NTF \l_@@_print_as_list_bool
      {
        \item [ \l_@@_pre_textmark_tl #1 \l_@@_post_textmark_tl ]
%    \end{macrocode}
% Leave vertical mode to avoid ``perhaps a missing \cs{item}'' error for empty
% notes.
%    \begin{macrocode}
        \mode_leave_vertical:
      }
      { \l_@@_pre_textmark_tl #1 \l_@@_post_textmark_tl }
  }
%    \end{macrocode}
% \end{macro}
%
%
% \subsection*{Print auxiliary}
%
% \cs{@@_verify_multipass:N} provides a general procedure for handling cases
% of multiple passes of content.  Ideally, the job should be done at
% \cs{@@_inhibit_note:F}, if at all possible.  But, failing that, we can rely
% on the fact that \cs{postnote}s of measuring/trial passes don't end up being
% output and hence don't generate labels in the \file{.aux} file.  This is the
% equivalent for \pkg{postnotes} to the effect of write restrictions for the
% packages based on external files, which is how they actually handle these
% cases.  However, despite this being a general test, and a reasonable one,
% I'd like to restrain it's use to the minimum possible.  First, using this
% criterion across the board would result in large swings on the content of
% \cs{printpostnotes} and spurious warnings in an initial compilation since
% the labels are not available on the first run.  Second, I'd prefer not to
% interfere with the queue, unless we really need to.  Hence, we only apply
% this check for ``eligible'' items.  For signaling this eligibility, the note
% must have been stored with the \cs{l_@@_maybe_multi_bool} set to
% \texttt{true}, which is then saved in the \texttt{multibool} property.  One
% implication of this procedure is that, if there are any new notes marked as
% \texttt{multibool}, three rounds of compilation will be needed, since the
% labels of the printed notes will be written only on the second run and the
% document will thus require a third one to stabilize.
%
% \begin{macro}{\@@_verify_multipass:N}
%   \begin{syntax}
%     \cs{@@_verify_multipass:N} \meta{\cs{g_@@_queue_seq}}
%   \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_verify_multipass:N #1
  {
    \group_begin:
    \seq_clear:N \l_@@_tmpa_seq
    \seq_map_inline:Nn #1
      {
        \@@_prop_get:nnN {##1} { multibool } \l_@@_tmpa_tl
        \str_if_eq:VnTF \l_@@_tmpa_tl { true }
          {
            \cs_if_exist:cT
              { \c_@@_ref_prefix_tl @ mark@ ##1 }
              { \seq_put_right:Nn \l_@@_tmpa_seq {##1} }
          }
          { \seq_put_right:Nn \l_@@_tmpa_seq {##1} }
      }
    \seq_gset_eq:NN #1 \l_@@_tmpa_seq
    \group_end:
  }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\@@_sort_queue:N}
%   Sorting function for \cs{@@_print_notes:}.
%   \begin{syntax}
%     \cs{@@_sort_queue:N} \meta{\cs{g_@@_queue_seq}}
%   \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_sort_queue:N #1
  {
    \group_begin:
    \seq_gsort:Nn #1
      {
        \@@_prop_get:nnN {##1} { pnsectid } \l_@@_tmpa_tl
        \@@_prop_get:nnN {##2} { pnsectid } \l_@@_tmpb_tl
        \tl_if_eq:NNTF \l_@@_tmpa_tl \l_@@_tmpb_tl
          {
            \@@_prop_get:nnN {##1} { type } \l_@@_tmpa_tl
            \@@_prop_get:nnN {##2} { type } \l_@@_tmpb_tl
            \bool_lazy_and:nnTF
              { \str_if_eq_p:Vn \l_@@_tmpa_tl { note } }
              { \str_if_eq_p:Vn \l_@@_tmpb_tl { note } }
              {
                \@@_prop_get:nnN {##1} { sortnum } \l_@@_tmpa_tl
                \@@_prop_get:nnN {##2} { sortnum } \l_@@_tmpb_tl
                \fp_compare:nNnTF
                  { \l_@@_tmpa_tl } > { \l_@@_tmpb_tl }
                  { \sort_return_swapped: }
                  { \sort_return_same:    }
              }
              { \sort_return_same: }
          }
          { \sort_return_same: }
      }
    \group_end:
  }
%    \end{macrocode}
% \end{macro}
%
%
% \section{Headers}
%
% The headers infrastructure of \pkg{postnotes} is comprised of three basic
% parts:
%
% \begin{enumerate}
% \item For each \cs{postnote}, labels are set storing the \texttt{page} where
%   the note occurs.  Each note actually generates a pair of such labels, once
%   when \cs{postnote} is called (with the mark), and another where the note
%   is printed (in \cs{printpostnotes}).  The former ones store \cs{thepage},
%   since we want the printed representation of it for typesetting purposes,
%   the latter ones store the value of the \texttt{page} counter, since we
%   don't need to typeset it, but do need to perform algebraic operations with
%   it.  These labels are set by \cs{@@_set_mark_page_label:n},
%   \cs{@@_set_text_page_label:n}, and \cs{@@_set_print_page_label:n} at the
%   appropriate places.  The set of these labels provides a mapping from each
%   note's ``mark'' and ``text'' to the page where it occurs.
% \item This information set is processed by \cs{@@_get_headers_data:N} at the
%   beginning of \cs{@@_print_notes:} to identify the first and last note of
%   each page in \cs{printpostnotes}, and to generate a mapping from these
%   first and last notes on each page to the pages where their corresponding
%   marks occur.  We also take the opportunity to enrich this mapping with
%   other metadata of each note.  So we get also mappings from the first and
%   last note on each page to \cs{thechapter}, \cs{thesection}, and the
%   \opt{name} of the section in which they occur.  These mappings are stored
%   in property lists \cs[no-index]{g_@@_header_\meta{info}_first_prop} and
%   \cs[no-index]{g_@@_header_\meta{info}_last_prop} where the \texttt{key} is
%   the page in \cs{printpostnotes} where their note's content is typeset (or
%   rather where it starts to be typeset, it is the page where the text's mark
%   is printed).
% \item Based on these mappings, along the span of notes section we run
%   \cs{@@_set_headers_vars_next:} at each \texttt{shipout/before} hook to set
%   user facing variables for the \emph{next} page, which will be available
%   when their heading gets typeset.  Given that at \texttt{shipout} we can
%   rely on a correct value of the \texttt{page} counter, we use it as
%   \texttt{key} to query the property lists generated in the previous step.
%   These user facing variables are called \cs[no-index]{pnhd\meta{info}first}
%   and \cs[no-index]{pnhd\meta{info}last}.  Since we cannot rely on the
%   shipout hook for the first page of \cs{printpostnotes},
%   \cs{@@_set_headers_vars_first:} is run at its beginning to ensure correct
%   values are in place on the first page of the notes section.
% \end{enumerate}
%
% These \cs[no-index]{pnhd\meta{info}first} and
% \cs[no-index]{pnhd\meta{info}last} variables can then be used to build
% simple functions which can be passed to mark commands to achieve rich
% contextual running headers.
%
%
% \begin{macro}[int]
%   {
%     \pnhdpagefirst ,
%     \pnhdpagelast ,
%     \pnhdchapfirst ,
%     \pnhdchaplast ,
%     \pnhdsectfirst ,
%     \pnhdsectlast ,
%     \pnhdnamefirst ,
%     \pnhdnamelast ,
%   }
%   User facing variables, aimed at making available header data for the user.
%   Setting these variables with correct values at the moment the header gets
%   typeset is \emph{the} objective of the whole headers infrastructure of the
%   package.
%    \begin{macrocode}
\tl_new:N \pnhdpagefirst
\tl_new:N \pnhdpagelast
\tl_new:N \pnhdchapfirst
\tl_new:N \pnhdchaplast
\tl_new:N \pnhdsectfirst
\tl_new:N \pnhdsectlast
\tl_new:N \pnhdnamefirst
\tl_new:N \pnhdnamelast
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}
%   {
%     \g_@@_header_page_first_prop ,
%     \g_@@_header_page_last_prop ,
%     \g_@@_header_chap_first_prop ,
%     \g_@@_header_chap_last_prop ,
%     \g_@@_header_sect_first_prop ,
%     \g_@@_header_sect_last_prop ,
%     \g_@@_header_name_first_prop ,
%     \g_@@_header_name_last_prop ,
%     \g_@@_header_prev_last_page_tl ,
%     \g_@@_header_prev_last_chap_tl ,
%     \g_@@_header_prev_last_sect_tl ,
%     \g_@@_header_prev_last_name_tl ,
%     \l_@@_prev_text_page_tl ,
%     \l_@@_curr_text_page_tl ,
%     \l_@@_prev_mark_page_tl ,
%     \l_@@_prev_mark_chap_tl ,
%     \l_@@_prev_mark_sect_tl ,
%     \l_@@_prev_mark_name_tl ,
%   }
%   Auxiliary variables for the headers infrastructure.
%    \begin{macrocode}
\prop_new:N \g_@@_header_page_first_prop
\prop_new:N \g_@@_header_page_last_prop
\prop_new:N \g_@@_header_chap_first_prop
\prop_new:N \g_@@_header_chap_last_prop
\prop_new:N \g_@@_header_sect_first_prop
\prop_new:N \g_@@_header_sect_last_prop
\prop_new:N \g_@@_header_name_first_prop
\prop_new:N \g_@@_header_name_last_prop
\tl_new:N \g_@@_header_prev_last_page_tl
\tl_new:N \g_@@_header_prev_last_chap_tl
\tl_new:N \g_@@_header_prev_last_sect_tl
\tl_new:N \g_@@_header_prev_last_name_tl
\tl_new:N \l_@@_prev_text_page_tl
\tl_new:N \l_@@_curr_text_page_tl
\tl_new:N \l_@@_prev_mark_page_tl
\tl_new:N \l_@@_prev_mark_chap_tl
\tl_new:N \l_@@_prev_mark_sect_tl
\tl_new:N \l_@@_prev_mark_name_tl
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\@@_get_headers_data:N}
%   Process header data for \cs{@@_set_headers_vars:n}.
%   \begin{syntax}
%     \cs{@@_get_headers_data:N} \meta{\cs{g_@@_queue_seq}}
%   \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_get_headers_data:N #1
  {
    \group_begin:
    \tl_gclear:N \pnhdpagefirst
    \tl_gclear:N \pnhdpagelast
    \tl_gclear:N \pnhdchapfirst
    \tl_gclear:N \pnhdchaplast
    \tl_gclear:N \pnhdsectfirst
    \tl_gclear:N \pnhdsectlast
    \tl_gclear:N \pnhdnamefirst
    \tl_gclear:N \pnhdnamelast
    \prop_gclear:N \g_@@_header_page_first_prop
    \prop_gclear:N \g_@@_header_page_last_prop
    \prop_gclear:N \g_@@_header_chap_first_prop
    \prop_gclear:N \g_@@_header_chap_last_prop
    \prop_gclear:N \g_@@_header_sect_first_prop
    \prop_gclear:N \g_@@_header_sect_last_prop
    \prop_gclear:N \g_@@_header_name_first_prop
    \prop_gclear:N \g_@@_header_name_last_prop
    \tl_gclear:N \g_@@_header_prev_last_page_tl
    \tl_gclear:N \g_@@_header_prev_last_chap_tl
    \tl_gclear:N \g_@@_header_prev_last_sect_tl
    \tl_gclear:N \g_@@_header_prev_last_name_tl
    \tl_clear:N \l_@@_prev_text_page_tl
    \tl_clear:N \l_@@_curr_text_page_tl
    \tl_clear:N \l_@@_prev_mark_page_tl
    \tl_clear:N \l_@@_prev_mark_chap_tl
    \tl_clear:N \l_@@_prev_mark_sect_tl
    \tl_clear:N \l_@@_prev_mark_name_tl
    \seq_map_inline:Nn #1
      {
        \exp_args:Ne \tl_if_eq:nnT
          { \@@_prop_item:nn {##1} { type } }
          { note }
          {
            \@@_get_pageref:Nn
              \l_@@_curr_text_page_tl { text@ ##1 }
            \tl_if_empty:NF \l_@@_curr_text_page_tl
              {
                \tl_if_eq:NNTF
                  \l_@@_prev_text_page_tl
                  \l_@@_curr_text_page_tl
                  {
%    \end{macrocode}
% We are on the same page as the previous note, just update the
% \texttt{prev_mark} data.
%    \begin{macrocode}
                    \@@_get_pageref:Nn
                      \l_@@_prev_mark_page_tl { mark@ ##1 }
                    \@@_prop_get:nnN {##1} { thechapter }
                      \l_@@_prev_mark_chap_tl
                    \@@_prop_get:nnN {##1} { thesection }
                      \l_@@_prev_mark_sect_tl
                    \@@_prop_get:nnN {##1} { pnsectname }
                      \l_@@_prev_mark_name_tl
                  }
                  {
%    \end{macrocode}
% We are on the transition between two pages, current ID is the first note of
% the new page (or on the very first note of \cs{printpostnotes}, given
% \cs{l_@@_prev_text_page_tl} is initialized to empty).
%
% Set `last' values for previous page, based on the last valid
% \texttt{prev_mark} stored ones.  There is no previous page to the first one
% of \cs{printpostnotes}, so we don't set `last' values for it (conditioning
% on \cs{l_@@_prev_text_page_tl} being empty, which only occurs on the first
% note).
%    \begin{macrocode}
                    \tl_if_empty:NF \l_@@_prev_text_page_tl
                      {
                        \prop_gput:Nee \g_@@_header_page_last_prop
                          { \l_@@_prev_text_page_tl }
                          { \l_@@_prev_mark_page_tl }
                        \prop_gput:Nee \g_@@_header_chap_last_prop
                          { \l_@@_prev_text_page_tl }
                          { \l_@@_prev_mark_chap_tl }
                        \prop_gput:Nee \g_@@_header_sect_last_prop
                          { \l_@@_prev_text_page_tl }
                          { \l_@@_prev_mark_sect_tl }
                        \prop_gput:Nee \g_@@_header_name_last_prop
                          { \l_@@_prev_text_page_tl }
                          { \l_@@_prev_mark_name_tl }
                      }
%    \end{macrocode}
%
% Set `first' values for current page, based on the current note ID.
%    \begin{macrocode}
                    \prop_gput:Nee \g_@@_header_page_first_prop
                      { \l_@@_curr_text_page_tl }
                      { \@@_extract_pageref:n { mark@ ##1 } }
                    \prop_gput:Nee \g_@@_header_chap_first_prop
                      { \l_@@_curr_text_page_tl }
                      { \@@_prop_item:nn {##1} { thechapter } }
                    \prop_gput:Nee \g_@@_header_sect_first_prop
                      { \l_@@_curr_text_page_tl }
                      { \@@_prop_item:nn {##1} { thesection } }
                    \prop_gput:Nee \g_@@_header_name_first_prop
                      { \l_@@_curr_text_page_tl }
                      { \@@_prop_item:nn {##1} { pnsectname } }
%    \end{macrocode}
%
% Store \texttt{prev_mark} data for the first note on the page.
%    \begin{macrocode}
                    \@@_get_pageref:Nn
                      \l_@@_prev_mark_page_tl { mark@ ##1 }
                    \@@_prop_get:nnN {##1} { thechapter }
                      \l_@@_prev_mark_chap_tl
                    \@@_prop_get:nnN {##1} { thesection }
                      \l_@@_prev_mark_sect_tl
                    \@@_prop_get:nnN {##1} { pnsectname }
                      \l_@@_prev_mark_name_tl
%    \end{macrocode}
%
% Set \cs{l_@@_prev_text_page_tl} for the next page
% (\cs{l_@@_curr_text_page_tl} is never empty at this point, since we
% conditioned to it).
%    \begin{macrocode}
                    \tl_set:NV \l_@@_prev_text_page_tl
                      \l_@@_curr_text_page_tl
                  }
              }
          }
      }
%    \end{macrocode}
% We can't catch the transition from the last page of \cs{printpostnotes} to
% the following one through the mapping above, but the \texttt{prev_mark}
% values of the last note in the loop are the ones we want, so we set `last'
% values for the last page based on them.
%    \begin{macrocode}
    \tl_if_empty:NF \l_@@_prev_text_page_tl
      {
        \prop_gput:Nee \g_@@_header_page_last_prop
          { \l_@@_prev_text_page_tl }
          { \l_@@_prev_mark_page_tl }
        \prop_gput:Nee \g_@@_header_chap_last_prop
          { \l_@@_prev_text_page_tl }
          { \l_@@_prev_mark_chap_tl }
        \prop_gput:Nee \g_@@_header_sect_last_prop
          { \l_@@_prev_text_page_tl }
          { \l_@@_prev_mark_sect_tl }
        \prop_gput:Nee \g_@@_header_name_last_prop
          { \l_@@_prev_text_page_tl }
          { \l_@@_prev_mark_name_tl }
      }
    \group_end:
  }
%    \end{macrocode}
% \end{macro}
%
%
% The sequence of pages processed in \cs{@@_get_headers_data:N} is not ensured
% to be continuous, since not every page of \cs{printpostnotes} starts a note.
% There may be notes that fill whole pages, or the last page of the notes may
% end with a note that started on the penultimate page.  We must handle this
% case at \cs{@@_set_headers_vars:n}.  For every page for which there is
% information provided by \cs{@@_get_headers_data:N} we store a
% \texttt{header_prev_last} (the last value of the previous header) for each
% of the variables of interest.  If the next page is skipped in the sequence
% (no notes starting on it), we can use these stored values to set both
% `first' and `last' variables based on them for that page.
%
%
% \begin{macro}{\@@_set_headers_vars:n}
%   Set user facing variables based on data generated by
%   \cs{@@_get_headers_data:N}.
%   \begin{syntax}
%     \cs{@@_set_headers_vars:n} \Arg{page number}
%   \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_set_headers_vars:n #1
  {
    \group_begin:
    \prop_get:NnNTF \g_@@_header_page_first_prop
      {#1} \l_@@_tmpa_tl
      { \tl_gset:NV \pnhdpagefirst \l_@@_tmpa_tl }
      { \tl_gset:NV \pnhdpagefirst \g_@@_header_prev_last_page_tl }
    \prop_get:NnNTF \g_@@_header_page_last_prop
      {#1} \l_@@_tmpa_tl
      {
        \tl_gset:NV \pnhdpagelast \l_@@_tmpa_tl
        \tl_gset:NV \g_@@_header_prev_last_page_tl
          \l_@@_tmpa_tl
      }
      { \tl_gset:NV \pnhdpagelast \g_@@_header_prev_last_page_tl }
    \prop_get:NnNTF \g_@@_header_chap_first_prop
      {#1} \l_@@_tmpa_tl
      { \tl_gset:NV \pnhdchapfirst \l_@@_tmpa_tl }
      { \tl_gset:NV \pnhdchapfirst \g_@@_header_prev_last_chap_tl }
    \prop_get:NnNTF \g_@@_header_chap_last_prop
      {#1} \l_@@_tmpa_tl
      {
        \tl_gset:NV \pnhdchaplast \l_@@_tmpa_tl
        \tl_gset:NV \g_@@_header_prev_last_chap_tl
          \l_@@_tmpa_tl
      }
      { \tl_gset:NV \pnhdchaplast \g_@@_header_prev_last_chap_tl }
    \prop_get:NnNTF \g_@@_header_sect_first_prop
      {#1} \l_@@_tmpa_tl
      { \tl_gset:NV \pnhdsectfirst \l_@@_tmpa_tl }
      { \tl_gset:NV \pnhdsectfirst \g_@@_header_prev_last_sect_tl }
    \prop_get:NnNTF \g_@@_header_sect_last_prop
      {#1} \l_@@_tmpa_tl
      {
        \tl_gset:NV \pnhdsectlast \l_@@_tmpa_tl
        \tl_gset:NV \g_@@_header_prev_last_sect_tl
          \l_@@_tmpa_tl
      }
      { \tl_gset:NV \pnhdsectlast \g_@@_header_prev_last_sect_tl }
    \prop_get:NnNTF \g_@@_header_name_first_prop
      {#1} \l_@@_tmpa_tl
      { \tl_gset:NV \pnhdnamefirst \l_@@_tmpa_tl }
      { \tl_gset:NV \pnhdnamefirst \g_@@_header_prev_last_name_tl }
    \prop_get:NnNTF \g_@@_header_name_last_prop
      {#1} \l_@@_tmpa_tl
      {
        \tl_gset:NV \pnhdnamelast \l_@@_tmpa_tl
        \tl_gset:NV \g_@@_header_prev_last_name_tl
          \l_@@_tmpa_tl
      }
      { \tl_gset:NV \pnhdnamelast \g_@@_header_prev_last_name_tl }
    \group_end:
  }
\cs_generate_variant:Nn \@@_set_headers_vars:n { e }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}
%   {
%     \@@_set_headers_vars_next: ,
%     \@@_set_headers_vars_first: ,
%   }
%   The functions that actually call \cs{@@_set_headers_vars:n} at the
%   appropriate contexts with appropriate page values.  Though we set
%   \cs{@@_set_headers_vars_next:} to run at every \texttt{shipout/before}
%   hook of the document, it is made no-op by \cs{g_@@_header_vars_next_bool}
%   which only has a \texttt{true} value inside \cs{printpostnotes}.
%   \cs{@@_set_headers_vars_first:} must set a label and retrieve its value to
%   be able to have a reliable value of its own page.
%    \begin{macrocode}
\AddToHook { shipout/before } [ postnotes/header ]
  { \@@_set_headers_vars_next: }
\bool_new:N \g_@@_header_vars_next_bool
\cs_new_protected:Npn \@@_set_headers_vars_next:
  {
    \bool_if:NT \g_@@_header_vars_next_bool
      { \@@_set_headers_vars:e { \int_eval:n { \c@page + 1 } } }
  }
\cs_new_protected:Npn \@@_set_headers_vars_first:
  {
    \@@_set_print_page_label:e
      { \int_use:N \g_@@_print_postnotes_int }
    \@@_set_headers_vars:e
      {
        \@@_extract_pageref:e
          { print@ \int_use:N \g_@@_print_postnotes_int }
      }
  }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}[int]{\pnheaderdefault}
%   A basic header function to be used as default in the \opt{heading} option.
%   It produces a header in the form ``Notes to pages N--M'', with a text
%   which can be localized (see Section~\ref{sec:languages}).
%   \begin{syntax}
%     \cs{pnheaderdefault}
%   \end{syntax}
%    \begin{macrocode}
\NewDocumentCommand \pnheaderdefault {}
  {
    \tl_if_eq:NNTF \pnhdpagefirst \pnhdpagelast
      { \pnhdnotes{} ~ \pnhdtopage{} ~ \pnhdpagefirst }
      { \pnhdnotes{} ~ \pnhdtopages{} ~ \pnhdpagefirst -- \pnhdpagelast }
  }
%    \end{macrocode}
% \end{macro}
%
%
% \section{Compatibility}
%
% A dedicated temp variable for restoring data.
%
%    \begin{macrocode}
\tl_new:N \l_@@_restore_tmp_tl
%    \end{macrocode}
%
% \subsection*{\cs{caption}}
%
% For \cs{caption}'s possible two passes.  This catches more than just
% captions, of course, but is not overkill.
%
% From the user's perspective, one-line captions will just work.  For two-line
% captions, there are two alternatives: i) decrement the counter by 1
% \texttt{\textbackslash{}addtocounter\{postnote\}\{-1\}} before the caption,
% then call \cs{postnote} inside the caption; or ii) right before the caption,
% call
% \texttt{\textbackslash{}postnote[nomark]\{\textbackslash{}label\{mynote\}...\}},
% then use \texttt{\textbackslash{}postnoteref\{mynote\}} inside the caption.
%
%    \begin{macrocode}
\AddToHook { postnotes/note/begin } [ postnotes ]
  {
    \cs_if_exist:NT \@captype
      { \bool_set_true:N \l_@@_maybe_multi_bool }
  }
%    \end{macrocode}
%
%
% \subsection*{\pkg{biblatex}}
%
% Thanks \contributor{Moritz Wemheuer}:
% \url{https://tex.stackexchange.com/q/597359#comment1594585_597389}.
%
%
%    \begin{macrocode}
\AddToHook { package/biblatex/after }
  {
%    \end{macrocode}
% Let \pkg{biblatex} know we are in a ``notes'' context.  See
% \url{https://tex.stackexchange.com/a/304464}, including comments.
%    \begin{macrocode}
    \AddToHook { postnotes/print/begin } [ postnotes ]
      { \toggletrue { blx@footnote } }
%    \end{macrocode}
% Make \pkg{biblatex}'s \cs{mkbibendnote} use \cs{postnote}.  This is very
% likely desired in most cases, but may occasionally not be, so we add it to
% an individually labeled hook, which can be disabled with
% \texttt{\textbackslash{}RemoveFromHook\{begindocument/before\}[postnotes/mkbibendnote]}
% in the preamble.
%    \begin{macrocode}
    \AddToHook { begindocument/before } [ postnotes/mkbibendnote ]
      {
        \cs_set:Npn \blx@theendnote { \postnote }
        \cs_set:Npn \blx@theendnotetext
          { \blx@err@endnote \footnotetext }
      }
  }
%    \end{macrocode}
%
%
%    \begin{macrocode}
%<*gobble>
%    \end{macrocode}
%
% I had made an initial experimental attempt to support \pkg{biblatex}'s
% \texttt{refsegment}s, \texttt{refcontext}s and \texttt{refsection}s.
% However, this attempt was rash.  Even if I could get many example files to
% work for \texttt{refsegment}s and \texttt{refcontext}s, I could not do so
% for \texttt{refsection}s.  More importantly, with this partial
% implementation, I could also generate documents which confused
% \pkg{biblatex} more than it helped.  Things I couldn't understand well, or
% fix.  All in all, I don't think this partial implementation is tenable, and
% I could not take it further.  Hence, \pkg{postnotes} support for this
% feature set of \pkg{biblatex} will depend, as it should, on proper upstream
% support for ``saving'' and ``restoring'' citation ``context'' information.
%
% I have made a feature request at \pkg{biblatex} for this
% (\url{https://github.com/plk/biblatex/issues/1226}), which was
% (understandably) classified as ``long term, no promises''.
%
%
% The attempt was the following (currently ``gobbled'' from the package):
%
%    \begin{macrocode}
\AddToHook { package/biblatex/after }
  {
%    \end{macrocode}
% Store \pkg{biblatex} variables for each note.
%    \begin{macrocode}
    \AddToHook { postnotes/note/store } [ postnotes ]
      {
        \prop_gput:cne { \@@_data_name:e { \l_postnotes_note_id_tl } }
          { biblatex@refsection } { \int_use:N \c@refsection }
        \prop_gput:cne { \@@_data_name:e { \l_postnotes_note_id_tl } }
          { biblatex@refsegment } { \int_use:N \c@refsegment }
        \prop_gput:cne { \@@_data_name:e { \l_postnotes_note_id_tl } }
          { biblatex@refcontextbool }
          { \iftoggle { blx@refcontext } { true } { false } }
        \prop_gput:cnV { \@@_data_name:e { \l_postnotes_note_id_tl } }
          { biblatex@refcontext } \blx@refcontext@context
      }
%    \end{macrocode}
% \pkg{biblatex} setup, once for \cs{printpostnotes} call.
%    \begin{macrocode}
    \AddToHook { postnotes/print/begin } [ postnotes ]
      {
        \@@_biblatex_endrefcontext_local:
        \@@_biblatex_citereset_local:
      }
%    \end{macrocode}
% Restore \pkg{biblatex} variables for each note.
%    \begin{macrocode}
    \AddToHook { postnotes/print/note/begin } [ postnotes ]
      {
        \@@_prop_get:nnN { \l_postnotes_print_note_id_tl }
          { biblatex@refsection } \l_@@_restore_tmp_tl
        \int_set:Nn \c@refsection { \l_@@_restore_tmp_tl }
        \@@_prop_get:nnN { \l_postnotes_print_note_id_tl }
          { biblatex@refsegment } \l_@@_restore_tmp_tl
        \int_set:Nn \c@refsegment { \l_@@_restore_tmp_tl }
        \@@_prop_get:nnN { \l_postnotes_print_note_id_tl }
          { biblatex@refcontextbool } \l_@@_restore_tmp_tl
        \use:c { toggle \l_@@_restore_tmp_tl } { blx@refcontext }
        \@@_prop_get:nnN { \l_postnotes_print_note_id_tl }
          { biblatex@refcontext } \l_@@_restore_tmp_tl
        \blx@edef@refcontext { \l_@@_restore_tmp_tl }
      }
%    \end{macrocode}
% Auxiliary functions.
%
% \begin{macro}{\@@_biblatex_endrefcontext_local:}
%   Replicate the job of \cs{endrefcontext}, but with local effects,
%   restrained to the group of \cs{printpostnotes}.
%    \begin{macrocode}
    \cs_new_protected:Npn \@@_biblatex_endrefcontext_local:
      {
        \togglefalse { blx@refcontext }
        \tl_clear:N \blx@refcontext@labelprefix
        \tl_clear:N \blx@refcontext@labelprefix@real
        \tl_set:Ne \blx@refcontext@sortingtemplatename { \blx@sorting }
        \tl_set:Nn \blx@refcontext@sortingnamekeytemplatename { global }
        \tl_set:Nn \blx@refcontext@uniquenametemplatename { global }
        \tl_set:Nn \blx@refcontext@labelalphanametemplatename { global }
        \blx@edef@refcontext
          {
            \blx@refcontext@sortingtemplatename /
            \blx@refcontext@sortingnamekeytemplatename /
            /
            \blx@refcontext@uniquenametemplatename /
            \blx@refcontext@labelalphanametemplatename
          }
      }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_biblatex_citereset_local:}
%   Replicate the job of \cs{citereset}, but with local effects, restrained to
%   the group of \cs{printpostnotes}.
%    \begin{macrocode}
    \cs_new_protected:Npn \@@_biblatex_citereset_local:
      {
%    \end{macrocode}
% \noindent
% {\em\scriptsize\verb|\global\cslet{blx@bsee@\the\c@refsection}\@empty|} \\
% {\em\scriptsize\verb|\global\cslet{blx@fsee@\the\c@refsection}\@empty|}
%    \begin{macrocode}
        \tl_clear:c { blx@bsee@ \int_use:N \c@refsection }
        \tl_clear:c { blx@fsee@ \int_use:N \c@refsection }
%    \end{macrocode}
% {\em\scriptsize\verb|\blx@ibidreset@force|}
%    \begin{macrocode}
        \undef \blx@lastkey@text
        \undef \blx@lastkey@foot
%    \end{macrocode}
% {\em\scriptsize\verb|\blx@idemreset@force|}
%    \begin{macrocode}
        \undef \blx@lasthash@text
        \undef \blx@lasthash@foot
%    \end{macrocode}
% {\em\scriptsize\verb|\blx@opcitreset@force|}
%    \begin{macrocode}
        \clist_map_inline:Nn \blx@trackhash@text
          { \csundef { blx@lastkey@text@ ##1 } }
        \tl_clear:N \blx@trackhash@text
        \clist_map_inline:Nn \blx@trackhash@foot
          { \csundef { blx@lastkey@foot@ ##1 } }
        \tl_clear:N \blx@trackhash@foot
%    \end{macrocode}
% {\em\scriptsize\verb|\blx@loccitreset@force|}
%    \begin{macrocode}
        \clist_map_inline:Nn \blx@trackkeys@text
          { \csundef { blx@lastnote@text@ ##1 } }
        \tl_clear:N \blx@trackkeys@text
        \clist_map_inline:Nn \blx@trackkeys@foot
          { \csundef { blx@lastnote@foot@ ##1 } }
        \tl_clear:N \blx@trackkeys@foot
%    \end{macrocode}
% {\em\scriptsize{}and all of them do:}
%    \begin{macrocode}
        \cs_set_eq:NN \blx@lastmpfn \z@
      }
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
  }
%    \end{macrocode}
%
% \pkg{biblatex}'s \texttt{refsections}, contrary to \texttt{refsegment}s and
% \texttt{refcontext}s which are handled in the \LaTeX{} side of things (as
% far as I can tell), need to go through \texttt{biber}, and must have correct
% corresponding citation data written to the \file{.bcf} file.  And the way
% \cs{refsection} is implemented presumes each section is only ever begun once
% (fair\dots{}), thus making it difficult to ``reopen'' it, or append new
% citations to it later on, when the notes are printed.  The start of a
% \texttt{refsection} must be registered on the \file{.bcf} file, and this is
% done by \cs{refsection} (and its auxiliary functions).  However, a number of
% its characteristics make things particularly difficult for the purpose at
% hand: i) it unconditionally sets a label for the section which, of course,
% cannot be done twice; and, critically, ii) the optional argument of the
% environment (which receives the \meta{resources}) is used to set a local
% assignment to \cs{blx@bibfiles}, based on which the relevant information is
% written to the \file{.bcf} file, and when the group closes the information
% is gone.  My best attempt is below but it is not good.  It feels a wrong
% approach to ``go around'' the intended use of \cs{refsection} so much, and
% it can't handle at all its optional argument, for the reasons above.  It's
% also incomplete, since it does not handle restoring
% \cs{l_@@_biblatex_orig_refsection_tl}.
%
%    \begin{macrocode}
\AddToHook { package/biblatex/after }
  {
    \tl_new:N \l_@@_biblatex_orig_refsection_tl
    \tl_new:N \g_@@_biblatex_prev_refsection_tl
    \AddToHook { postnotes/print/begin } [ postnotes ]
      {
        \tl_set:Ne \l_@@_biblatex_orig_refsection_tl
          { \int_use:N \c@refsection }
        \tl_gset:Ne \g_@@_biblatex_prev_refsection_tl
          { \l_@@_biblatex_orig_refsection_tl }
     }
    \AddToHook { postnotes/print/note/begin } [ postnotes ]
      {
        \@@_prop_get:nnN { \l_postnotes_print_note_id_tl }
          { biblatex@refsection } \l_@@_restore_tmp_tl
        \tl_if_eq:NNF
          \l_@@_restore_tmp_tl
          \g_@@_biblatex_prev_refsection_tl
          {
            \int_set:Nn \c@blx@maxsection
              { \l_@@_restore_tmp_tl - 1 }
            \tl_gset_eq:NN \g_@@_biblatex_prev_refsection_tl
              \l_@@_restore_tmp_tl
            \group_begin:
            \cs_set_eq:NN \label \use_none:n
            \cs_set_eq:NN \blx@info \use_none:n
            \blx@endrefsection
            \refsection
            \group_end:
          }
      }
  }
%    \end{macrocode}
%
%    \begin{macrocode}
%</gobble>
%    \end{macrocode}
%
%
% \subsection*{\pkg{zref-user}}
%
% \begin{macro}{\l_@@_note_zlabel_tl}
%   Even though the \opt{zlabel} option is provided only when \pkg{zref-user}
%   is loaded, \cs{l_@@_note_zlabel_tl} must be unconditionally defined, since
%   it is presumed to exist by \cs{@@_set_user_labels:}.
%    \begin{macrocode}
\tl_new:N \l_@@_note_zlabel_tl
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
\AddToHook { package/zref-user/after }
  {
%    \end{macrocode}
% Provide \opt{zlabel} option.
%    \begin{macrocode}
    \keys_define:nn { postnotes/note }
      {
        zlabel .tl_set:N = \l_@@_note_zlabel_tl ,
        zlabel .value_required:n = true ,
      }
%    \end{macrocode}
%
% \begin{macro}[int]{\postnotezref}
%   Provide \cs{postnotezref}.
%   \begin{syntax}
%     \cs{postnotezref}\meta{*}\marg{label}
%   \end{syntax}
%    \begin{macrocode}
    \NewDocumentCommand \postnotezref { s m }
      { \@@_note_zref:nn {#1} {#2} }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_note_zref:nn}
%   The internal version of \cs{postnotezref}.
%   \begin{syntax}
%     \cs{@@_note_zref:nn} \Arg{star bool} \Arg{label}
%   \end{syntax}
%    \begin{macrocode}
    \cs_new_protected:Npn \@@_note_zref:nn #1#2
      {
        \group_begin:
        \@@_typeset_mark_wrapper:n
          {
            \bool_lazy_all:nTF
              {
                { ! #1 }
                { \l_@@_hyperlink_bool }
                { \l_@@_zrefhyperref_bool }
              }
              {
                \hyperlink
                  { \zref@extractdefault {#2} { anchor } { } }
                  { \@@_make_mark:nnn { \zref{#2} } { } { } }
              }
              { \@@_make_mark:nnn { \zref{#2} } { } { } }
          }
        \group_end:
      }
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\bool_new:N \l_@@_zrefhyperref_bool
\AddToHook { package/zref-hyperref/after }
  { \bool_set_true:N \l_@@_zrefhyperref_bool }
%    \end{macrocode}
%
%
% \subsection*{\pkg{zref-clever}}
%
%    \begin{macrocode}
\AddToHook { package/zref-clever/after }
  {
    \zcsetup
      {
        countertype = { postnote = endnote } ,
        countertype = { postnotetext = endnote } ,
      }
    \AddToHook { postnotes/print/begin } [ postnotes ]
      { \zcsetup { counterresetby = { postnotetext = postnotesection } } }
  }
%    \end{macrocode}
%
%
% \subsection*{\pkg{zref-check}}
%
%    \begin{macrocode}
\AddToHook { package/zref-check/after }
  {
    \IfPackageAtLeastTF { zref-check } { 2022-07-05 }
      {
        \AddToHook { postnotes/note/store } [ postnotes ]
          {
            \prop_gput:cne { \@@_data_name:e { \l_postnotes_note_id_tl } }
              { zref-check@abschap } { \int_use:N \c@zc@abschap }
            \prop_gput:cne { \@@_data_name:e { \l_postnotes_note_id_tl } }
              { zref-check@abssec } { \int_use:N \c@zc@abssec }
          }
        \AddToHook { postnotes/print/note/begin } [ postnotes ]
          {
            \@@_prop_get:nnN { \l_postnotes_print_note_id_tl }
              { zref-check@abschap } \l_@@_restore_tmp_tl
            \int_set:Nn \c@zc@abschap { \l_@@_restore_tmp_tl }
            \@@_prop_get:nnN { \l_postnotes_print_note_id_tl }
              { zref-check@abssec } \l_@@_restore_tmp_tl
            \int_set:Nn \c@zc@abssec { \l_@@_restore_tmp_tl }
          }
      }
      { }
  }
%    \end{macrocode}
%
%
% \subsection*{\pkg{amsmath}}
%
%    \begin{macrocode}
\AddToHook { package/amsmath/after }
  {
%    \end{macrocode}
% Testing for \cs{ifmeasuring@} is sufficient to get things right for the
% measuring passes in math environments.
%    \begin{macrocode}
    \AddToHook { postnotes/note/inhibit } [ postnotes ]
      {
        \legacy_if:nT { measuring@ }
          {
            \bool_set_true:N \l_@@_inhibit_note_bool
            \bool_set_true:N \l_@@_print_plain_mark_bool
            \bool_set_true:N \l_@@_print_plain_mark_stepcounter_bool
          }
      }
%    \end{macrocode}
% However, the \cs{text} macro, defined by \pkg{amstext} (required by
% \pkg{amsmath}), poses problems if its own.  Despite my best efforts, I could
% not salvage things from the use of \cs{mathchoice} and the redefinitions of
% \cs{setcounter} and \cs{addtocounter} performed by \pkg{amstext}.  Setting
% \cs{l_@@_maybe_multi_bool} when \texttt{firstchoice@} is \texttt{false}
% grants us a working situation for display style.  But the use of
% \cs{postnote} inside \cs{text} (and, if \pkg{amsmath} is loaded,
% \cs{textnormal}, \cs{textup}, etc.) in inline math environments is not
% supported.  If a note really needs to be there, one can use the \opt{nomark}
% option and \cs{postnoteref}.  Things should work in text mode and in display
% style.  For some related discussion with regard to footnotes,
% see \url{https://tex.stackexchange.com/a/82820} and, in particular, Barbara
% Beeton's comment: ``This is certainly bravura code.  I do hope it doesn't
% result in a request to add \cs{footnote} capabilities to \pkg{amsmath}'s
% multi-line display facilities.  (The answer will almost certainly be "no".
% We agree with Kopka \& Daly.)''
%    \begin{macrocode}
    \AddToHook { postnotes/note/begin } [ postnotes ]
      {
        \legacy_if:nF { firstchoice@ }
          { \bool_set_true:N \l_@@_maybe_multi_bool }
      }
  }
%    \end{macrocode}
%
%
% \subsection*{\pkg{csquotes}}
%
%    \begin{macrocode}
\AddToHook { package/csquotes/after }
  {
    \bool_new:N \l_@@_csquotes_measuring_bool
    \BlockquoteDisable
      { \bool_set_true:N \l_@@_csquotes_measuring_bool }
    \AddToHook { postnotes/note/inhibit } [ postnotes ]
      {
        \bool_if:NT \l_@@_csquotes_measuring_bool
          {
            \bool_set_true:N \l_@@_inhibit_note_bool
            \bool_set_true:N \l_@@_print_plain_mark_bool
            \bool_set_true:N \l_@@_print_plain_mark_stepcounter_bool
          }
      }
  }
%    \end{macrocode}
%
%
% \subsection*{\pkg{tabularx}}
%
% For the identification of the trial passes in \pkg{tabularx}, see
% \url{https://tex.stackexchange.com/a/640035} (including discussion in the
% comments, thanks \contributor{David Carlisle}), and also
% \url{https://tex.stackexchange.com/a/227155} and
% \url{https://tex.stackexchange.com/a/352134}.
%
%    \begin{macrocode}
\AddToHook { package/tabularx/after }
  {
    \bool_new:N \l_@@_tabularx_inside_env_bool
    \AddToHook { env/tabularx/begin } [ postnotes ]
      {
        \bool_set_true:N \l_@@_tabularx_inside_env_bool
        \cs_set_eq:NN \@@_tabularx_saved_write:Nn \write
      }
    \AddToHook { postnotes/note/inhibit } [ postnotes ]
      {
        \bool_lazy_and:nnT
          { \l_@@_tabularx_inside_env_bool }
          { ! \cs_if_eq_p:NN \write \@@_tabularx_saved_write:Nn }
          {
            \bool_set_true:N \l_@@_inhibit_note_bool
            \bool_set_true:N \l_@@_print_plain_mark_bool
            \bool_set_true:N \l_@@_print_plain_mark_stepcounter_bool
          }
      }
  }
%    \end{macrocode}
%
%
% \subsection*{\pkg{tabularray}}
%
%    \begin{macrocode}
\AddToHook { package/tabularray/after }
  {
%    \end{macrocode}
% Since version \texttt{2023A}, from 2023-03-01, \pkg{tabularray} offers the
% \cs{lTblrMeasuringBool} which is true when measuring and false otherwise.
% See \url{https://tex.stackexchange.com/q/675818}
% and \url{https://github.com/lvjr/tabularray/issues/179} (thanks
% \contributor{Ulrike Fischer}).
%    \begin{macrocode}
    \bool_if_exist:NTF \lTblrMeasuringBool
      {
%    \end{macrocode}
% I'd be inclined to restrict the inhibition effect to known \pkg{tabularray}
% environments to ``keep things under control''.  However this is a dedicated
% and public boolean, and users can create arbitrary new \pkg{tabularray}
% environments with \cs{NewTblrEnviron}, which we either wouldn't catch or
% have to provide an user interface for.  So, for the time being, let's trust
% this boolean won't be misused by third-parties or users.  Note that setting
% \cs{l_@@_print_plain_mark_stepcounter_bool} to true presumes
% \pkg{tabularray}'s \texttt{counter} module is enabled.  But, since this is
% the only way to get the measuring right in this context if there is more
% than one \cs{postnote} inside a given table, pkg{postnotes} expects and
% requires the \texttt{counter} module.
%    \begin{macrocode}
        \AddToHook { postnotes/note/inhibit } [ postnotes ]
          {
            \bool_if:NT \lTblrMeasuringBool
              {
                \bool_set_true:N \l_@@_inhibit_note_bool
                \bool_set_true:N \l_@@_print_plain_mark_bool
                \bool_set_true:N \l_@@_print_plain_mark_stepcounter_bool
              }
          }
      }
      {
%    \end{macrocode}
% If the new boolean is not yet available, we use \cs{@@_verify_multipass:N}
% to distinguish a trial/measure pass from the final one.
%    \begin{macrocode}
        \clist_map_inline:nn
          {
            tblr , longtblr , talltblr , booktabs ,
            longtabs , talltabs , +array
          }
          {
            \AddToHook { env/#1/begin } [ postnotes ]
              { \bool_set_true:N \l_@@_maybe_multi_bool }
          }
      }
  }
%    \end{macrocode}
%
%
% \section{Languages}
% \label{sec:languages}
%
% \begin{macro}[int]
%   {
%     \pntitle ,
%     \pnhdnotes ,
%     \pnhdtopage ,
%     \pnhdtopages ,
%   }
%   Set of language specific user variables.  They are used in the default
%   value of the \opt{heading} option and in \cs{pnheaderdefault} which,
%   ultimately, is also used in the same place.
%    \begin{macrocode}
\tl_new:N \pntitle
\tl_new:N \pnhdnotes
\tl_new:N \pnhdtopage
\tl_new:N \pnhdtopages
\tl_set:Nn \pntitle { Notes }
\tl_set:Nn \pnhdnotes { Notes }
\tl_set:Nn \pnhdtopage { to~page }
\tl_set:Nn \pnhdtopages { to~pages }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\@@_define_language:nn}
%   Defines language specific values for \meta{postnote language} by storing a
%   set of assignments for the language specific variables in \meta{setup}.
%   \meta{postnote language} is an internal name, typically the ``main'' name
%   of the language, based on which we can set specific \pkg{babel} or
%   \pkg{polyglossia} languages or variants.
%     \begin{syntax}
%       \cs{@@_define_language:nn} \Arg{postnote language} \Arg{setup}
%     \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_define_language:nn #1#2
  {
    \tl_new:c { g_@@_language_ #1 _tl }
    \tl_gset:cn { g_@@_language_ #1 _tl } {#2}
  }
%    \end{macrocode}
% \end{macro}
%
%
% For \pkg{babel} we use the new hook system, it's clean, and avoids the
% \cs{addto} pitfalls.  The appropriate hook to use is
% \texttt{babel/\meta{language}/beforeextras} so that users can override it
% with a traditional
% \texttt{\textbackslash{}addto\textbackslash{}extras\meta{language}}.
%
% Note that, for \pkg{babel}, the captions are currently handled in two
% different ways -- the ``old way'' and the ``new way'' -- and which of them
% is used depends on the language.  Most still use the ``old way'', but the
% problem is that it is not universal.  And the ``new way'' uses a different
% naming scheme -- \texttt{\textbackslash{}\meta{language}\meta{caption}},
% which is meant to be set with \cs{setlocalecaption}, and not suitable for
% our needs.  The \texttt{\textbackslash{}extras\meta{language}} macros are
% meant for ``arbitrary'' code to be run when the language is selected, which
% is what we want.  The captions used to work in the same way, but no longer
% for languages which use the ``new way''.
%
% Note also that there seems to exist some qualms about \pkg{babel}'s
% \cs{addto}.  A number of packages define their own versions of it.  Do so at
% least \pkg{varioref} (probably the original), \pkg{backref}, and
% \pkg{cleveref}.  The latter comments that \cs{addto} is ``flawed''.
% \pkg{babel} itself comments the definition recognizing that there is an
% ``inconsistency'': depending on the case, the operation will be either local
% or global.  This is documented in the manual, which explains this
% inconsistent behavior is preserved for backward compatibility, and
% recommends \pkg{etoolbox}'s facilities if available.  \pkg{polyglossia} also
% recommends \pkg{etoolbox}'s \cs{gappto}.  All in all, if there's need to use
% the traditional way instead of the new hooks, just rely on \texttt{expl3}
% and use \cs{tl_gput_right:Nn}.
%
% \begin{macro}{\@@_set_babel_language:nn}
%   Sets \meta{babel language} to execute the setup defined by
%   \cs{@@_define_language:nn} for \meta{postnote language} at the
%   \texttt{babel/\meta{language}/beforeextras} hook.
%     \begin{syntax}
%       \cs{@@_set_babel_language:nn} \Arg{babel language} \Arg{postnote language}
%     \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_set_babel_language:nn #1#2
  {
    \ActivateGenericHook { babel/#1/beforeextras }
    \exp_args:Nnv \AddToHook { babel/#1/beforeextras }
      { g_@@_language_ #2 _tl }
  }
%    \end{macrocode}
% \end{macro}
%
%
% \pkg{polyglossia} uses a similar set of macros for setting up languages as
% \pkg{babel} does.  However, the
% \texttt{\textbackslash{}blockextras@\meta{language}} macros are
% unfortunately internal (despite what the manual says, that's what the code
% does), thus requiring \cs{makeatletter}/\cs{makeatother} for user
% configuration, which would be an inconvenience.  On the other hand,
% \pkg{polyglossia}'s \texttt{\textbackslash{}captions\meta{language}} works
% as in \pkg{babel}'s ``old way'', meaning it is just a ``hook'' to which we
% can append some code.  So we use
% \texttt{\textbackslash{}captions\meta{language}} for \pkg{polyglossia}.
% Things may complicate here if there's need to set up different values for
% different language variants, since the hooks available are all necessarily
% internal, but I doubt we'll ever need variants for these simple strings.
%
% \begin{macro}{\@@_set_polyglossia_language:nn}
%   Sets \meta{polyglossia language} to execute the setup defined by
%   \cs{@@_define_language:nn} for \meta{postnote language} at the
%   \pkg{polyglossia} \texttt{\textbackslash{}captions\meta{language}} hook.
%     \begin{syntax}
%       \cs{@@_set_polyglossia_language:nn} \Arg{polyglossia language}
%       ~~\Arg{postnote language}
%     \end{syntax}
%    \begin{macrocode}
\cs_new_protected:Npn \@@_set_polyglossia_language:nn #1#2
  {
    \AddToHook { package/polyglossia/after }
      {
        \exp_args:Nnv \csgappto { captions #1 }
          { g_@@_language_ #2 _tl }
      }
  }
%    \end{macrocode}
% \end{macro}
%
%
% \subsection*{English}
%
%    \begin{macrocode}
\@@_define_language:nn { english }
  {
    \tl_set:Nn \pntitle     { Notes }
    \tl_set:Nn \pnhdnotes   { Notes }
    \tl_set:Nn \pnhdtopage  { to~page }
    \tl_set:Nn \pnhdtopages { to~pages }
  }
\@@_set_babel_language:nn { english }    { english }
\@@_set_babel_language:nn { british }    { english }
\@@_set_babel_language:nn { american }   { english }
\@@_set_babel_language:nn { canadian }   { english }
\@@_set_babel_language:nn { australian } { english }
\@@_set_babel_language:nn { newzealand } { english }
\@@_set_babel_language:nn { UKenglish }  { english }
\@@_set_babel_language:nn { USenglish }  { english }
\@@_set_polyglossia_language:nn { english } { english }
%    \end{macrocode}
%
%
% \subsection*{Portuguese}
%
%    \begin{macrocode}
\@@_define_language:nn { portuguese }
  {
    \tl_set:Nn \pntitle     { Notas }
    \tl_set:Nn \pnhdnotes   { Notas }
    \tl_set:Nn \pnhdtopage  { da~página }
    \tl_set:Nn \pnhdtopages { das~páginas }
  }
\@@_set_babel_language:nn { portuguese } { portuguese }
\@@_set_babel_language:nn { brazilian }  { portuguese }
\@@_set_babel_language:nn { portuges }   { portuguese }
\@@_set_babel_language:nn { brazil }     { portuguese }
\@@_set_polyglossia_language:nn { portuguese } { portuguese }
%    \end{macrocode}
%
%
% \subsection*{French}
%
% French localization validated by \contributor{\username{Pika78}} at
% \githubissue{1}.
%
% \pkg{babel-french} also has \file{.ldf}s for \texttt{francais},
% \texttt{frenchb}, and \texttt{canadien}, but they are deprecated as options
% and, if used, they fall back to either \texttt{french} or \texttt{acadian}.
%
%    \begin{macrocode}
\@@_define_language:nn { french }
  {
    \tl_set:Nn \pntitle     { Notes }
    \tl_set:Nn \pnhdnotes   { Notes }
    \tl_set:Nn \pnhdtopage  { de~la~page }
    \tl_set:Nn \pnhdtopages { des~pages }
  }
\@@_set_babel_language:nn { french }  { french }
\@@_set_babel_language:nn { acadian } { french }
\@@_set_polyglossia_language:nn { french } { french }
%    \end{macrocode}
%
%
% \subsection*{German}
%
% German localization provided by \contributor{Herbert Voß} at
% \githubissue{2}.
%
% \pkg{babel-german} also has \file{.ldf}s for \texttt{germanb} and
% \texttt{ngermanb}, but they are deprecated as options and, if used, they
% fall back respectively to \texttt{german} and \texttt{ngerman}.
%
%    \begin{macrocode}
\@@_define_language:nn { german }
  {
    \tl_set:Nn \pntitle     { Endnoten }
    \tl_set:Nn \pnhdnotes   { Endnoten }
    \tl_set:Nn \pnhdtopage  { zu~Seite }
    \tl_set:Nn \pnhdtopages { zu~Seiten }
  }
\@@_set_babel_language:nn { german }       { german }
\@@_set_babel_language:nn { ngerman }      { german }
\@@_set_babel_language:nn { austrian }     { german }
\@@_set_babel_language:nn { naustrian }    { german }
\@@_set_babel_language:nn { swissgerman }  { german }
\@@_set_babel_language:nn { nswissgerman } { german }
\@@_set_polyglossia_language:nn { german } { german }
%    \end{macrocode}
%
%
%    \begin{macrocode}
%</package>
%    \end{macrocode}
%
%
% \PrintIndex
%
%
