diff --git a/CHANGELOG.md b/CHANGELOG.md index bc1c38b9..d7baf19b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add support for multiple bibliographies (`refsection` environment). - Add global `ref-section` option. +### Fixed + +- Fix an error of empty locator in citation (([#70](https://github.com/zepinglee/citeproc-lua/discussions/70))) + ## [0.5.1] - 2024-07-10 ### Fixed diff --git a/citeproc/citeproc-element.lua b/citeproc/citeproc-element.lua index 2fb19b48..18d92b33 100644 --- a/citeproc/citeproc-element.lua +++ b/citeproc/citeproc-element.lua @@ -384,10 +384,20 @@ function Element:apply_strip_periods(str) end +---@param number string Non-empty string +---@param variable string +---@param form string +---@param context Context +---@return string function Element:format_number(number, variable, form, context) number = util.strip(number) if variable == "locator" then - variable = context:get_variable("label") + local locator_variable = context:get_variable("label") + if not locator_variable or type(locator_variable) ~= "string" then + util.error("Invalid locator label") + locator_variable = "page" + end + variable = locator_variable end form = form or "numeric" local number_part_list = self:split_number_parts_lpeg(number, context) @@ -431,9 +441,11 @@ function Element:format_number(number, variable, form, context) return res end ----comment ----@param number any ----@param context any +---@alias NumberToken {type: string, value: string, delimiter_type: string} + +---@param number string +---@param context Context +---@return NumberToken[] function Element:parse_number_tokens(number, context) local and_text = "and" local and_symbol = "&" @@ -465,10 +477,15 @@ function Element:parse_number_tokens(number, context) value = token, } end - local grammer = l.Ct(token_patt * (delimiter * token_patt)^0) + local grammer = l.Ct((token_patt * (delimiter * token_patt)^0)^-1) local tokens = grammer:match(number) -- util.debug(tokens) + if not tokens then + return {} + end + ---@cast tokens NumberToken[] + for i, token in ipairs(tokens) do if token.type == "string" then token.value = string.gsub(token.value, "\\%-", "-") diff --git a/citeproc/citeproc-node-choose.lua b/citeproc/citeproc-node-choose.lua index b3c827dc..7f89cb4e 100644 --- a/citeproc/citeproc-node-choose.lua +++ b/citeproc/citeproc-node-choose.lua @@ -283,6 +283,10 @@ function If:evaluate_condition(condition, state, context) return self:is_uncertain_date(value) elseif condition.condition == "locator" then + local locator = context:get_variable("locator") + if not locator or locator == "" then + return false + end local locator_label = context:get_variable("label") if locator_label == "sub verbo" then locator_label = "sub-verbo" diff --git a/citeproc/citeproc-node-number.lua b/citeproc/citeproc-node-number.lua index b8a55d3c..0be68cba 100644 --- a/citeproc/citeproc-node-number.lua +++ b/citeproc/citeproc-node-number.lua @@ -59,8 +59,9 @@ function Number:build_ir(engine, state, context) local number if not state.suppressed[self.variable] then number = context:get_variable(self.variable, self.form) + ---@cast number string | number? end - if not number then + if not number or number == "" then local ir = Rendered:new({}, self) ir.group_var = GroupVar.Missing return ir diff --git a/citeproc/citeproc-node-text.lua b/citeproc/citeproc-node-text.lua index 99b20f81..c3f6af2e 100644 --- a/citeproc/citeproc-node-text.lua +++ b/citeproc/citeproc-node-text.lua @@ -86,6 +86,7 @@ function Text:build_ir(engine, state, context) if self.variable then ir = self:build_variable_ir(engine, state, context) elseif self.macro then + -- util.debug(self.macro) ir = self:build_macro_ir(engine, state, context) elseif self.term then ir = self:build_term_ir(engine, state, context) @@ -108,9 +109,10 @@ function Text:build_variable_ir(engine, state, context) if not state.suppressed[variable] then text = context:get_variable(variable, self.form) + ---@case text string | number? end - if not text then + if not text or text == "" then local ir = Rendered:new({}, self) ir.group_var = GroupVar.Missing return ir diff --git a/tests/fixtures/local/locator_EmptyLocator.txt b/tests/fixtures/local/locator_EmptyLocator.txt new file mode 100644 index 00000000..170a4f48 --- /dev/null +++ b/tests/fixtures/local/locator_EmptyLocator.txt @@ -0,0 +1,86 @@ +>>===== MODE =====>> +citation +<<===== MODE =====<< + + + +>>===== DESCRIPTION =====>> + +<<===== DESCRIPTION =====<< + + + +>>===== RESULT =====>> +(Doe, condition false: Title Page) +<<===== RESULT =====<< + + +>>==== CITATION-ITEMS ====>> +[ + [ + { + "id": "ITEM-1", + "label": "page", + "locator": "" + } + ] +] +<<==== CITATION-ITEMS ====<< + + +>>===== CSL =====>> + + +<<===== CSL =====<< + + +>>===== INPUT =====>> +[ + { + "id": "ITEM-1", + "type": "book", + "author": [ + { + "family": "Doe", + "given": "John" + } + ], + "title": "Title" + } +] +<<===== INPUT =====<< + + +>>===== VERSION =====>> +1.0 +<<===== VERSION =====<< diff --git a/tests/latex/luatex-1/issue-70.lvt b/tests/latex/luatex-1/issue-70.lvt new file mode 100644 index 00000000..d29198bb --- /dev/null +++ b/tests/latex/luatex-1/issue-70.lvt @@ -0,0 +1,20 @@ +% + +\input{regression-test} +\documentclass{article} +\input{csl-test} + +\usepackage[style=chicago-fullnote-bibliography]{citation-style-language} +\cslsetup{regression-test = true} +\addbibresource{test.json} + + +\begin{document} +\START + +\TEST{Citation with empty locator}{ + \cite[page = ]{ITEM-1} +} + +\OMIT +\end{document} diff --git a/tests/latex/luatex-1/issue-70.tlg b/tests/latex/luatex-1/issue-70.tlg new file mode 100644 index 00000000..a53cab9f --- /dev/null +++ b/tests/latex/luatex-1/issue-70.tlg @@ -0,0 +1,20 @@ +This is a generated file for the l3build validation system. +Don't change this file in any respect. +============================================================ +TEST 1: Citation with empty locator +============================================================ +> \l__csl_citation_info_tl=citationID={ITEM-1@1},citationItems={{id={ITEM-1},label={page},locator={}}},properties={noteIndex={1}}. + } +l. ...} +> \l__csl_citation_tl=Bruce D’Arcus, \textit {Boundaries of Dissent: Protest and State Power in the Media Age} (Routledge, 2005).. + } +l. ...} +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <7> on input line .... +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <5> on input line .... +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <8> on input line .... +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <6> on input line .... +============================================================ diff --git a/tests/latex/luatex-2/issue-70.lvt b/tests/latex/luatex-2/issue-70.lvt new file mode 100644 index 00000000..d29198bb --- /dev/null +++ b/tests/latex/luatex-2/issue-70.lvt @@ -0,0 +1,20 @@ +% + +\input{regression-test} +\documentclass{article} +\input{csl-test} + +\usepackage[style=chicago-fullnote-bibliography]{citation-style-language} +\cslsetup{regression-test = true} +\addbibresource{test.json} + + +\begin{document} +\START + +\TEST{Citation with empty locator}{ + \cite[page = ]{ITEM-1} +} + +\OMIT +\end{document} diff --git a/tests/latex/luatex-2/issue-70.tlg b/tests/latex/luatex-2/issue-70.tlg new file mode 100644 index 00000000..a53cab9f --- /dev/null +++ b/tests/latex/luatex-2/issue-70.tlg @@ -0,0 +1,20 @@ +This is a generated file for the l3build validation system. +Don't change this file in any respect. +============================================================ +TEST 1: Citation with empty locator +============================================================ +> \l__csl_citation_info_tl=citationID={ITEM-1@1},citationItems={{id={ITEM-1},label={page},locator={}}},properties={noteIndex={1}}. + } +l. ...} +> \l__csl_citation_tl=Bruce D’Arcus, \textit {Boundaries of Dissent: Protest and State Power in the Media Age} (Routledge, 2005).. + } +l. ...} +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <7> on input line .... +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <5> on input line .... +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <8> on input line .... +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <6> on input line .... +============================================================ diff --git a/tests/latex/pdftex-1/issue-70.lvt b/tests/latex/pdftex-1/issue-70.lvt new file mode 100644 index 00000000..d29198bb --- /dev/null +++ b/tests/latex/pdftex-1/issue-70.lvt @@ -0,0 +1,20 @@ +% + +\input{regression-test} +\documentclass{article} +\input{csl-test} + +\usepackage[style=chicago-fullnote-bibliography]{citation-style-language} +\cslsetup{regression-test = true} +\addbibresource{test.json} + + +\begin{document} +\START + +\TEST{Citation with empty locator}{ + \cite[page = ]{ITEM-1} +} + +\OMIT +\end{document} diff --git a/tests/latex/pdftex-1/issue-70.tlg b/tests/latex/pdftex-1/issue-70.tlg new file mode 100644 index 00000000..ebf2464e --- /dev/null +++ b/tests/latex/pdftex-1/issue-70.tlg @@ -0,0 +1,21 @@ +This is a generated file for the l3build validation system. +Don't change this file in any respect. +============================================================ +TEST 1: Citation with empty locator +============================================================ +> \l__csl_citation_info_tl=citationID={ITEM-1@1},citationItems={{id={ITEM-1},label={page},locator={}}},properties={noteIndex={1}}. + } +l. ...} +LaTeX Warning: Citation `ITEM-1' on page 1 undefined on input line .... +> \l__csl_citation_tl=[\textbf {ITEM-1}]. + } +l. ...} +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <7> on input line .... +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <5> on input line .... +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <8> on input line .... +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <6> on input line .... +============================================================ diff --git a/tests/latex/pdftex-2/issue-70.lvt b/tests/latex/pdftex-2/issue-70.lvt new file mode 100644 index 00000000..d29198bb --- /dev/null +++ b/tests/latex/pdftex-2/issue-70.lvt @@ -0,0 +1,20 @@ +% + +\input{regression-test} +\documentclass{article} +\input{csl-test} + +\usepackage[style=chicago-fullnote-bibliography]{citation-style-language} +\cslsetup{regression-test = true} +\addbibresource{test.json} + + +\begin{document} +\START + +\TEST{Citation with empty locator}{ + \cite[page = ]{ITEM-1} +} + +\OMIT +\end{document} diff --git a/tests/latex/pdftex-2/issue-70.tlg b/tests/latex/pdftex-2/issue-70.tlg new file mode 100644 index 00000000..a53cab9f --- /dev/null +++ b/tests/latex/pdftex-2/issue-70.tlg @@ -0,0 +1,20 @@ +This is a generated file for the l3build validation system. +Don't change this file in any respect. +============================================================ +TEST 1: Citation with empty locator +============================================================ +> \l__csl_citation_info_tl=citationID={ITEM-1@1},citationItems={{id={ITEM-1},label={page},locator={}}},properties={noteIndex={1}}. + } +l. ...} +> \l__csl_citation_tl=Bruce D’Arcus, \textit {Boundaries of Dissent: Protest and State Power in the Media Age} (Routledge, 2005).. + } +l. ...} +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <7> on input line .... +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <5> on input line .... +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <8> on input line .... +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <6> on input line .... +============================================================