% % Copyright (c) 2021-2024 Zeping Lee % Released under the MIT License. % Repository: https://github.com/zepinglee/citeproc-lua % % ## Bibliography commands % The options like `notcategory` can be used multiple times and thus we save % them into a seq instead of a prop. \seq_new:N \l__csl_bib_filter_seq \int_new:N \g__bib_list_index_int \tl_new:N \g__bib_list_index_tl \tl_new:N \l__csl_bibliography_tl \seq_new:N \l__csl_bibliography_seq \NewDocumentCommand \printbibliography { O { } } { \int_gincr:N \g__bib_list_index_int \tl_gset:Nx \g__bib_list_index_tl { \int_use:N \g__bib_list_index_int } \__csl_set_categories: % Bibliography filter \group_begin: \seq_clear:N \l__csl_bib_filter_seq \seq_put_right:Nx \l__csl_bib_filter_seq { index = \g__bib_list_index_tl } \keys_set:nn { csl / bibliography } {#1} \__csl_serialize_seq:NN \l__csl_bib_filter_seq \l__csl_bib_filter_tl % Collect the bibliography to token list \sys_if_engine_luatex:TF { \bool_if:NT \l__csl_engine_initialized_bool { \__csl_collect_bibliography:n { \lua_now:e { csl.bibliography("\l__csl_bib_filter_tl") } } } } { % Write to aux file \exp_args:NV \__csl_write_aux_bibliography:n \l__csl_bib_filter_tl } % Print the bibliography \prop_get:NVNTF \g__csl_bibliographies_prop \g__bib_list_index_tl \l__csl_bibliography_tl { \bool_if:NT \l__csl_regression_test_bool { \seq_set_split:NnV \l__csl_bibliography_seq { \par } \l__csl_bibliography_tl \seq_show:N \l__csl_bibliography_seq } \tl_use:N \l__csl_bibliography_tl } { \msg_warning:nn { citation-style-language } { bibliography / empty } } \group_end: } \msg_new:nnn { citation-style-language } { bibliography / empty } { The~ bibliography~ is~ empty. } \DeclareDocumentCommand \bibliography { m } { \__csl_write_aux_bibdata:n {#1} \printbibliography } \tl_new:N \l__csl_bib_env_tl \tl_new:N \l__csl_bib_head_name_tl \tl_new:N \l__csl_bib_head_title_tl \tl_new:N \l__csl_bib_head_label_tl \tl_new:N \l__csl_bib_pre_note_tl \tl_new:N \l__csl_bib_post_note_tl \tl_new:N \l__csl_bib_filter_tl \tl_set:Nn \l__csl_bib_env_tl { bibliography } \tl_set:Nn \l__csl_bib_head_name_tl { bibliography } \keys_define:nn { csl / bibliography } { % env .tl_set:N = \l__csl_bib_env_name_tl , heading .tl_set:N = \l__csl_bib_head_name_tl , title .tl_set:N = \l__csl_bib_head_title_tl , label .tl_set:N = \l__csl_bib_head_label_tl , % block prenote .tl_set:N = \l__csl_bib_pre_note_tl , postnote .tl_set:N = \l__csl_bib_post_note_tl , % section % segment type .code:n = { \seq_put_right:Nn \l__csl_bib_filter_seq { type = {#1} } } , nottype .code:n = { \seq_put_right:Nn \l__csl_bib_filter_seq { nottype = {#1} } } , % subtype .code:n = { \seq_put_right:Nn \l__csl_bib_filter_seq { subtype = {#1} } } , % notsubtype .code:n = { \seq_put_right:Nn \l__csl_bib_filter_seq { notsubtype = {#1} } } , keyword .code:n = { \seq_put_right:Nn \l__csl_bib_filter_seq { keyword = {#1} } } , notkeyword .code:n = { \seq_put_right:Nn \l__csl_bib_filter_seq { notkeyword = {#1} } } , category .code:n = { \seq_put_right:Nn \l__csl_bib_filter_seq { category = {#1} } } , notcategory .code:n = { \seq_put_right:Nn \l__csl_bib_filter_seq { notcategory = {#1} } } , % filter .tl_set:N = \l__csl_bibliography_nottype_tl , } % Used for debugging and testing \clist_new:N \g__csl_bib_items_clist \cs_new:Npn \__csl_write_aux_bibliography:n #1 { \if@filesw \iow_now:Nn \@auxout { \csl@aux@bibliography {#1} } \fi } \cs_new:Npn \csl@aux@bibliography #1 { } \tl_new:N \l__csl_bib_index_tl \bool_new:N \l__csl_hanging_indent_bool \tl_new:N \l__csl_line_spacing_tl \tl_new:N \l__csl_entry_spacing_tl \tl_new:N \l__csl_bib_wides_label_tl \keys_define:nn { csl / bib-options } { index .tl_set:N = \l__csl_bib_index_tl , hanging-indent .bool_set:N = \l__csl_hanging_indent_bool , line-spacing .tl_set:N = \l__csl_line_spacing_tl , entry-spacing .tl_set:N = \l__csl_entry_spacing_tl , widest-label .tl_set:N = \l__csl_bib_wides_label_tl , } \keys_set:nn { csl / bib-options } { index = 1 , hanging-indent = false , line-spacing = 1 , entry-spacing = 1 , widest-label = { } , } \RenewDocumentEnvironment { thebibliography } { m } { \exp_args:NVV \__csl_make_bib_heading:nn \l__csl_bib_head_name_tl \l__csl_bib_head_title_tl \exp_args:NV \__csl_print_bib_note:n \l__csl_bib_pre_note_tl \group_begin: \tl_set:Nn \l__csl_bib_index_tl { 1 } \keys_set:nn { csl / bib-options } {#1} \dim_zero:N \parindent \tl_if_eq:NnF \l__csl_line_spacing_tl { 1 } { \linespread { \l__csl_line_spacing_tl } \selectfont } \l__csl_bib_font_tl \list { } { \__csl_set_bib_label_spacing:n { \l__csl_bib_wides_label_tl } \__csl_set_bib_item_sep: } \sloppy \__csl_set_bib_page_break: \frenchspacing \__csl_bib_url_setup: \clist_gclear:N \g__csl_bib_items_clist } { \tl_set:Nn \@noitemerr { \msg_warning:nn { citation-style-language } { bibliography / empty } } \endlist \group_end: \exp_args:NV \__csl_print_bib_note:n \l__csl_bib_post_note_tl } % ### Bibliography spacing \dim_new:N \l__csl_bib_hang_dim \cs_new:Npn \__csl_set_bib_label_spacing:n #1 { \bool_if:NTF \l__csl_hanging_indent_bool { \dim_set:Nn \l__csl_bib_hang_dim { \l__csl_bib_hang_tl } \dim_set_eq:NN \leftmargin \l__csl_bib_hang_dim \dim_set:Nn \itemindent { - \leftmargin } } { \settowidth \labelwidth { \@biblabel {#1} } \dim_set_eq:NN \leftmargin \labelwidth \dim_add:Nn \leftmargin { \labelsep } } } % In standard LaTeX classes (10pt), the vertical sep of bibliographic item is % \itemsep (4\p@ \@plus2\p@ \@minus\p@) + \parsep (4\p@ \@plus2\p@ \@minus\p@) % = 8pt plus 4pt minus 2pt \cs_new:Npn \__csl_set_bib_item_sep: { \skip_zero:N \parsep \tl_if_empty:NTF \l__csl_bib_item_sep_tl { \skip_set:Nn \itemsep { 8 pt plus 4 pt minus 2 pt * \dim_ratio:nn { 1 em } { 8 pt } * \l__csl_entry_spacing_tl } } { \skip_set:Nn \itemsep { \l__csl_bib_item_sep_tl } } } % ### Bibliography label % CSL outputs the whole label thus the brackets are removed from \@biblabel % \def\@biblabel#1{[#1]} \cs_set:Npn \@biblabel #1 {#1} % For numeric or label-style bibliography: \bibitem[{[17]}]{entrykey} % \@lbibitem is redefined in `babel` and `hyperref` and we need to override it % in the patching code. Thus we define \__csl_lbibitem: here and reassign it to % \@lbibitem in compatability code \cs_new:Npn \__csl_lbibitem: { \bool_if:NTF \l__csl_back_ref_bool { \__csl_lbibitem_back_ref:nnn } { \__csl_lbibitem_plain:nn } } \cs_set_eq:NN \@lbibitem \__csl_lbibitem: \cs_new:Npn \__csl_lbibitem_plain:nn [#1]#2 { \clist_gput_right:Nn \g__csl_bib_items_clist {#2} \item [ \@biblabel {#1} \hfill ] \ignorespaces } % This is the version for use with backref feature. \cs_new:Npn \__csl_lbibitem_back_ref:nnn [#1]#2#3\par { \__csl_lbibitem_plain:nn [#1] {#2} #3 \prop_get:NnNT \g__csl_back_ref_info_prop {#2} \l_tmpa_tl { \c_space_tl \exp_args:NV \__csl_print_back_refs:n \l_tmpa_tl } \par } \cs_new:Npn \__csl_print_back_refs:n #1 % #1: list of {}{