summaryrefslogtreecommitdiff
path: root/biblio/citation-style-language/citation-style-language.sty
diff options
context:
space:
mode:
Diffstat (limited to 'biblio/citation-style-language/citation-style-language.sty')
-rw-r--r--biblio/citation-style-language/citation-style-language.sty458
1 files changed, 395 insertions, 63 deletions
diff --git a/biblio/citation-style-language/citation-style-language.sty b/biblio/citation-style-language/citation-style-language.sty
index 7d0daab99e..5566737b49 100644
--- a/biblio/citation-style-language/citation-style-language.sty
+++ b/biblio/citation-style-language/citation-style-language.sty
@@ -1,5 +1,5 @@
%
-% Copyright (c) 2021-2022 Zeping Lee
+% Copyright (c) 2021-2023 Zeping Lee
% Released under the MIT License.
% Repository: https://github.com/zepinglee/citeproc-lua
%
@@ -9,7 +9,7 @@
\RequirePackage{expl3}
\RequirePackage{xparse}
-\ProvidesExplPackage {citation-style-language} {2022-12-25} {v0.3.0}
+\ProvidesExplPackage {citation-style-language} {2023-04-02} {v0.4.0}
{Citation Style Language for LaTeX}
\RequirePackage { l3keys2e }
@@ -18,21 +18,18 @@
% Check incompatible packages
\msg_new:nnn { citation-style-language } { incompatible-package }
- { The~ `#1'~ package~ is~ incompatible~ with~ `citeproc'. }
+ { The~ `#1'~ package~ is~ incompatible~ with~ `citation-style-language'. }
-\cs_new_protected:Npn \__csl_load_check:n #1
- {
- \AtBeginOfPackageFile* {#1}
- { \msg_error:nnn { citation-style-language } { incompatible-package } {#1} }
- }
-
-\clist_map_function:nN
+\clist_map_inline:nn
{
babelbib , backref , biblatex , bibtopic , bibunits , chapterbib ,
cite , citeref , inlinebib , jurabib , mcite , mciteplus ,
multibib , natbib , splitbib
}
- \__csl_load_check:n
+ {
+ \AtBeginOfPackageFile* {#1}
+ { \msg_error:nnn { citation-style-language } { incompatible-package } {#1} }
+ }
% Check l3build regression-test
@@ -50,7 +47,7 @@
\NewDocumentCommand \cslsetup { m }
{ \keys_set:nn { csl } {#1} }
-\cs_new:Npn \csloptions #1 { }
+\cs_new:Npn \csl@aux@options #1 { }
\DeclareDocumentCommand \cite { o o m }
@@ -68,6 +65,9 @@
\NewDocumentCommand \citet { o o m }
{ \__csl_text_cite:nnn {#1} {#2} {#3} }
+\NewDocumentCommand \footcite { o o m }
+ { \__csl_cite:nnn {#1} {#2} {#3} }
+
% \cites[⟨prenote⟩][⟨postnote⟩]{⟨key⟩}...[⟨prenote⟩][⟨postnote⟩]{⟨key⟩}
\NewDocumentCommand \cites { }
@@ -82,14 +82,19 @@
\prop_new:N \l__csl_citation_properties_prop
\prop_new:N \l__csl_citation_info_prop
+% \__csl_cite:nnn #1#2#3
\cs_new:Npn \__csl_cite:nnn #1#2#3
{
- \seq_clear:N \l__csl_cite_keys_seq
- \seq_clear:N \l__csl_citation_items_seq
- \prop_clear:N \l__csl_citation_properties_prop
- \__csl_process_cite_input:nnn {#1} {#2} {#3}
- \__csl_process_citation_info:NN \l__csl_cite_keys_seq \l__csl_citation_items_seq
- \__csl_make_citation:N \l__csl_citation_info_prop
+ \tl_if_blank:nTF {#3}
+ { \__csl_print_undefined_citation:n {#3} }
+ {
+ \seq_clear:N \l__csl_cite_keys_seq
+ \seq_clear:N \l__csl_citation_items_seq
+ \prop_clear:N \l__csl_citation_properties_prop
+ \__csl_process_cite_input:nnn {#1} {#2} {#3}
+ \__csl_process_citation_info:NN \l__csl_cite_keys_seq \l__csl_citation_items_seq
+ \__csl_make_citation:N \l__csl_citation_info_prop
+ }
}
@@ -279,6 +284,46 @@
\__csl_process_citation_id:NN \l__csl_citation_id_tl #1
\__csl_get_note_index:N \l__csl_note_index_tl
\prop_put:NnV \l__csl_citation_properties_prop { noteIndex } \l__csl_note_index_tl
+ \__csl_add_back_ref_info:
+ }
+
+
+\tl_new:N \l__csl_back_ref_tl
+\prop_new:N \g__csl_back_ref_info_prop
+\prop_new:N \l__csl_back_ref_section_pop
+
+% Provide empty \@currentHref when hyperref is not loaded.
+\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:Nx \l__csl_back_ref_tl
+ { { \thepage } { (document) } { Doc-Start } }
+ }
+ {
+ \tl_set:Nx \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
+ }
+ }
}
@@ -420,7 +465,7 @@
% #1: citation info "{<citationID>}{{id=ITEM-1},{id=ITEM-2}}{<noteIndex>}"
{
\if@filesw
- \iow_now:Nn \@auxout { \citation {#1} }
+ \iow_now:Nn \@auxout { \csl@aux@cite {#1} }
\fi
}
@@ -441,11 +486,13 @@
{
\G@refundefinedtrue
\msg_warning:nnn { citation-style-language } { citation / undefined } {#1}
- \tl_set:Nn \l__csl_citation_tl { [ \textbf {#1} ] }
+ \tl_if_blank:nTF {#1}
+ { \tl_set:Nn \l__csl_citation_tl { [ \textbf { ? } ] } }
+ { \tl_set:Nn \l__csl_citation_tl { [ \textbf {#1} ] } }
\bool_if:NT \l__csl_regression_test_bool
{ \tl_show:N \l__csl_citation_tl }
\group_begin:
- \reset@font [ \textbf {#1} ]
+ \reset@font \l__csl_citation_tl
\group_end:
}
@@ -504,37 +551,116 @@
% Used in aux files to register cite items.
% #1: a citation object
-\cs_set:Npn \citation #1
+\cs_set:Npn \csl@aux@cite #1
{
\sys_if_engine_luatex:T
- { \lua_now:n { csl.register_citation_info("#1") } }
+ { \lua_now:e { csl.register_citation_info("\lua_escape:n {#1}") } }
}
-\cs_new:Npn \cslcite #1#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}
+
+
+\keys_define:nn { csl / bibliography }
{
- % \if@filesw
- % \iow_now:Nn \@auxout { \bibcite {#1} {#2} }
- % \fi
- \bibcite {#1} {#2}
+ type .code:n = \__csl_add_filter_condition:nn { type } {#1} ,
+ nottype .code:n = \__csl_add_filter_condition_negative:nn { type } {#1} , % subtype .code:n = \__csl_add_filter_condition:nn { subtype } {#1} ,
+ % notsubtype .code:n = \__csl_add_filter_condition_negative:nn { subtype } {#1} ,
+ keyword .code:n = \__csl_add_filter_condition:nn { keyword } {#1} ,
+ notkeyword .code:n = \__csl_add_filter_condition_negative:nn { keyword } {#1} ,
+ category .code:n = \__csl_add_filter_condition:nn { categories } {#1} ,
+ notcategory .code:n = \__csl_add_filter_condition_negative:nn { categories } {#1} ,
+ % filter .tl_set:N = \l__csl_bibliography_nottype_tl ,
}
+\seq_new:N \l__bibliography_filter_conditions_seq
+\tl_new:N \l__bibliography_filter_conditions_tl
-\cs_new:Npn \__csl_bibcite:nn #1#2
- { \prop_gput:Nnn \g__csl_citations_prop {#1} {#2} }
+\cs_new:Npn \__csl_add_filter_condition:nn #1#2
+ {
+ \seq_put_right:Nn \l__bibliography_filter_conditions_seq
+ {
+ {
+ field = #1 ,
+ value = #2
+ }
+ }
+ }
-\cs_set_eq:NN \bibcite \__csl_bibcite:nn
+\cs_new:Npn \__csl_add_filter_condition_negative:nn #1#2
+ {
+ \seq_put_right:Nn \l__bibliography_filter_conditions_seq
+ {
+ {
+ field = #1,
+ value = #2,
+ negative = true
+ }
+ }
+ }
\NewDocumentCommand \printbibliography { O { } }
{
+ % Set categories
+ \prop_if_empty:NF \l__csl_categories_prop
+ {
+ \tl_clear:N \l_tmpa_tl
+ \prop_map_inline:Nn \l__csl_categories_prop
+ {
+ \tl_if_empty:NF \l_tmpa_tl
+ { \tl_put_right:Nn \l_tmpa_tl { , } }
+ \tl_put_right:Nn \l_tmpa_tl { ##1 = {##2} }
+ }
+ \sys_if_engine_luatex:T
+ { \lua_now:e { csl.set_categories("\l_tmpa_tl") } }
+ {
+ \tl_put_left:Nx \l_tmpa_tl { categories = \c_left_brace_str }
+ \tl_put_right:NV \l_tmpa_tl \c_right_brace_str
+ \exp_args:NV \__csl_write_aux_options:n \l_tmpa_tl
+ }
+ }
+ % Bibliography filter
+ \seq_clear:N \l__bibliography_filter_conditions_seq
+ \keys_set:nn { csl / bibliography } {#1}
+ \tl_clear:N \l__bibliography_filter_conditions_tl
+ \seq_if_empty:NF \l__bibliography_filter_conditions_seq
+ {
+ \tl_set:Nx \l__bibliography_filter_conditions_tl
+ { select = \c_left_brace_str }
+ \tl_put_right:Nx \l__bibliography_filter_conditions_tl
+ { \seq_use:Nn \l__bibliography_filter_conditions_seq { , } }
+ \tl_put_right:NV \l__bibliography_filter_conditions_tl
+ { \c_right_brace_str }
+ % Write to aux file
+ \sys_if_engine_luatex:F
+ {
+ \tl_set:Nx \l_tmpa_tl { bib-filter = \c_left_brace_str }
+ \tl_put_right:NV \l_tmpa_tl { \l__bibliography_filter_conditions_tl }
+ \tl_put_right:NV \l_tmpa_tl { \c_right_brace_str }
+ \exp_args:NV \__csl_write_aux_options:n \l_tmpa_tl
+ }
+ }
+ % Collect the bibliography to token list
\sys_if_engine_luatex:T
{
\bool_if:NT \l__csl_engine_initialized_bool
{
- \__csl_collect_bibliography:n { \lua_now:n { csl.bibliography() } }
+ \__csl_collect_bibliography:n
+ {
+ \lua_now:e
+ { csl.bibliography("\l__bibliography_filter_conditions_tl") }
+ }
}
}
+ % Print the bibliography
\tl_if_empty:NTF \g__csl_bibliography_tl
{ \msg_warning:nn { citation-style-language } { bibliography / empty } }
{
@@ -552,34 +678,54 @@
\tl_new:N \l__csl_style_tl
+\newcommand \csl@style {} % For latex2e interface
\tl_new:N \l__csl_class_tl
\bool_new:N \l__csl_note_bool
\clist_new:N \l__csl_bib_resources_clist
+\tl_new:N \l__csl_locale_tl
+\bool_new:N \l__csl_back_ref_bool
+\str_new:N \l__csl_back_ref_type_str
+% Citation formatting
\tl_new:N \l__csl_prefix_separator_tl
\tl_new:N \l__csl_suffix_separator_tl
-\tl_new:N \l__csl_locale_tl
+% Bibliography formatting
+\tl_new:N \bibsection
\tl_new:N \l__csl_bib_font_tl
+\bool_new:N \l__csl_bib_entry_page_break_bool
\tl_new:N \l__csl_bib_item_sep_tl
\tl_new:N \l__csl_bib_hang_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_set:Nn \l__csl_back_ref_type_str { page }
+
\keys_define:nn { csl }
{
regression-test .bool_set:N = \l__csl_regression_test_bool ,
- style .tl_set:N = \l__csl_style_tl ,
+ style .code:n =
+ {
+ \tl_set:Nn \l__csl_style_tl {#1}
+ \renewcommand \csl@style {#1}
+ } ,
class .code:n =
{
\tl_set:Nn \l__csl_class_tl {#1}
\tl_if_eq:NnT \l__csl_class_tl { note }
{ \bool_set_true:N \l__csl_note_bool }
} ,
+ locale .tl_set:N = \l__csl_locale_tl ,
+ backref .choices:nn =
+ { true, page, section, false }
+ { \exp_args:NV \__csl_set_back_ref:n \l_keys_choice_tl } ,
+ % Citation formatting
prefix-separator .tl_set:N = \l__csl_prefix_separator_tl ,
suffix-separator .tl_set:N = \l__csl_suffix_separator_tl ,
- locale .tl_set:N = \l__csl_locale_tl ,
+ % Bibliography formatting
+ bib-section .tl_set:N = \bibsection ,
bib-font .tl_set:N = \l__csl_bib_font_tl ,
+ bib-entry-page-break .bool_set:N = \l__csl_bib_entry_page_break_bool ,
bib-item-sep .tl_set:N = \l__csl_bib_item_sep_tl ,
bib-hang .tl_set:N = \l__csl_bib_hang_tl ,
hanging-indent .bool_set:N = \l__csl_hanging_indent_bool ,
@@ -591,11 +737,13 @@
{
prefix-separator = { ~ } ,
suffix-separator = { , ~ } ,
+ bib-entry-page-break = true ,
bib-hang = { 1 em } ,
line-spacing = { 1 } ,
entry-spacing = { 1 } ,
}
+
\ProcessKeysPackageOptions { csl }
\bool_new:N \l__csl_engine_initialized_bool
@@ -737,7 +885,10 @@
\cs_new:Npn \__csl_write_aux_info:
{
\tl_if_empty:NTF \l__csl_style_tl
- { \tl_set_eq:NN \l__csl_style_tl \g__csl_aux_bibstyle_tl }
+ {
+ \tl_set_eq:NN \l__csl_style_tl \g__csl_aux_bibstyle_tl
+ \edef \csl@style { \g__csl_aux_bibstyle_tl }
+ }
{ \exp_args:Nx \__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 }
@@ -751,7 +902,7 @@
\cs_new:Npn \__csl_write_aux_bibstyle:n #1
{
\if@filesw
- \iow_now:Nx \@auxout { \token_to_str:N \bibstyle {#1} }
+ \iow_now:Nx \@auxout { \token_to_str:N \csl@aux@style {#1} }
\fi
}
@@ -823,13 +974,13 @@
\cs_new:Npn \__csl_write_aux_options:n #1
{
\if@filesw
- \iow_now:Nn \@auxout { \csloptions {#1} }
+ \iow_now:Nn \@auxout { \csl@aux@options {#1} }
\fi
}
% Load .bbl at the beginning of document to save one pass of latex.
-% In this procedure, the \cslcite command is processed and the contents
+% In this procedure, the \cslcitation command is processed and the contents
% of `thebibliography` is stored into \g__csl_bibliography_tl.
\cs_new:Npn \__csl_load_bbl:
{
@@ -883,7 +1034,7 @@
}
\tl_new:N \g__csl_aux_bibstyle_tl
-\cs_set:Npn \bibstyle #1
+\cs_set:Npn \csl@aux@style #1
{ \tl_gset:Nn \g__csl_aux_bibstyle_tl {#1} }
@@ -895,7 +1046,7 @@
% to find xxx.json.bib and it refuses to run the $bibtex procedure.
% John Collins suggests using a different command than \bibdata.
\clist_new:N \g__csl_aux_bib_files_clist
-\cs_new:Npn \csl@data #1
+\cs_new:Npn \csl@aux@data #1
{ \clist_gput_right:Nn \g__csl_aux_bib_files_clist {#1} }
@@ -909,35 +1060,134 @@
{
\if@filesw
% Full expansion for files like \jobname.bib
- \iow_now:Nx \@auxout { \token_to_str:N \csl@data {#1} }
+ \iow_now:Nx \@auxout { \token_to_str:N \csl@aux@data {#1} }
\fi
}
% Used for debugging and testing
\clist_new:N \g__csl_bib_items_clist
+% Backref
+\bool_set_false:N \l__csl_back_ref_bool
% For numeric or label-style bibliography
% \def\@lbibitem[#1]#2{\item[\@biblabel{#1}\hfill]\if@filesw
% {\let\protect\noexpand
% \immediate
% \write\@auxout{\string\bibcite{#2}{#1}}}\fi\ignorespaces}
-\cs_new:Npn \__csl_lbibitem:nn [#1]#2
+\cs_new:Npn \__csl_lbibitem_plain:nn [#1]#2
{
\clist_gput_right:Nn \g__csl_bib_items_clist {#2}
- \item [ \@biblabel {#1} \hfill ] \ignorespaces
+ \item [ \@biblabel {#1} \hfill ]
+ \ignorespaces
+ }
+
+\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 {<page>}{<label>}{anchor}
+ {
+ \clist_set:Nn \l_tmpa_clist {#1}
+ % To remove duplicates
+ \prop_clear:N \l_tmpa_prop
+ % Output seq
+ \seq_clear:N \l_tmpa_seq
+ \clist_map_inline:Nn \l_tmpa_clist { \__csl_print_back_ref_aux:nnn ##1 }
+ \backref { \seq_use:Nn \l_tmpa_seq { ,~ } }
+ }
+
+\cs_new:Npn \__csl_print_back_ref_aux:nnn #1#2#3
+ {
+ \str_if_eq:VnTF \l__csl_back_ref_type_str { page }
+ {
+ \prop_if_in:NnF \l_tmpa_prop {#1}
+ {
+ \bool_if:NTF \l__csl_hyperref_loaded_bool
+ { \seq_put_right:Nn \l_tmpa_seq { \hyperlink { page. #1 } {#1} } }
+ { \seq_put_right:Nn \l_tmpa_seq {#1} }
+ \prop_put:Nnn \l_tmpa_prop {#1} {#1}
+ }
+ }
+ {
+ % section
+ \prop_if_in:NnF \l_tmpa_prop {#2}
+ {
+ \bool_if:NTF \l__csl_hyperref_loaded_bool
+ { \seq_put_right:Nn \l_tmpa_seq { \hyperlink {#3} {#2} } }
+ { \seq_put_right:Nn \l_tmpa_seq {#2} }
+ \prop_put:Nnn \l_tmpa_prop {#2} {#2}
+ }
+ }
+ }
+
+% Hook
+\cs_new:Npn \backref #1 {#1}
+
+\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:nn
+
+\cs_set_eq:NN \@lbibitem \__csl_lbibitem:
+
% For author-date bibliography
% \def\@bibitem#1{\item\if@filesw \immediate\write\@auxout
% {\string\bibcite{#1}{\the\value{\@listctr}}}\fi\ignorespaces}
-\cs_new:Npn \__csl_bibitem:n #1
+\cs_new:Npn \__csl_bibitem:
+ {
+ \bool_if:NTF \l__csl_back_ref_bool
+ { \__csl_bibitem_back_ref:nn }
+ { \__csl_bibitem_plain:n }
+ }
+
+\cs_set_eq:NN \@bibitem \__csl_bibitem:
+
+\cs_new:Npn \__csl_bibitem_plain:n #1
{
\clist_gput_right:Nn \g__csl_bib_items_clist {#1}
- \item [ ] \ignorespaces
+ \item
+ \ignorespaces
+ }
+
+\cs_new:Npn \__csl_bibitem_back_ref:nn #1#2\par
+ {
+ \__csl_bibitem_plain:n {#1}
+ #2
+ % \prop_show:N \g__csl_back_ref_info_prop
+ \prop_get:NnNT \g__csl_back_ref_info_prop {#1} \l_tmpa_tl
+ {
+ \c_space_tl
+ \exp_args:NV \__csl_print_back_refs:n \l_tmpa_tl
+ }
+ \par
+ }
+
+\cs_new:Npn \__csl_set_back_ref:n #1
+ {
+ \str_if_eq:nnTF {#1} {false}
+ {
+ \bool_set_false:N \l__csl_back_ref_bool
+ }
+ {
+ \bool_set_true:N \l__csl_back_ref_bool
+ \str_if_eq:nnTF {#1} {true}
+ { \str_set:Nn \l__csl_back_ref_type_str { page } }
+ { \str_set:Nn \l__csl_back_ref_type_str {#1} }
+ }
}
-\cs_set_eq:NN \@bibitem \__csl_bibitem:n
% CSL outputs the whole label thus the brackets are removed from \@biblabel
@@ -945,9 +1195,10 @@
\cs_set:Npn \@biblabel #1 {#1}
+% Bibliography heading
\cs_if_exist:cTF { chapter }
{
- \cs_set:Nn \__csl_bib_section:
+ \tl_set:Nn \bibsection
{
\chapter*
{
@@ -959,7 +1210,7 @@
}
}
{
- \cs_set:Nn \__csl_bib_section:
+ \tl_set:Nn \bibsection
{
\section*
{
@@ -976,7 +1227,6 @@
\tl_new:N \l__csl_bib_postamble_tl
\dim_new:N \l__csl_bib_hang_dim
-\skip_new:N \l__csl_bib_item_sep_skip
\cs_new:Npn \__csl_set_bib_label_spacing:n #1
{
@@ -993,20 +1243,26 @@
}
}
+% 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 \l__csl_bib_item_sep_skip
+ \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 \l__csl_bib_item_sep_skip { \l__csl_bib_item_sep_tl } }
+ { \skip_set:Nn \itemsep { \l__csl_bib_item_sep_tl } }
}
+
+% See <https://github.com/plk/biblatex/blob/e16f4aaa5d9857c7b844bbcbe246f0535fd334e9/tex/latex/biblatex/biblatex.def#L219-L258>
+
\cs_new:Npn \__csl_set_bib_allow_break:
{
\sloppy
@@ -1017,8 +1273,6 @@
\frenchspacing
}
-\cs_new_eq:NN \__csl_set_bib_page_break: \__csl_set_bib_allow_break:
-
\cs_new:Npn \__csl_set_bib_no_break:
{
\sloppy
@@ -1030,6 +1284,13 @@
\frenchspacing
}
+\cs_new:Npn \__csl_set_bib_page_break:
+ {
+ \bool_if:NTF \l__csl_bib_entry_page_break_bool
+ { \__csl_set_bib_allow_break: }
+ { \__csl_set_bib_no_break: }
+ }
+
% Taken from `biblatex`'s \biburlsetup
% https://github.com/plk/biblatex/blob/dev/tex/latex/biblatex/biblatex.def
@@ -1152,7 +1413,7 @@
% \newenvironment{thebibliography}[1]
\RenewDocumentEnvironment { thebibliography } { m }
{
- \__csl_bib_section:
+ \bibsection
\dim_zero:N \parindent
\l__csl_bib_preamble_tl
\tl_if_eq:NnF \l__csl_line_spacing_tl { 1 }
@@ -1178,12 +1439,41 @@
}
+% Bibliography Categories
+
+\prop_new:N \l__csl_categories_prop
+
+% \DeclareBibliographyCategory{⟨category⟩}
+\NewDocumentCommand \DeclareBibliographyCategory { m }
+ {
+ \prop_put:Nnn \l__csl_categories_prop { #1 } { }
+ }
+
+% \addtocategory{⟨category⟩}{⟨keys⟩}
+\NewDocumentCommand \addtocategory { m m }
+ {
+ \prop_get:NnNTF \l__csl_categories_prop {#1} \l_tmpa_tl
+ {
+ \tl_if_empty:NF \l_tmpa_tl
+ { \tl_put_right:Nn \l_tmpa_tl { , } }
+ \tl_put_right:Nn \l_tmpa_tl {#2}
+ \prop_put:NnV \l__csl_categories_prop {#1} \l_tmpa_tl
+ }
+ {
+ \msg_error:nnn { citation-style-language } { category-not-declared }
+ {#1}
+ }
+ }
+
+
+\msg_new:nnn { citation-style-language } { category-not-declared }
+ { Category~ '#1'~ not~ declared. }
+
% Compatibilities with other packages
% babel
-% The `babel` package redefines \bibcite in the \@begindocumenthook.
% This should be disabled.
\AtEndOfPackageFile* { babel }
{
@@ -1194,9 +1484,9 @@
\__csl_no_cite:n {#1}
\@safe@activesfalse
}
- \cs_set_eq:NN \bibcite \__csl_bibcite:nn
\cs_set_eq:NN \bbl@cite@choice \relax
- \cs_set_eq:NN \@bibitem \__csl_bibitem:n
+ \cs_set_eq:NN \@lbibitem \__csl_lbibitem_plain:nn
+ \cs_set_eq:NN \@bibitem \__csl_bibitem_plain:n
}
@@ -1216,12 +1506,54 @@
% The hyperref package also patches \bibcite but it cannot provide hyperlinks
% when used with csl.
+\bool_new:N \l__csl_hyperref_loaded_bool
\AtEndOfPackageFile* { hyperref }
{
- \cs_set_eq:NN \bibcite \__csl_bibcite:nn
- \cs_set_eq:NN \Hy@bibcite \bibcite
- \cs_gset_eq:NN \@lbibitem \__csl_lbibitem:nn
- \cs_gset_eq:NN \@bibitem \__csl_bibitem:n
+ \bool_set_true:N \l__csl_hyperref_loaded_bool
+ % Pakcage "hyperref" redefines \@lbibitem and \bibitem and we need to
+ % recover them.
+ \cs_gset_eq:NN \@lbibitem \__csl_lbibitem:
+ \cs_gset_eq:NN \@bibitem \__csl_bibitem:
+ \cs_gset_eq:NN \__csl_lbibitem_plain:nn \__csl_hyperref_lbibitem:nn
+ \cs_gset_eq:NN \__csl_bibitem_plain:n \__csl_hyperref_bibitem:n
+ \cs_gset_eq:NN \cslcite \__csl_hyperref_cite_item:nn
+ }
+
+\cs_set:Npn \__csl_hyperref_cite_item:nn #1#2
+ { \hyper@@link [ cite ] { } { cite. #1 \@extra@b@citeb } { #2 } }
+
+\cs_new:Npn \__csl_hyperref_lbibitem:nn [#1]#2
+ {
+ \clist_gput_right:Nn \g__csl_bib_items_clist {#2}
+ \@skiphyperreftrue
+ \H@item[%
+ \ifx\Hy@raisedlink\@empty
+ \hyper@anchorstart{cite.#2\@extra@b@citeb}%
+ \@BIBLABEL{#1}%
+ \hyper@anchorend
+ \else
+ \Hy@raisedlink{%
+ \hyper@anchorstart{cite.#2\@extra@b@citeb}\hyper@anchorend
+ }%
+ \@BIBLABEL{#1}%
+ \fi
+ \hfill
+ ]%
+ \@skiphyperreffalse
+ \ignorespaces
+ }
+
+\cs_new:Npn \__csl_hyperref_bibitem:n #1
+ {
+ \clist_gput_right:Nn \g__csl_bib_items_clist {#1}
+ \@skiphyperreftrue \H@item \@skiphyperreffalse
+ \Hy@raisedlink
+ {
+ \hyper@anchorstart
+ { cite. #1 \@extra@b@citeb } \relax
+ \hyper@anchorend
+ }
+ \ignorespaces
}