% % Copyright (c) 2021-2024 Zeping Lee % Released under the MIT License. % Repository: https://github.com/zepinglee/citeproc-lua % % ## Initialization at `\begin{document}` \hook_gput_code:nnn { begindocument } { . } { \__csl_at_begin_document_hook: } \cs_new:Npn \__csl_at_begin_document_hook: { \__csl_write_aux_info: \sys_if_engine_luatex:TF { \__csl_initialize_lua_module: } { \__csl_load_bbl: \__csl_read_style_class: } } \clist_new:N \g__csl_aux_bib_files_clist \cs_new:Npn \__csl_write_aux_info: { \tl_if_empty:NT \l__csl_style_tl { \tl_set_eq:NN \l__csl_style_tl \g__csl_aux_bibstyle_tl \edef \csl@style { \g__csl_aux_bibstyle_tl } } \tl_if_empty:VTF \l__csl_style_tl { \msg_warning:nn { citation-style-language } { missing-style-name } \tl_set:Nn \l__csl_style_tl { apa } } { \exp_args:NV \__csl_write_aux_bibstyle:n \l__csl_style_tl } \clist_if_empty:NTF \l__csl_bib_resources_clist { \clist_set_eq:NN \l__csl_bib_resources_clist \g__csl_aux_bib_files_clist } { \exp_args:Nx \__csl_write_aux_bibdata:n { \clist_use:Nn \l__csl_bib_resources_clist { , } } } \__csl_write_aux_csl_options: } \cs_new:Npn \__csl_write_aux_bibstyle:n #1 { \if@filesw \iow_now:Nx \@auxout { \token_to_str:N \csl@aux@style {#1} } \fi } \cs_new:Npn \__csl_write_aux_bibdata:n #1 { \if@filesw % Full expansion for files like \jobname.bib \iow_now:Nx \@auxout { \token_to_str:N \csl@aux@data {#1} } \fi } % In earlier time, \bibdata{xxx.json} was used but this causes latexmk unable % to find xxx.json.bib and it refuses to run the $bibtex procedure. % John Collins suggests using a different command than \bibdata. \cs_new:Npn \csl@aux@data #1 { \clist_gput_right:Nn \g__csl_aux_bib_files_clist {#1} } \cs_new:Npn \__csl_initialize_lua_module: { \clist_if_empty:NT \l__csl_bib_resources_clist { \msg_warning:nn { citation-style-language } { empty-bib-resources } } \lua_now:e { csl.init( "\l__csl_style_tl", "\l__csl_bib_resources_clist", "\l__csl_locale_tl" ) } \str_if_eq:eeT { \lua_now:n { tex.print(csl.initialized) } } { true } { \bool_set_true:N \l__csl_engine_initialized_bool } \__csl_get_style_class: \@ifpackageloaded { hyperref } { \lua_now:n { csl.enable_linking() } } { } } \msg_new:nnn { citation-style-language } { missing-style-name } { Missing~ style~ name.\\Will~ use~ default~ APA~ style. } \msg_new:nnn { citation-style-language } { empty-bib-resources } { Empty~ bibliographic~ resources.~ Use~ \token_to_str:N \addbibresource. } % \str_new:N \l__csl_style_class_str % In-text (including numeric or author-date) or note style % \bool_new:N \l__csl_note_style_bool \cs_new:Npn \__csl_get_style_class: { \bool_if:NT \l__csl_engine_initialized_bool { \tl_set:Nx \l__csl_class_tl { \lua_now:n { csl.get_style_class() } } \tl_if_eq:NnT \l__csl_class_tl { note } { \bool_set_true:N \l__csl_note_bool } } } \clist_new:N \l__csl_options_clist \bool_new:N \l__csl_engine_initialized_bool \prop_new:N \l__csl_language_code_map_prop \prop_set_from_keyval:Nn \l__csl_language_code_map_prop { acadian = fr-CA, american = en-US, australian = en-AU, afrikaans = af-ZA, albanian = sq-AL, amharic = am-ET, arabic = ar, armenian = hy-AM, asturian = ast-ES, austrian = de-AT, bahasa = id-ID, bahasai = id-ID, bahasam = id-ID, basque = eu-ES, bengali = bn-BD, bgreek = el-GR, brazil = pt-BR, brazilian = pt-BR, breton = br-FR, british = en-GB, bulgarian = bg-BG, canadian = en-CA, canadien = fr-CA, catalan = ca-AD, coptic = cop, croatian = hr-HR, czech = cs-CZ, danish = da-DK, divehi = dv-MV, dutch = nl-NL, english = en-US, esperanto = eo-001, estonian = et-EE, ethiopia = am-ET, farsi = fa-IR, finnish = fi-FI, francais = fr-FR, french = fr-FR, frenchle = fr-FR, friulan = fur-IT, galician = gl-ES, german = de-DE, germanb = de-DE, greek = el-GR, hebrew = he-IL, hindi = hi-IN, ibygreek = el-CY, icelandic = is-IS, indon = id-ID, indonesia = id-ID, interlingua = ia-FR, irish = ga-IE, italian = it-IT, japanese = ja-JP, kannada = kn-IN, lao = lo-LA, latin = la-Latn, latvian = lv-LV, lithuanian = lt-LT, lowersorbian = dsb-DE, lsorbian = dsb-DE, magyar = hu-HU, malay = id-ID, malayalam = ml-IN, marathi = mr-IN, meyalu = id-ID, mongolian = mn-Cyrl, naustrian = de-AT, newzealand = en-NZ, ngerman = de-DE, nko = ha-NG, norsk = nb-NO, norwegian = nn-NO, nynorsk = nn-NO, occitan = oc-FR, piedmontese = pms-IT, pinyin = pny, polish = pl-PL, polutonikogreek = el-GR, portuges = pt-PT, portuguese = pt-PT, romanian = ro-RO, romansh = rm-CH, russian = ru-RU, samin = se-NO, sanskrit = sa-IN, scottish = gd-GB, serbian = sr-Latn, serbianc = sr-Cyrl, slovak = sk-SK, slovene = sl-SI, slovenian = sl-SI, spanish = es-ES, swedish = sv-SE, swiss = de-CH, swissgerman = de-CH, nswissgerman = de-CH, syriac = syc, tamil = ta-IN, telugu = te-IN, thai = th-TH, thaicjk = th-TH, tibetan = bo-CN, turkish = tr-TR, turkmen = tk-TM, ukrainian = uk-UA, urdu = ur-IN, UKenglish = en-UK, uppersorbian = hsb-DE, USenglish = en-US, usorbian = hsb-DE, vietnamese = vi-VN, welsh = cy-GB, } \cs_new:Npn \__csl_write_aux_csl_options: { \clist_clear:N \l__csl_options_clist % locale \tl_if_empty:NT \l__csl_locale_tl { \tl_if_exist:NT \bbl@main@language { \prop_get:NVN \l__csl_language_code_map_prop \bbl@main@language \l__csl_locale_tl } } \tl_if_empty:NF \l__csl_locale_tl { \clist_put_right:Nx \l__csl_options_clist { locale = \l__csl_locale_tl } } % linking \@ifpackageloaded { hyperref } { \clist_put_right:Nn \l__csl_options_clist { linking = true } } { } % write to aux file \prop_if_empty:NF \l__csl_options_clist { \exp_args:Nx \__csl_write_aux_options:n { \clist_use:Nn \l__csl_options_clist { , } } } } \cs_new:Npn \__csl_write_aux_options:n #1 { \if@filesw \iow_now:Nn \@auxout { \csl@aux@options {#1} } \fi } \cs_new:Npn \csl@aux@options #1 { } \tl_new:N \g__csl_bibliography_setup_tl % Load .bbl at the beginning of document to save one pass of latex. % In this procedure, the \cslcitation command is processed and the contents % of `thebibliography` is stored into \g__csl_bibliographies_prop. \cs_new:Npn \__csl_load_bbl: { % The \@input@ prints "No file ....bbl" in the .log file from which % the latexmk decides to run $bibtex or not. \__csl_collect_bibliography:n { \@input@ { \jobname .bbl } } % Execute the \cslsetup part to set the style class. % \tl_show:N \g__csl_bibliography_setup_tl \tl_use:N \g__csl_bibliography_setup_tl % \bool_show:N \l__csl_note_bool } % A document may have multiple bibliographies or biblists and they are stored % in `\g__csl_bibliographies_prop` by their index. \prop_new:N \g__csl_bibliographies_prop % Collection the bibliography into \g__csl_bibliographies_prop \cs_new:Npn \__csl_collect_bibliography:n #1 { \group_begin: % URLs may contain "%" and "#" characters. \char_set_catcode_other:N \% \char_set_catcode_other:N \# \RenewDocumentCommand \cslsetup { m } { \tl_gset:Nn \g__csl_bibliography_setup_tl { \cslsetup { ##1 } } } \RenewDocumentEnvironment { thebibliography } { m +b } { \tl_set:Nn \l__csl_bib_index_tl { 1 } \keys_set:nn { csl / bib-options } {##1} \prop_gput:NVn \g__csl_bibliographies_prop \l__csl_bib_index_tl { \begin { thebibliography } {##1} ##2 \end { thebibliography } } } { } % Perform the execution #1 \group_end: } % The `\textcite` bahaves differently with note styles. % Thus we read the style class from the `.csl` file with non-LuaTeX engines. \ior_new:N \l__csl_style_ior \cs_new:Npn \__csl_read_style_class: { \bool_set_false:N \l__csl_note_bool \tl_if_blank:VF \l__csl_style_tl { \exp_args:NNx \ior_open:Nn \l__csl_style_ior { \l__csl_style_tl .csl } \ior_map_inline:Nn \l__csl_style_ior { % \tl_show:n {##1} \tl_if_in:nnT {##1} { class="note" } { \tl_set:Nn \l__csl_class_tl { note } \bool_set_true:N \l__csl_note_bool \ior_map_break: } } \ior_close:N \l__csl_style_ior } } % \msg_new:nnn { citation-style-language } { file / non-exist } % { No~ file~ #1. }