%
% 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
 { \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 }
   \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}
}