%
% Copyright (c) 2021-2025 Zeping Lee
% Released under the MIT License.
% Repository: https://github.com/zepinglee/citeproc-lua
%

% ## Citation commands

\DeclareDocumentCommand \cite { s o o m }
  {
    \IfBooleanTF {#1}
      {
        \bool_if:NTF \l__csl_note_bool
          { \__csl_cite_in_text:nnnn {#2} {#3} {#4} { } }
          { \__csl_cite_in_text:nnnn {#2} {#3} {#4} { suppress-author } }
      }
      {
        \bool_if:NTF \l__csl_note_bool
          { \__csl_cite_note:nnnn {#2} {#3} {#4} { } }
          { \__csl_cite_in_text:nnnn {#2} {#3} {#4} { } }
      }
  }

\NewCommandCopy \autocite \cite

\NewDocumentCommand \parencite { s o o m }
  {
    \IfBooleanTF {#1}
      {
        \bool_if:NTF \l__csl_note_bool
          { \__csl_cite_in_text:nnnn {#2} {#3} {#4} { } }
          { \__csl_cite_in_text:nnnn {#2} {#3} {#4} { suppress-author } }
      }
      { \__csl_cite_parens:nnn {#2} {#3} {#4} }
  }

\NewDocumentCommand \citep { o o m }
  { \__csl_cite_parens:nnn {#1} {#2} {#3} }

\NewDocumentCommand \textcite { o o m }
  { \__csl_text_cite:nnn {#1} {#2} {#3} }

\NewDocumentCommand \citet { o o m }
  { \__csl_text_cite:nnn {#1} {#2} {#3} }

\NewDocumentCommand \footcite { o o m }
  { \__csl_cite_note:nnnn {#1} {#2} {#3} { } }


% \cites[⟨prenote⟩][⟨postnote⟩]{⟨key⟩}...[⟨prenote⟩][⟨postnote⟩]{⟨key⟩}
\NewDocumentCommand \cites { }
  { \__csl_cites: }

\NewDocumentCommand \parencites { }
  { \__csl_cites: }

\NewDocumentCommand \citeauthor { o o m }
  { \__csl_cite_in_text:nnnn {#1} {#2} {#3} { author-only } }

\NewDocumentCommand \citeyear { o o m }
  { \__csl_cite_in_text:nnnn {#1} {#2} {#3} { cite-year } }


% Suppresses the author (from `natbib`).
\NewDocumentCommand \citeyearpar { o o m }
  { \__csl_cite_in_text:nnnn {#1} {#2} {#3} { suppress-author } }

\NewDocumentCommand \fullcite { o o m }
  { \__csl_cite_in_text:nnnn {#1} {#2} {#3} { full-cite } }


\seq_new:N \l__csl_cite_keys_seq
\seq_new:N \l__csl_citation_items_seq
\prop_new:N \l__csl_citation_properties_prop
\bool_new:N \l__csl_citation_unsorted_bool
\prop_new:N \l__csl_citation_info_prop

% #1: prenote
% #2: postnote
% #3: cite keys
% #4: mode
\cs_new:Npn \__csl_cite_in_text:nnnn #1#2#3#4
  {
    \tl_if_blank:nTF {#3}
      { \__csl_print_undefined_citation:n {#3} }
      {
        \__csl_cite_init:
        \__csl_collect_citation_items:nnn {#1} {#2} {#3}
        \__csl_process_citation_info:
        \prop_put:Nnn \l__csl_citation_properties_prop { noteIndex } { 0 }
        \tl_if_empty:nF {#4}
          {
            \prop_put:Nnn \l__csl_citation_properties_prop { mode } {#4}
          }
        \__csl_make_citation:
      }
  }

% #1: prenote
% #2: postnote
% #3: cite keys
% #4: mode
\cs_new:Npn \__csl_cite_note:nnnn #1#2#3#4
  {
    \bool_if:NTF \l__csl_in_note_bool
      {
        \tl_if_blank:nTF {#3}
          { \__csl_print_undefined_citation:n {#3} }
          {
            \__csl_cite_init:
            \__csl_collect_citation_items:nnn {#1} {#2} {#3}
            \__csl_process_citation_info:
            \tl_if_empty:nF {#4}
              {
                \prop_put:Nnn \l__csl_citation_properties_prop { mode } {#4}
              }
            \__csl_make_citation:
          }
      }
      {
        \footnote
          {
            \tl_if_blank:nTF {#3}
              { \__csl_print_undefined_citation:n {#3} }
              {
                \__csl_cite_init:
                \__csl_collect_citation_items:nnn {#1} {#2} {#3}
                \__csl_process_citation_info:
                \tl_if_empty:nF {#4}
                  {
                    \prop_put:Nnn \l__csl_citation_properties_prop { mode } {#4}
                  }
                \__csl_make_citation:
              }
          }
      }
  }


% #1: prenote
% #2: postnote
% #3: cite keys
\cs_new:Npn \__csl_cite_parens:nnn #1#2#3
  {
    \bool_if:NTF \l__csl_note_bool
      { ( \__csl_cite_in_text:nnnn {#1} {#2} {#3} { } ) }
      { \__csl_cite_in_text:nnnn {#1} {#2} {#3} { } }
  }


\cs_new:Npn \__csl_text_cite:nnn #1#2#3
  {
    \bool_if:NTF \l__csl_note_bool
      {
        % In note styles, the authors are printed in-text followed by a note.
        \__csl_cite_in_text:nnnn {#1} {#2} {#3} { author-only }
        \__csl_cite_note:nnnn {#1} {#2} {#3} { }
      }
      { \__csl_cite_in_text:nnnn {#1} {#2} {#3} { composite } }
  }


\bool_new:N \l__csl_multi_cite_bool

\cs_new:Npn \__csl_cites:
  {
    \__csl_cite_init:
    \bool_set_true:N \l__csl_multi_cite_bool
    \__csl_next_cites:nnn
  }

\NewDocumentCommand \__csl_next_cites:nnn { o o g }
  {
    \tl_if_novalue:nTF {#3}
      {
        \bool_if:NTF \l__csl_note_bool
          {
            \footnote
              {
                \__csl_process_citation_info:
                \__csl_make_citation:
              }
          }
          {
            \__csl_process_citation_info:
            \__csl_make_citation:
          }
      }
      {
        \__csl_collect_citation_items:nnn {#1} {#2} {#3}
        \__csl_next_cites:nnn
      }
  }


\cs_new:Npn \__csl_cite_init:
  {
    \bool_set_false:N \l__csl_multi_cite_bool
    \prop_clear:N \l__csl_citation_info_prop
    \seq_clear:N \l__csl_cite_keys_seq
    \seq_clear:N \l__csl_citation_items_seq
    \prop_clear:N \l__csl_citation_properties_prop
    \bool_set_false:N \l__csl_citation_unsorted_bool
    \tl_clear:N \l__csl_cite_prefix_tl
    \tl_clear:N \l__csl_cite_suffix_tl
  }


% Appends the cite key into \l__csl_cite_keys_seq and cite-items into
% \l__csl_citation_items_seq
% #1, #2: prenote/postnote
% #3: keys
\cs_new:Npn \__csl_collect_citation_items:nnn #1#2#3
  {
    \tl_if_novalue:nTF {#2}
      {
        \tl_if_novalue:nTF {#1}
          { \__csl_process_cite_input_aux:nnn { } { } {#3} }
          { \__csl_process_cite_input_aux:nnn { } {#1} {#3} }
      }
      { \__csl_process_cite_input_aux:nnn {#1} {#2} {#3} }
  }

\cs_new:Npn \__csl_process_cite_input_aux:nnn #1#2#3
  % #1: prenote, #2: postnote, #3: keys
  % Return: "{id={ITEM-1},{locator=6},...}, {id={ITEM-2},...}, ..."
  {
    \int_zero:N \l_tmpa_int
    \clist_map_inline:nn {#3}
      {
        \int_incr:N \l_tmpa_int
        \seq_put_right:Nn \l__csl_cite_keys_seq {##1}
        \int_compare:nNnTF { \l_tmpa_int } = { 1 }
          { \__csl_process_cite_item:nnn {#1} {#2} {##1} }
          { \__csl_process_cite_item:nnn { } { } {##1} }
      }
  }


\prop_new:N \l__csl_cite_item_prop

% Collect citation items into \l__csl_citation_items_seq
% Append "{id={ITEM},locator={42},label={page}}" into \l__csl_citation_items_seq
% #1: prenote
% #2: postnote
% #3: key
\cs_new:Npn \__csl_process_cite_item:nnn #1#2#3
  {
    \prop_clear:N \l__csl_cite_item_prop
    \prop_put:Nnn \l__csl_cite_item_prop { id } {#3}
    % \bool_if:T \l__csl_suppress_author_bool
    %   { \prop_put:Nnn \l__csl_cite_item_prop { suppress-author } { true } }
    % \bool_if:T \l__csl_author_only_bool
    %   { \prop_put:Nnn \l__csl_cite_item_prop { author-only } { true } }
    \tl_clear:N \l__csl_cite_prefix_tl
    \tl_clear:N \l__csl_cite_suffix_tl
    \tl_if_empty:nF {#1}
      {
        \tl_set:Nn \l__csl_cite_prefix_tl {#1}
        \tl_put_right:NV \l__csl_cite_prefix_tl \l__csl_prefix_separator_tl
      }
    \tl_if_empty:nF {#2}
      {
        \tl_if_in:nnTF {#2} { = }
          { \keys_set:nn { csl / cite-item } {#2} }
          {
            \regex_match:nnTF { \d+ } {#2}
              { \__csl_set_locator:nn { page } {#2} }
              {
                \tl_set:Nn \l__csl_cite_suffix_tl {#2}
                \tl_put_left:NV \l__csl_cite_suffix_tl \l__csl_suffix_separator_tl
              }
          }
      }
    % The affixes are treated as cite item affixes in a multi-cite command
    % (like `\cites`). Otherwise they are citation affixes.
    \bool_if:NTF \l__csl_multi_cite_bool
      {
        \tl_if_empty:NF \l__csl_cite_prefix_tl
          { \prop_put:NnV \l__csl_cite_item_prop { prefix } \l__csl_cite_prefix_tl }
        \tl_if_empty:NF \l__csl_cite_suffix_tl
          { \prop_put:NnV \l__csl_cite_item_prop { suffix } \l__csl_cite_suffix_tl }
      }
      {
        \tl_if_empty:NF \l__csl_cite_prefix_tl
          { \prop_put:NnV \l__csl_citation_properties_prop { prefix } \l__csl_cite_prefix_tl }
        \tl_if_empty:NF \l__csl_cite_suffix_tl
          { \prop_put:NnV \l__csl_citation_properties_prop { suffix } \l__csl_cite_suffix_tl }
      }
    \__csl_serialize_prop:NN \l__csl_cite_item_prop \l_tmpa_tl
    \tl_put_left:NV \l_tmpa_tl { \c_left_brace_str }
    \tl_put_right:NV \l_tmpa_tl { \c_right_brace_str }
    \seq_put_right:NV \l__csl_citation_items_seq \l_tmpa_tl
  }

\cs_new:Npn \__csl_set_locator:nn #1#2
  {
    \tl_if_empty:nTF {#2}
      { \msg_warning:nnn { citation-style-language } { empty-locator } {#1} }
      {
        \prop_put:Nnn \l__csl_cite_item_prop { label } {#1}
        \prop_put:Nnn \l__csl_cite_item_prop { locator } {#2}
      }
  }

\msg_new:nnn { citation-style-language } { empty-locator }
  { Empty~ '#1'~ locator. }

\tl_new:N \l__csl_cite_prefix_tl
\tl_new:N \l__csl_cite_suffix_tl

\keys_define:nn { csl / cite-item }
  {
    prefix          .tl_set:N = \l__csl_cite_prefix_tl,
    suffix          .tl_set:N = \l__csl_cite_suffix_tl,
    locator         .prop_put:N = \l__csl_cite_item_prop,
    label           .prop_put:N = \l__csl_cite_item_prop,
    suppress-author .prop_put:N = \l__csl_cite_item_prop,
    author-only     .prop_put:N = \l__csl_cite_item_prop,
    uris            .prop_put:N = \l__csl_cite_item_prop,
    % Locators.
    act             .code:n = { \__csl_set_locator:nn { act             } {#1} } ,
    appendix        .code:n = { \__csl_set_locator:nn { appendix        } {#1} } ,
    article         .code:n = { \__csl_set_locator:nn { article-locator } {#1} } ,
    book            .code:n = { \__csl_set_locator:nn { book            } {#1} } ,
    canon           .code:n = { \__csl_set_locator:nn { canon           } {#1} } ,
    chapter         .code:n = { \__csl_set_locator:nn { chapter         } {#1} } ,
    column          .code:n = { \__csl_set_locator:nn { column          } {#1} } ,
    elocation       .code:n = { \__csl_set_locator:nn { elocation       } {#1} } ,
    equation        .code:n = { \__csl_set_locator:nn { equation        } {#1} } ,
    figure          .code:n = { \__csl_set_locator:nn { figure          } {#1} } ,
    folio           .code:n = { \__csl_set_locator:nn { folio           } {#1} } ,
    issue           .code:n = { \__csl_set_locator:nn { issue           } {#1} } ,
    line            .code:n = { \__csl_set_locator:nn { line            } {#1} } ,
    note            .code:n = { \__csl_set_locator:nn { note            } {#1} } ,
    opus            .code:n = { \__csl_set_locator:nn { opus            } {#1} } ,
    page            .code:n = { \__csl_set_locator:nn { page            } {#1} } ,
    paragraph       .code:n = { \__csl_set_locator:nn { paragraph       } {#1} } ,
    part            .code:n = { \__csl_set_locator:nn { part            } {#1} } ,
    rule            .code:n = { \__csl_set_locator:nn { rule            } {#1} } ,
    scene           .code:n = { \__csl_set_locator:nn { scene           } {#1} } ,
    section         .code:n = { \__csl_set_locator:nn { section         } {#1} } ,
    sub-verbo       .code:n = { \__csl_set_locator:nn { sub-verbo       } {#1} } ,
    supplement      .code:n = { \__csl_set_locator:nn { supplement      } {#1} } ,
    table           .code:n = { \__csl_set_locator:nn { table           } {#1} } ,
    timestamp       .code:n = { \__csl_set_locator:nn { timestamp       } {#1} } ,
    title           .code:n = { \__csl_set_locator:nn { title-locator   } {#1} } ,
    verse           .code:n = { \__csl_set_locator:nn { verse           } {#1} } ,
    version         .code:n = { \__csl_set_locator:nn { version         } {#1} } ,
    volume          .code:n = { \__csl_set_locator:nn { volume          } {#1} } ,
    % Citation properties
    infix           .prop_put:N = \l__csl_citation_properties_prop,
    unsorted        .bool_set:N = \l__csl_citation_unsorted_bool
  }


\tl_new:N \l__csl_citation_id_tl
\tl_new:N \l__csl_cite_items_tl
\tl_new:N \l__csl_note_index_tl

% Load the cite keys and prepare:
%   - \l__csl_citation_id_tl
%   - \l__csl_citation_properties_prop
\cs_new:Npn \__csl_process_citation_info:
  {
    \__csl_process_citation_id:
    \__csl_get_note_index:
    \prop_put:NnV \l__csl_citation_properties_prop { noteIndex } \l__csl_note_index_tl
    \__csl_make_chapter_property:
    \__csl_add_back_ref_info:
    \bool_if:NT \l__csl_citation_unsorted_bool
      {
        \prop_put:Nnn \l__csl_citation_properties_prop { unsorted } { true }
      }
  }

\cs_new:Npn \__csl_make_chapter_property:
  {
    \int_if_exist:NT \c@chapter
      {
        \prop_put:Nne \l__csl_citation_properties_prop { chapterIndex }
          { \int_use:N \c@chapter }
      }
  }


\tl_new:N \l__csl_back_ref_tl
\prop_new:N \g__csl_back_ref_info_prop

% Provide empty \@currentHref when hyperref is not loaded.
% LaTeX2e 2023-06-01 defines `\@currentHref` in the kernel.
\cs_if_exist:NF \@currentHref
  { \cs_new:Npn \@currentHref { } }

% TODO: write backref info to .brf file or .aux file
\cs_new:Npn \__csl_add_back_ref_info:
  {
    % Same as the second argument of backref's \backcite
    % \thepage: the page number
    % \@currentlabel: the current label of the citation
    % \@currentHref: the current anchor name
    \tl_if_empty:NTF \@currentlabel
      {
        \tl_set:Ne \l__csl_back_ref_tl
          { { \thepage } { (document) } { Doc-Start } }
      }
      {
        \tl_set:Ne \l__csl_back_ref_tl
          { { \thepage } { \@currentlabel } { \@currentHref } }
      }
    \seq_map_inline:Nn \l__csl_cite_keys_seq
      {
        \prop_get:NnNTF \g__csl_back_ref_info_prop {##1} \l_tmpa_tl
          {
            \tl_put_right:Nn \l_tmpa_tl { , }
            \tl_put_right:NV \l_tmpa_tl \l__csl_back_ref_tl
            \prop_gput:NnV \g__csl_back_ref_info_prop {##1} \l_tmpa_tl
          }
          {
            \prop_gput:NnV \g__csl_back_ref_info_prop {##1}
              \l__csl_back_ref_tl
          }
      }
  }


\tl_new:N \l__csl_citation_info_tl
\tl_new:N \l__csl_citation_tl
\prop_new:N \g__csl_citations_prop

\tl_new:N \l__csl_citation_properties_tl

% Write citation info to aux and print the citation contents.
\cs_new:Npn \__csl_make_citation:
  {
    \prop_clear:N \l__csl_citation_info_prop
    % citationID
    \prop_put:NnV \l__csl_citation_info_prop { citationID } \l__csl_citation_id_tl
    % citationItems
    \__csl_serialize_seq:NN \l__csl_citation_items_seq \l__csl_cite_items_tl
    \prop_put:NnV \l__csl_citation_info_prop { citationItems } \l__csl_cite_items_tl
    % properties
    \__csl_serialize_prop:NN \l__csl_citation_properties_prop \l__csl_citation_properties_tl
    \prop_put:NnV \l__csl_citation_info_prop { properties } \l__csl_citation_properties_tl
    \__csl_serialize_prop:NN \l__csl_citation_info_prop \l__csl_citation_info_tl
    % Write to .aux file
    % \tl_show:N \l__csl_citation_info_tl
    \exp_args:NVV \__csl_write_aux_citation:nn \g__csl_ref_section_index_int \l__csl_citation_info_tl
    \bool_if:NT \l__csl_regression_test_bool
      { \tl_show:N \l__csl_citation_info_tl }
    % Print the citation string
    \prop_get:NVNTF \g__csl_citations_prop \l__csl_citation_id_tl
      \l__csl_citation_tl
      { \__csl_print_citation: }
      {
        \bool_if:NTF \l__csl_engine_initialized_bool
          {
            % \tl_show:N \l__csl_citation_info_tl
            % \tl_set:Nf \l__csl_citation_tl
            %   { \exp_args:NV \__csl_cite_aux:n \l__csl_citation_info_tl }
            \group_begin:
              \char_set_catcode_other:N \%
              \char_set_catcode_other:N \#
              \exp_args:NV \__csl_cite_aux:n \l__csl_citation_info_tl
              \__csl_print_citation:
            \group_end:
          }
          {
            \exp_args:Ne \__csl_print_undefined_citation:n
              { \seq_use:Nn \l__csl_cite_keys_seq { ,~ } }
          }
      }
  }

\cs_new:Npn \__csl_cite_aux:n #1
  {
    \bool_if:NT \g__csl_use_lua_module_bool
      { \lua_now:e { csl_citation_manager:cite("\lua_escape:n {#1}") } }
  }

% #1: seq
% #2: tl
\cs_new:Npn \__csl_serialize_seq:NN #1#2
  {
    \tl_clear:N #2
    \seq_map_inline:Nn #1
      {
        \tl_if_empty:NF #2
          { \tl_put_right:Nn #2 { , } }
        \tl_put_right:Nn #2 { ##1 }
      }
  }

% #1: prop
% #2: tl
\cs_new:Npn \__csl_serialize_prop:NN #1#2
  {
    \tl_clear:N #2
    \prop_map_inline:Nn #1
      {
        \tl_if_empty:NF #2
          { \tl_put_right:Nn #2 { , } }
        \tl_put_right:Nn #2 { ##1 = { ##2 } }
      }
  }

\tl_new:N \l__csl_cite_keys_tl
\tl_new:N \l__csl_citation_count_tl
\int_new:N \l__csl_citation_count_int
\prop_new:N \g__csl_citations_count_prop

% Load cite keys from `\l__csl_cite_keys_seq` and make `\l__csl_citation_id_tl`.
% Set \l__csl_citation_id_tl = "ITEM-1,ITEM-2@4".
\cs_new:Npn \__csl_process_citation_id:
  {
    \tl_set:Ne \l__csl_cite_keys_tl
      { \seq_use:Nn \l__csl_cite_keys_seq { , } }
    % \prop_show:N \g__csl_citations_count_prop
    % \tl_show:N \l__csl_cite_keys_tl
    \prop_get:NVNTF \g__csl_citations_count_prop \l__csl_cite_keys_tl
      \l__csl_citation_count_tl
      {
        \int_set:Nn \l__csl_citation_count_int { \l__csl_citation_count_tl }
        \int_incr:N \l__csl_citation_count_int
      }
      { \int_set_eq:NN \l__csl_citation_count_int \c_one_int }
    \prop_gput:NVV \g__csl_citations_count_prop \l__csl_cite_keys_tl
      \l__csl_citation_count_int
    \tl_set:Ne \l__csl_citation_id_tl
      { \l__csl_cite_keys_tl @ \int_use:N \l__csl_citation_count_int }
  }


\int_new:N \g__csl_pseudo_note_index_int
\int_gset:Nn \g__csl_pseudo_note_index_int { 0 }

% Save the note number to \l__csl_note_index_tl
% TODO: multiple citations in a note
\cs_new:Npn \__csl_get_note_index:
  % #1: \l__csl_note_index_tl
  {
    \bool_if:NTF \l__csl_note_bool
      { \tl_set:Ne \l__csl_note_index_tl { \int_use:c { c@ \@mpfn } } }
      {
        \tl_if_empty:NTF \l__csl_class_tl
          {
            % The style class (in-text/note) is undetermined.
            \int_set_eq:Nc \l_tmpa_int { c@ \@mpfn }
            \int_gincr:N \g__csl_pseudo_note_index_int
            \int_add:Nn \l_tmpa_int { \g__csl_pseudo_note_index_int }
            \tl_set:Ne \l__csl_note_index_tl { \int_use:N \l_tmpa_int }
          }
          { \tl_set:Nn \l__csl_note_index_tl { 0 } }
      }
  }


\cs_new:Npn \__csl_write_aux_citation:nn #1#2
  % #1: refsection index (already converted to tl)
  % #2: citation info "{<citationID>}{{id=ITEM-1},{id=ITEM-2}}{<noteIndex>}"
  {
    \if@filesw
      \iow_now:Nn \@auxout { \csl@aux@cite {#1} {#2} }
    \fi
  }

% Should be set to true when located in a footnote, and to false otherwise
\bool_new:N \l__csl_in_note_bool

\hook_gput_code:nnn { cmd / @makefntext / before } { . }
  { \bool_set_true:N \l__csl_in_note_bool }

\hook_gput_code:nnn { cmd / @makefntext / after } { . }
  { \bool_set_false:N \l__csl_in_note_bool }


% #1: \l__csl_citation_tl
\cs_new:Npn \__csl_print_citation:
  {
    \bool_if:NT \l__csl_regression_test_bool
      { \tl_show:N \l__csl_citation_tl }
    \tl_use:N \l__csl_citation_tl
  }


\cs_new:Npn \__csl_print_undefined_citation:n #1
  % #1: keys
  {
    \tl_if_blank:nTF {#1}
      {
        \__csl_warn_citation_undefined:n { }
        \__csl_set_undefined_cite:n { ? }
      }
      {
        \clist_map_inline:nn {#1} { \__csl_warn_citation_undefined:n {##1} }
        % Underscores in citation keys like `zankl_kunstliche_2019` may cause a missing $ error.
        % Thus We convert them to str.
        \tl_set:Ne \l_tmpa_str { \tl_to_str:n {#1} }
        \exp_args:NV \__csl_set_undefined_cite:n \l_tmpa_str
      }
    \bool_if:NT \l__csl_regression_test_bool
      { \tl_show:N \l__csl_citation_tl }
    \group_begin:
      \reset@font \l__csl_citation_tl
    \group_end:
  }

\cs_new:Npn \__csl_set_undefined_cite:n #1
  {
    \tl_set:Nn \l__csl_citation_tl { [ \textbf {#1} ] }
  }

% \msg_new:nnn { citation-style-language } { undefined-citation }
%   { Citation~ '#1'~ on~ page~ \thepage \space undefined~ \msg_line_context: . }

\cs_new:Npn \__csl_warn_citation_undefined:n #1
  {
    \G@refundefinedtrue
    % The warning message is read by latexmk.
    \@latex@warning { Citation~ `#1'~ on~ page~ \thepage \space undefined }
  }


\DeclareDocumentCommand \nocite { m }
  { \__csl_no_cite:n {#1} }


\cs_new:Npn \__csl_no_cite:n #1
  {
    \__csl_cite_init:
    \__csl_collect_citation_items:nnn { } { } {#1}
    \tl_set:Ne \l__csl_cite_items_tl
      { \seq_use:Nn \l__csl_citation_items_seq { , } }
    \prop_clear:N \l__csl_citation_properties_prop
    \prop_put:Nnn \l__csl_citation_properties_prop { noteIndex } { 0 }
    \__csl_make_chapter_property:
    \__csl_serialize_prop:NN \l__csl_citation_properties_prop \l__csl_citation_properties_tl
    \tl_set:Ne \l__csl_citation_info_tl
      {
        citationID    = { @nocite } ,
        citationItems = { \tl_use:N \l__csl_cite_items_tl } ,
        properties    = { \tl_use:N \l__csl_citation_properties_tl }
      }
    \bool_if:NT \l__csl_regression_test_bool
      { \tl_show:N \l__csl_citation_info_tl }
    \exp_args:NVV \__csl_no_cite_write_aux:nn \g__csl_ref_section_index_int \l__csl_citation_info_tl
    \sys_if_engine_luatex:T
      { \lua_now:n { csl_citation_manager:nocite("#1") } }
    \tl_clear:N \l__csl_citation_tl
    \bool_if:NT \l__csl_regression_test_bool
      { \tl_show:N \l__csl_citation_tl }
}


\cs_new:Npn \__csl_no_cite_write_aux:nn #1#2
  {
    \__csl_if_preamble:TF
      {
        \hook_gput_code:nnn { begindocument } { . }
          { \__csl_write_aux_citation:nn {#1} {#2} }
      }
      { \__csl_write_aux_citation:nn {#1} {#2} }
  }


\prg_new_conditional:Nnn \__csl_if_preamble: { T , F , TF }
  {
    \if_meaning:w \@begindocumenthook \@undefined
      \prg_return_false:
    \else
      \prg_return_true:
    \fi
  }


% Used in aux files to register cite items.
% #1: a citation object
\cs_new:Npn \csl@aux@cite #1#2
  {
    \sys_if_engine_luatex:T
      { \lua_now:e { csl_citation_manager:register_citation_info(#1, "\lua_escape:n {#2}") } }
  }


\cs_new:Npn \cslcitation #1#2
  { \prop_gput:Nnn \g__csl_citations_prop {#1} {#2} }


% This command is for use with hyperref.
% #1: cite id
% #2: cite contents
\cs_new:Npn \cslcite #1#2 {#2}

% This command is for use with hyperref.
% #1: cite id
\cs_new:Npn \cslundefinedcite #1 {
  \textbf {#1}
  \__csl_warn_citation_undefined:n {#1}
}
