texlive[72038] Master/texmf-dist: citation-style-language (15aug24)
commits+karl at tug.org
commits+karl at tug.org
Thu Aug 15 22:01:24 CEST 2024
Revision: 72038
https://tug.org/svn/texlive?view=revision&revision=72038
Author: karl
Date: 2024-08-15 22:01:24 +0200 (Thu, 15 Aug 2024)
Log Message:
-----------
citation-style-language (15aug24)
Modified Paths:
--------------
trunk/Master/texmf-dist/doc/latex/citation-style-language/CHANGELOG.md
trunk/Master/texmf-dist/doc/latex/citation-style-language/citation-style-language-doc.pdf
trunk/Master/texmf-dist/doc/latex/citation-style-language/citation-style-language-doc.tex
trunk/Master/texmf-dist/doc/man/man1/citeproc-lua.1
trunk/Master/texmf-dist/doc/man/man1/citeproc-lua.man1.pdf
trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-context.lua
trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-element.lua
trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-engine.lua
trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-ir-node.lua
trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-manager.lua
trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-node-bibliography.lua
trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-node-citation.lua
trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-node-text.lua
trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-output.lua
trunk/Master/texmf-dist/scripts/citation-style-language/citeproc.lua
trunk/Master/texmf-dist/tex/latex/citation-style-language/citation-style-language.sty
trunk/Master/texmf-dist/tex/latex/citation-style-language/locales/csl-locales-en-US.xml
trunk/Master/texmf-dist/tex/latex/citation-style-language/locales/csl-locales-zh-TW.xml
trunk/Master/texmf-dist/tex/latex/citation-style-language/styles/american-medical-association.csl
trunk/Master/texmf-dist/tex/latex/citation-style-language/styles/apa.csl
Modified: trunk/Master/texmf-dist/doc/latex/citation-style-language/CHANGELOG.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/citation-style-language/CHANGELOG.md 2024-08-15 20:00:44 UTC (rev 72037)
+++ trunk/Master/texmf-dist/doc/latex/citation-style-language/CHANGELOG.md 2024-08-15 20:01:24 UTC (rev 72038)
@@ -7,14 +7,22 @@
## [Unreleased]
+## [0.6.1] - 2024-08-15
+
+### Fixed
+
+- Fix parsing quotation marks ([#71](https://github.com/zepinglee/citeproc-lua/discussions/71)).
+
## [0.6.0] - 2024-07-31
+### Added
+
- 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)))
+- Fix an error of empty locator in citation ([#70](https://github.com/zepinglee/citeproc-lua/discussions/70)).
## [0.5.1] - 2024-07-10
@@ -212,7 +220,8 @@
- Initial CTAN release.
-[Unreleased]: https://github.com/zepinglee/citeproc-lua/compare/v0.6.0...HEAD
+[Unreleased]: https://github.com/zepinglee/citeproc-lua/compare/v0.6.1...HEAD
+[0.6.1]: https://github.com/zepinglee/citeproc-lua/compare/v0.6.0...v0.6.1
[0.6.0]: https://github.com/zepinglee/citeproc-lua/compare/v0.5.1...v0.6.0
[0.5.1]: https://github.com/zepinglee/citeproc-lua/compare/v0.5.0...v0.5.1
[0.5.0]: https://github.com/zepinglee/citeproc-lua/compare/v0.4.9...v0.5.0
Modified: trunk/Master/texmf-dist/doc/latex/citation-style-language/citation-style-language-doc.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/citation-style-language/citation-style-language-doc.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/citation-style-language/citation-style-language-doc.tex 2024-08-15 20:00:44 UTC (rev 72037)
+++ trunk/Master/texmf-dist/doc/latex/citation-style-language/citation-style-language-doc.tex 2024-08-15 20:01:24 UTC (rev 72038)
@@ -51,7 +51,7 @@
}%
}
-\date{2024-07-31 v0.6.0}
+\date{2024-08-15 v0.6.1}
\maketitle
Modified: trunk/Master/texmf-dist/doc/man/man1/citeproc-lua.1
===================================================================
--- trunk/Master/texmf-dist/doc/man/man1/citeproc-lua.1 2024-08-15 20:00:44 UTC (rev 72037)
+++ trunk/Master/texmf-dist/doc/man/man1/citeproc-lua.1 2024-08-15 20:01:24 UTC (rev 72038)
@@ -1,4 +1,4 @@
-.TH citeproc-lua 1 "0.6.0"
+.TH citeproc-lua 1 "0.6.1"
.SH NAME
citeproc-lua \- make CSL citations and bibliography for LaTeX
.SH SYNOPSIS
Modified: trunk/Master/texmf-dist/doc/man/man1/citeproc-lua.man1.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-context.lua
===================================================================
--- trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-context.lua 2024-08-15 20:00:44 UTC (rev 72037)
+++ trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-context.lua 2024-08-15 20:01:24 UTC (rev 72038)
@@ -23,9 +23,11 @@
--- at class Context
--- at field reference ItemData?
---- at field format any
+--- at field format OutputFormat
--- at field cite_id string?
+--- at field engine CiteProc
--- at field style any Style
+--- at field lang LanguageCode
--- at field locale Locale?
--- at field name_citation any
--- at field names_delimiter any
@@ -60,6 +62,7 @@
function Context:new()
local o = {
+ lang = "en-US",
in_bibliography = false
}
setmetatable(o, self)
@@ -348,6 +351,9 @@
end
+--- at class IrState
+--- at field macro_stack string[]
+--- at field suppressed {[string]: boolean}
local IrState = {}
function IrState:new(style, cite_id, cite, reference)
Modified: trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-element.lua
===================================================================
--- trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-element.lua 2024-08-15 20:00:44 UTC (rev 72037)
+++ trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-element.lua 2024-08-15 20:01:24 UTC (rev 72038)
@@ -245,6 +245,9 @@
return ir
end
+--- at param str string
+--- at param context Context
+--- at return InlineElement[]
function Element:render_text_inlines(str, context)
if str == "" then
return {}
Modified: trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-engine.lua
===================================================================
--- trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-engine.lua 2024-08-15 20:00:44 UTC (rev 72037)
+++ trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-engine.lua 2024-08-15 20:01:24 UTC (rev 72038)
@@ -101,6 +101,7 @@
--- at field opt table
--- at field registry Registry
--- at field cite_first_note_numbers table<ItemId, NoteIndex>
+--- at field locale_tags_info_dict {[LanguageCode]: table}
local CiteProc = {}
--- at class CiteProcSys
@@ -179,6 +180,8 @@
o.person_names = {}
o.person_names_by_output = {}
+ o.locale_tags_info_dict = {}
+
setmetatable(o, { __index = CiteProc })
return o
end
@@ -420,12 +423,21 @@
cite_item.label = "page"
end
+ local the_context = Context:new()
+ the_context.engine = self
+ the_context.style = self.style
+ the_context.area = self
+ the_context.in_bibliography = false
+ the_context.lang = self.lang
+ the_context.locale = self:get_locale(self.lang)
+ the_context.format = self.output_format
+
if cite_item.prefix then
-- Assert CSL rich-text or HTML-like tagged string
if cite_item.prefix == "" then
cite_item.prefix = nil
else
- cite_item.prefix_inlines = InlineElement:parse(cite_item.prefix, nil, true)
+ cite_item.prefix_inlines = InlineElement:parse(cite_item.prefix, the_context, true)
end
end
if cite_item.suffix then
@@ -432,7 +444,7 @@
if cite_item.suffix == "" then
cite_item.suffix = nil
else
- cite_item.suffix_inlines = InlineElement:parse(cite_item.suffix, nil, true)
+ cite_item.suffix_inlines = InlineElement:parse(cite_item.suffix, the_context, true)
end
end
@@ -1065,6 +1077,7 @@
context.style = self.style
context.area = self.style.bibliography
context.in_bibliography = true
+ context.lang = self.lang
context.locale = self:get_locale(self.lang)
context.name_inheritance = self.style.bibliography.name_inheritance
context.format = SortStringFormat:new()
@@ -1177,6 +1190,10 @@
return o
end
+--- at param engine CiteProc
+--- at param state IrState
+--- at param context Context
+--- at return IrNode?
function Macro:build_ir(engine, state, context)
local ir = self:build_group_ir(engine, state, context)
return ir
Modified: trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-ir-node.lua
===================================================================
--- trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-ir-node.lua 2024-08-15 20:00:44 UTC (rev 72037)
+++ trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-ir-node.lua 2024-08-15 20:01:24 UTC (rev 72038)
@@ -32,6 +32,8 @@
--- at field text string?
--- at field formatting any
--- at field affixes any
+--- at field display any
+--- at field quotes LocalizedQuotes
--- at field inlines InlineElement[]?
--- at field children IrNode[]?
--- at field delimiter string?
Modified: trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-manager.lua
===================================================================
--- trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-manager.lua 2024-08-15 20:00:44 UTC (rev 72037)
+++ trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-manager.lua 2024-08-15 20:01:24 UTC (rev 72038)
@@ -292,7 +292,6 @@
--- at param citeproc_sys CiteProcSys
function RefSection:_check_dependent_style(citeproc_sys)
if self.engine:is_dependent_style() then
- local default_locale = self.engine.style.default_locale;
local parent_style_link = self.engine:get_independent_parent()
if not parent_style_link then
return nil
@@ -304,14 +303,16 @@
util.error(string.format("Failed to load style '%s.csl'", parent_style_id))
return nil
end
+ local default_locale = self.engine.style.default_locale;
local force_lang = false
if self.lang and self.lang ~= "" then
force_lang = true
+ elseif default_locale and default_locale ~= "" then
+ self.lang = default_locale
else
self.lang = nil
end
self.engine = citeproc.new(citeproc_sys, style, self.lang, force_lang)
- self.engine.style.default_locale = default_locale
end
end
Modified: trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-node-bibliography.lua
===================================================================
--- trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-node-bibliography.lua 2024-08-15 20:00:44 UTC (rev 72037)
+++ trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-node-bibliography.lua 2024-08-15 20:01:24 UTC (rev 72038)
@@ -118,7 +118,6 @@
context.style = engine.style
context.area = self
context.in_bibliography = true
- -- context.locale = engine:get_locale(engine.lang)
context.name_inheritance = self.name_inheritance
context.format = output_format
context.id = id
@@ -127,6 +126,7 @@
-- CSL-M: `layout` extension
local active_layout, context_lang = util.get_layout_by_language(self, engine, context.reference)
+ context.lang = context_lang
context.locale = engine:get_locale(context_lang)
local ir = self:build_ir(engine, state, context, active_layout)
Modified: trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-node-citation.lua
===================================================================
--- trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-node-citation.lua 2024-08-15 20:00:44 UTC (rev 72037)
+++ trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-node-citation.lua 2024-08-15 20:01:24 UTC (rev 72038)
@@ -255,6 +255,7 @@
context.style = engine.style
context.area = self
context.in_bibliography = false
+ context.lang = engine.lang
context.locale = engine:get_locale(engine.lang)
context.name_inheritance = self.name_inheritance
context.format = output_format
@@ -394,6 +395,7 @@
context.style = engine.style
context.area = self
context.in_bibliography = false
+ context.lang = engine.lang
context.locale = engine:get_locale(engine.lang)
context.name_inheritance = self.name_inheritance
context.format = SortStringFormat:new()
@@ -456,7 +458,6 @@
context.engine = engine
context.style = engine.style
context.area = self
- -- context.locale = engine:get_locale(engine.lang)
context.name_inheritance = self.name_inheritance
context.format = output_format
context.id = cite_item.id
@@ -465,6 +466,7 @@
context.reference = engine.registry.registry[cite_item.id]
local active_layout, context_lang = util.get_layout_by_language(self, engine, context.reference)
+ context.lang = context_lang
context.locale = engine:get_locale(context_lang)
local ir
Modified: trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-node-text.lua
===================================================================
--- trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-node-text.lua 2024-08-15 20:00:44 UTC (rev 72037)
+++ trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-node-text.lua 2024-08-15 20:01:24 UTC (rev 72038)
@@ -229,7 +229,12 @@
end
function Text:build_macro_ir(engine, state, context)
+ --- at type Macro
local macro = context:get_macro(self.macro)
+ if not macro then
+ util.error(string.format("Macro '%s' not found", self.macro))
+ return nil
+ end
-- util.debug(string.format('<macro name="%s">', self.macro))
state:push_macro(self.macro)
local ir = macro:build_ir(engine, state, context)
Modified: trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-output.lua
===================================================================
--- trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-output.lua 2024-08-15 20:00:44 UTC (rev 72037)
+++ trunk/Master/texmf-dist/scripts/citation-style-language/citeproc-output.lua 2024-08-15 20:01:24 UTC (rev 72038)
@@ -101,12 +101,15 @@
end
text = text .. self._type
if self.formatting then
- text = text .. "["
+ text = text .. " ["
for attr, value in pairs(self.formatting) do
text = text .. attr .. '="' .. value .. '"'
end
- text = text .. "]"
+ text = text .. "] "
end
+ if self.is_inner then
+ text = text .. " [inner quotes]"
+ end
text = text .. "("
if self.value then
text = text .. '"' .. self.value .. '"'
@@ -167,16 +170,17 @@
--- at class Quoted: InlineElement
--- at field is_inner boolean
---- at field quotes table
+--- at field quotes LocalizedQuotes
local Quoted = InlineElement:derive("Quoted")
--- at param inlines InlineElement[]
---- at param localized_quotes table?
+--- at param localized_quotes LocalizedQuotes?
+--- at param is_inner boolean?
--- at return Quoted
-function Quoted:new(inlines, localized_quotes)
+function Quoted:new(inlines, localized_quotes, is_inner)
local o = InlineElement.new(self)
o.inlines = inlines
- o.is_inner = false
+ o.is_inner = is_inner or false
if localized_quotes then
o.quotes = localized_quotes
else
@@ -410,224 +414,457 @@
return inlines
end
-local function tokens2inlines(tokens)
- local inlines = {}
- local i = 1
- while i <= #tokens do
- local token = tokens[i]
- if type(token) == "string" then
- local text = token
- local j = i + 1
- while j <= #tokens and type(tokens[j]) == "string" do
- text = text .. tokens[j]
- j = j + 1
- end
- i = j
- table.insert(inlines, PlainText:new(text))
- else
- table.insert(inlines, token)
- i = i + 1
+
+local P = lpeg.P
+local Ct = lpeg.Ct
+local Cp = lpeg.Cp
+
+-- Lua's regex doesn't support groups and thus we have to implement the same
+-- logic with `lpeg`.
+local code_pattern =
+ Ct(Cp() * P("<code>") * Cp()) * ((1 - P("</code>")) ^ 0) *
+ Ct(Cp() * P("</code>") * Cp())
+ + Ct(Cp() * P("<script>") * Cp()) * ((1 - P("</script>")) ^ 0) *
+ Ct(Cp() * P("</script>") * Cp())
+ + Ct(Cp() * P("<pre>") * Cp()) * ((1 - P("</pre>")) ^ 0) *
+ Ct(Cp() * P("</pre>") * Cp())
+ + Ct(Cp() * P("<math>") * Cp()) * ((1 - P("</math>")) ^ 0) * Ct(Cp() * P("</math>") * Cp())
+ + Ct(Cp() * P("<math-tex>") * Cp()) * ((1 - P("</math-tex>")) ^ 0) * Ct(Cp() * P("</math-tex>") * Cp())
+local basic_tag_pattern = P '<span class="nocase">'
+ + P '<span class="nodecor">'
+ + P '<span style="font-variant:small-caps;">'
+ + P '<sc>'
+ + P '<i>'
+ + P '<b>'
+ + P '<sup>'
+ + P '<sub>'
+ + P ' "'
+ + P " '"
+ + P '("'
+ + P "('"
+ + P "“"
+ + P "‘"
+ + P '</span>'
+ + P '</sc>'
+ + P '</i>'
+ + P '</b>'
+ + P '</sup>'
+ + P '</sub>'
+ + P '"'
+ + P "'"
+ + P "”"
+ + P "’"
+
+local default_tag_pattern = Ct((code_pattern + Ct(Cp() * basic_tag_pattern * Cp()) + P(1)) ^ 0)
+
+local default_openers_info = {
+ ['<span class="nocase">'] = {
+ closer = "</span>",
+ quotes = false,
+ },
+ ['<span class="nodecor">'] = {
+ closer = "</span>",
+ quotes = false,
+ },
+ ['<span style="font-variant:small-caps;">'] = {
+ closer = "</span>",
+ quotes = false,
+ },
+ ['<sc>'] = {
+ closer = "</sc>",
+ quotes = false,
+ },
+ ['<i>'] = {
+ closer = "</i>",
+ quotes = false,
+ },
+ ['<b>'] = {
+ closer = "</b>",
+ quotes = false,
+ },
+ ['<sup>'] = {
+ closer = "</sup>",
+ quotes = false,
+ },
+ ['<sub>'] = {
+ closer = "</sub>",
+ quotes = false,
+ },
+ [' "'] = {
+ closer = '"',
+ quotes = true,
+ },
+ [" '"] = {
+ closer = "'",
+ quotes = true,
+ },
+ ["“"] = {
+ closer = "”",
+ quotes = true,
+ },
+ ["‘"] = {
+ closer = "’",
+ quotes = true,
+ },
+ ['<code>'] = {
+ closer = "</code>",
+ quotes = false,
+ },
+ ['<script>'] = {
+ closer = "</script>",
+ quotes = false,
+ },
+ ['<pre>'] = {
+ closer = "</pre>",
+ quotes = false,
+ },
+ ['<math>'] = {
+ closer = "</math>",
+ quotes = false,
+ },
+ ['<math-tex>'] = {
+ closer = "</math-tex>",
+ quotes = false,
+ },
+}
+
+local function _quoted(str)
+ str = string.gsub(str, "'", "\'")
+ return string.format("'%s'", str)
+end
+
+--- at param locale string
+--- at param context Context
+local function make_locale_tag_info(locale, context)
+ if context.engine.locale_tags_info_dict[locale] then
+ return
+ end
+ local localed_quotes = context:get_localized_quotes()
+
+ local tag_pattern = basic_tag_pattern
+ local openers_info = util.deep_copy(default_openers_info)
+
+ if localed_quotes.outer_open and localed_quotes.outer_close then
+ tag_pattern = tag_pattern + P(_quoted(localed_quotes.outer_open))
+ tag_pattern = tag_pattern + P(_quoted(localed_quotes.outer_close))
+
+ openers_info[localed_quotes.outer_open] = {
+ closer = localed_quotes.outer_close,
+ quotes = true,
+ inner = false
+ }
+ end
+
+ if localed_quotes.inner_open and localed_quotes.inner_close then
+ tag_pattern = tag_pattern + P(_quoted(localed_quotes.inner_open))
+ tag_pattern = tag_pattern + P(_quoted(localed_quotes.inner_close))
+
+ openers_info[localed_quotes.inner_open] = {
+ closer = localed_quotes.inner_close,
+ quotes = true,
+ inner = true
+ }
+ end
+
+ context.engine.locale_tags_info_dict[locale] = {
+ tag_pattern = Ct((code_pattern + Ct(Cp() * tag_pattern * Cp()) + P(1)) ^ 0),
+ openers_info = openers_info,
+ }
+end
+
+
+local straight_quotes_flip = {
+ [" '"] = ' "',
+ [' "'] = " '",
+};
+
+--- at param str any
+--- at param context Context?
+--- at return string[]
+--- at return string[]
+local function split_tags_and_strings(str, context)
+ local tags = {}
+ local strings = {}
+
+ str = string.gsub(str, '(<span)%s+(style="font%-variant:)%s*(small%-caps);?"[^>]*(>)', '%1 %2%3;"%4');
+
+ str = string.gsub(str, '(<span)%s+(class="nocase")[^>]*(>)', "%1 %2%3");
+ str = string.gsub(str, '(<span)%s+(class="nodecor")[^>]*(>)', "%1 %2%3");
+
+ local tag_pattern = default_tag_pattern
+ local openers_info = default_openers_info
+ if context and context.lang then
+ tag_pattern = context.engine.locale_tags_info_dict[context.lang].tag_pattern
+ end
+
+ local tag_positions_list = lpeg.match(tag_pattern, str)
+ if not tag_positions_list then
+ error('Pattern not match')
+ end
+ local start = 1
+ local stop = 1
+ local new_stop = 1
+ for _, postion_tuple in ipairs(tag_positions_list) do
+ start, new_stop = table.unpack(postion_tuple)
+ table.insert(strings, string.sub(str, stop, start - 1))
+ table.insert(tags, string.sub(str, start, new_stop - 1))
+ stop = new_stop
+ end
+ table.insert(strings, string.sub(str, stop, -1))
+
+ for i, tag in ipairs(tags) do
+ if string.match(tag, "^.['\"]$") then
+ strings[i] = strings[i] .. string.sub(tag, 1, 1)
+ tags[i] = " " .. string.sub(tag, 2)
+ elseif (tag == "'" or tag == '"') and strings[i] == "" and (i == 1 or openers_info[tags[i - 1]]) then
+ -- See `bugreports_NoCaseEscape.txt`.
+ -- '"PIAAC-Longitudinal (PIAAC-L) 2015"'
+ -- <span class=\"nocase\">\"PIAAC-Longitudinal (PIAAC-Lx) 2015\"</span>
+ tags[i] = " " .. tag
end
end
- return inlines
+
+ return tags, strings
end
-local function get_inline_element_grammar()
- local P = lpeg.P
- local C = lpeg.C
- local Ct = lpeg.Ct
- local S = lpeg.S
- local V = lpeg.V
- local spaces = P(" ")^1
- local grammar = P{
- "content";
- token = V"italic" + V"bold" + V"sup" + V"sub" + V"sc" + V"small_caps" + V"span_nocase" + V"nodecor" + V"math_tex" + V"math_ml" + V"code" + V"script" + C(1),
- content = Ct((V"token")^0) / tokens2inlines,
- italic = P"<i>" * Ct((V"token" - P"</i>")^0) * P"</i>" / function (tokens)
- return Formatted:new(tokens2inlines(tokens), {["font-style"] = "italic"})
- end,
- bold = P"<b>" * Ct((V"token" - P"</b>")^0) * P"</b>" / function (tokens)
- return Formatted:new(tokens2inlines(tokens), {["font-weight"] = "bold"})
- end,
- sup = P"<sup>" * Ct((V"token" - P"</sup>")^0) * P"</sup>" / function (tokens)
- return Formatted:new(tokens2inlines(tokens), {["vertical-align"] = "sup"})
- end,
- sub = P"<sub>" * Ct((V"token" - P"</sub>")^0) * P"</sub>" / function (tokens)
- return Formatted:new(tokens2inlines(tokens), {["vertical-align"] = "sub"})
- end,
- sc = P"<sc>" * Ct((V"token" - P"</sc>")^0) * P"</sc>" / function (tokens)
- return Formatted:new(tokens2inlines(tokens), {["font-variant"] = "small-caps"})
- end,
- quoted = (
- C(P'"') * Ct((V"token" - P'"')^0) * C(P'"')
- + C(P"'") * Ct((V"token" - P"'")^0) * C(P"'")
- + C(P'“') * Ct((V"token" - P'”')^0) * C(P'”')
- + C(P"‘") * Ct((V"token" - P"’")^0) * C(P"’")
- + C(P"«") * Ct((V"token" - P"»")^0) * C(P"»")
- ) / function (open, tokens, close)
- return Quoted:new(tokens2inlines(tokens), LocalizedQuotes:new(open, close))
- end,
- small_caps = P"<span" * spaces * P'style="font-variant:' * spaces^0 * P'small-caps;">' * Ct((V"token" - P"</span>")^0) * P"</span>" / function (tokens)
- return Formatted:new(tokens2inlines(tokens), {["font-variant"] = "small-caps"})
- end,
- -- nocase = P"<nocase>" * Ct((V"token" - P"</nocase>")^0) * P"</nocase>" / function (tokens)
- -- return NoCase:new(tokens2inlines(tokens))
- -- end,
- span_nocase = P"<span" * spaces * P'class="nocase">' * Ct((V"token" - P"</span>")^0) * P"</span>" / function (tokens)
- return NoCase:new(tokens2inlines(tokens))
- end,
- nodecor = P"<span" * spaces * P'class="nodecor">' * Ct((V"token" - P"</span>")^0) * P"</span>" / function (tokens)
- return NoDecor:new(tokens2inlines(tokens))
- end,
- math_tex = P"<math-tex>" * C((1- P"</math-tex>")^0) * P"</math-tex>" / function (text)
- return MathTeX:new(text)
- end,
- math_ml = P"<math>" * C((1- P"</math>")^0) * P"</math>" / function (text)
- return MathML:new(text)
- end,
- code = P"<code>" * C((1 - P"</code>")^0) * P"</code>" / function (text)
- return Code:new(text)
- end,
- script = P"<script>" * C((1- P"</script>")^0) * P"</script>" / function (text)
- return Code:new(text)
- end,
- }
- return grammar
+
+--- at param tag string
+--- at param str string
+--- at return string?
+local function _apostrophe_force(tag, str)
+ if tag == "'" or tag == "’" then
+ if str ~= "" and string.match(str, "^[^,.?:; ]") then
+ return util.unicode["right single quotation mark"]
+ end
+ elseif (tag == " '" or tag == "’") and str ~= "" and string.match(str, "^%s") then
+ return util.unicode["right single quotation mark"]
+ end
+ return nil
end
-local inline_element_grammar = get_inline_element_grammar()
+--- at param quote string
+--- at param openers_info table
+local function set_outer_quote_form(quote, openers_info)
+ openers_info[quote].inner = false;
+ openers_info[straight_quotes_flip[quote]].inner = true;
+end
+
+
+--- at param tag string
+--- at param inlines InlineElement[]
+--- at param openers_info table
+--- at param context Context
+--- at return InlineElement
+local function make_inline_from_tag(tag, inlines, openers_info, context)
+ if tag == '<span class="nocase">' then
+ return NoCase:new(inlines)
+ elseif tag == '<span class="nodecor">' then
+ return NoDecor:new(inlines)
+ elseif tag == '<span style="font-variant:small-caps;">' then
+ return Formatted:new(inlines, {["font-variant"] = "small-caps"})
+ elseif tag == '<sc>' then
+ return Formatted:new(inlines, {["font-variant"] = "small-caps"})
+ elseif tag == '<i>' then
+ return Formatted:new(inlines, {["font-style"] = "italic"})
+ elseif tag == '<b>' then
+ return Formatted:new(inlines, {["font-weight"] = "bold"})
+ elseif tag == '<sup>' then
+ return Formatted:new(inlines, {["vertical-align"] = "sup"})
+ elseif tag == '<sub>' then
+ return Formatted:new(inlines, {["vertical-align"] = "sub"})
+ elseif openers_info[tag] and openers_info[tag].quotes then
+ local localized_quotes = context:get_localized_quotes()
+ return Quoted:new(inlines, localized_quotes, openers_info[tag].inner)
+ elseif tag == "<code>" or tag == "<script>" or tag == "<pre>" then
+ return Code:new(inlines[1].value)
+ elseif tag == "<math>" or tag == "<math-tex>" then
+ return MathTeX:new(inlines[1].value)
+ else
+ error(string.format("Invalid tag '%s'", tag))
+ return PlainText:new("")
+ end
+end
+
+
+--- processTags() in
+--- <https://github.com/Juris-M/citeproc-js/blob/master/src/util_flipflop.js#L474>
--- at param str string
--- at param context Context?
--- at param is_external boolean?
--- at return InlineElement[]
function InlineElement:parse_html_tags(str, context, is_external)
- local inlines = inline_element_grammar:match(str)
- inlines = InlineElement:parse_quotes(inlines, context, is_external)
- return inlines
-end
+ if str == "" then
+ return {}
+ end
--- TODO: Rewrite with lpeg
---- at param inlines InlineElement[]
---- at param context Context
---- at param is_external boolean?
---- at return table
-function InlineElement:parse_quotes(inlines, context, is_external)
- local quote_fragments = InlineElement:get_quote_fragments(inlines)
- -- util.debug(quote_fragments)
+ str = string.gsub(str, "(\u{00ab}) ", "\u{00ab}\u{202f}")
+ str = string.gsub(str, " (\u{00bb})", "\u{202f}%1")
+ str = string.gsub(str, " ([:;?!])", "\u{202f}%1")
+ -- str = " " .. string.gsub(str, util.unicode["right single quotation mark"], "'")
- local quote_stack = {}
- local text_stack = {{}}
-
- local localized_quotes
- if context then
- localized_quotes = context:get_localized_quotes()
- else
- localized_quotes = LocalizedQuotes:new()
+ local openers_info = default_openers_info
+ if context and context.lang then
+ if not context.engine.locale_tags_info_dict[context.lang] then
+ make_locale_tag_info(context.lang, context)
+ end
+ openers_info = context.engine.locale_tags_info_dict[context.lang].openers_info
end
- for _, fragment in ipairs(quote_fragments) do
- local top_text_list = text_stack[#text_stack]
+ local tags, strings = split_tags_and_strings(str, context)
- if type(fragment) == "table" then
- if fragment.inlines then
- fragment.inlines = self:parse_quotes(fragment.inlines, context, is_external)
- end
- table.insert(top_text_list, fragment)
+ -- util.debug(tags)
+ -- util.debug(strings)
- elseif type(fragment) == "string" then
- local quote = fragment
- local top_quote = quote_stack[#quote_stack]
+ -- if #tags == 0 then
+ -- return {PlainText:new(str)}
+ -- end
- if quote == "'" then
- if top_quote == "'" and #top_text_list > 0 then
- table.remove(quote_stack)
- local quoted = Quoted:new(top_text_list, localized_quotes)
- table.remove(text_stack)
- table.insert(text_stack[#text_stack], quoted)
- else
- table.insert(quote_stack, quote)
- table.insert(text_stack, {})
- end
+ --- at type {tag: string, closer: string, pos: number}[]
+ local opener_stack = {}
- elseif quote == '"' then
- if top_quote == '"' then
- table.remove(quote_stack)
- local quoted = Quoted:new(top_text_list, localized_quotes)
- table.remove(text_stack)
- table.insert(text_stack[#text_stack], quoted)
- else
- table.insert(quote_stack, quote)
- table.insert(text_stack, {})
+ for i, tag in ipairs(tags) do
+ -- util.debug(i)
+ -- util.debug(strings[i])
+ -- util.debug(tag)
+ -- util.debug(opener_stack)
+ local apostrophe = _apostrophe_force(tag, strings[i + 1])
+ if apostrophe then
+ strings[i + 1] = apostrophe .. strings[i + 1]
+ tags[i] = "";
+ else
+ local opener_info = openers_info[tag]
+ local last_opener_info = opener_stack[#opener_stack]
+ if opener_info then
+ if opener_info.quotes and last_opener_info and tag == last_opener_info.tag then
+ local pos = last_opener_info.pos
+ strings[pos + 1] = string.gsub(tag, "^%s", "") .. strings[pos + 1]
+ tags[pos] = "";
+ table.remove(opener_stack)
end
-
- elseif quote == util.unicode["left single quotation mark"] or
- quote == util.unicode["left double quotation mark"] or
- quote == util.unicode["left-pointing double angle quotation mark"] then
- table.insert(quote_stack, quote)
- table.insert(text_stack, {})
-
- elseif (quote == util.unicode["right single quotation mark"] and
- top_quote == util.unicode["left single quotation mark"]) or
- (quote == util.unicode["right double quotation mark"] and
- top_quote == util.unicode["left double quotation mark"]) or
- (quote == util.unicode["right-pointing double angle quotation mark"] and
- top_quote == util.unicode["left-pointing double angle quotation mark"]) then
- table.remove(quote_stack)
- if is_external then
- -- The text is from prefix or suffix of citationItem.
- -- See flipflop_LeadingMarkupWithApostrophe.txt
- localized_quotes.outer_open = top_quote
- localized_quotes.outer_close = quote
- localized_quotes.inner_open = top_quote
- localized_quotes.inner_close = quote
+ table.insert(opener_stack, {
+ tag = tag,
+ closer = openers_info[tag].closer,
+ pos = i,
+ })
+ else
+ -- Closer tag
+ if last_opener_info then
+ if last_opener_info.closer == tag then
+ table.remove(opener_stack)
+ else
+ if tag == "'" or tag == "’" then
+ strings[i + 1] = "’" .. strings[i + 1]
+ tags[i] = ""
+ else
+ while #opener_stack > 0 and opener_stack[#opener_stack].closer ~= tag do
+ local pos = opener_stack[#opener_stack].pos
+ strings[pos + 1] = tags[pos] .. strings[pos + 1]
+ tags[pos] = ""
+ table.remove(opener_stack)
+ end
+ if #opener_stack > 0 then
+ table.remove(opener_stack)
+ else
+ strings[i + 1] = tags[i] .. strings[i + 1]
+ tags[i] = ""
+ end
+ end
end
- local quoted = Quoted:new(top_text_list, localized_quotes)
- table.remove(text_stack)
- table.insert(text_stack[#text_stack], quoted)
-
- else
- local last_inline = top_text_list[#top_text_list]
- if last_inline and last_inline._type == "PlainText" then
- last_inline.value = last_inline.value .. fragment
else
- table.insert(top_text_list, PlainText:new(fragment))
+ if tag == "'" or tag == "’" then
+ strings[i + 1] = "’" .. strings[i + 1]
+ tags[i] = ""
+ else
+ strings[i + 1] = tags[i] .. strings[i + 1]
+ tags[i] = ""
+ end
end
end
+ end
+ end
+ -- util.debug(opener_stack)
+
+ -- Process remainders in the stack
+ if #opener_stack > 0 then
+ for _, opener_info in ipairs(opener_stack) do
+ local pos = opener_info.pos
+ local orphan = string.gsub(tags[pos], "^%s", "")
+ orphan = string.gsub(orphan, "'", "’")
+ strings[pos + 1] = orphan .. strings[pos + 1]
+ tags[pos] = ""
end
end
- local elements = text_stack[1]
- if #text_stack > 1 then
- -- assert(#text_stack == #quote_stack + 1)
- for i, quote in ipairs(quote_stack) do
- if quote == "'" then
- quote = util.unicode["apostrophe"]
+ -- Remove empty tag
+ for i = #tags, 1, -1 do
+ local tag = tags[i]
+ if tag == "" then
+ strings[i + 1] = strings[i] .. strings[i + 1]
+ table.remove(strings, i)
+ table.remove(tags, i)
+ end
+ end
+
+ -- The first appearance of straight quote is treated as outer quote.
+ for _, tag in ipairs(tags) do
+ -- util.debug(i)
+ -- util.debug(tag)
+ if straight_quotes_flip[tag] then
+ set_outer_quote_form(tag, openers_info)
+ break
+ end
+ end
+
+ -- util.debug(tags)
+ -- util.debug(strings)
+
+ --- at type InlineElement[]
+ local output = {}
+
+ if strings[1] ~= "" then
+ table.insert(output, PlainText:new(strings[1]))
+ end
+
+ --- at type {tag: string, closer: string, pos: number, output_pos: number}[]
+ opener_stack = {}
+
+ for i, tag in ipairs(tags) do
+ if openers_info[tag] then
+ table.insert(opener_stack, {
+ tag = tag,
+ closer = openers_info[tag].closer,
+ pos = i,
+ output_pos = #output + 1
+ })
+ else
+ assert(#opener_stack > 0)
+ local opener_info = opener_stack[#opener_stack]
+ assert(opener_info.closer == tag)
+ local output_pos = opener_info.output_pos
+ local inlines = util.slice(output, output_pos)
+ for j = #output, output_pos, -1 do
+ table.remove(output, j)
end
- local last_inline = elements[#elements]
- if last_inline and last_inline._type == "PlainText" then
- last_inline.value = last_inline.value .. quote
- else
- table.insert(elements, PlainText:new(quote))
+ table.remove(opener_stack)
+ local inline = make_inline_from_tag(opener_info.tag, inlines, openers_info, context)
+ if inline._type == "Quoted" then
+ --- at cast inline Quoted
+ local quotes = context:get_localized_quotes()
+ inline.punctuation_in_quote = quotes.punctuation_in_quote
end
+ table.insert(output, inline)
+ end
- for _, inline in ipairs(text_stack[i + 1]) do
- if inline._type == "PlainText" then
- local last_inline = elements[#elements]
- if last_inline and last_inline._type == "PlainText" then
- last_inline.value = last_inline.value .. inline.value
- else
- table.insert(elements, inline)
- end
- else
- table.insert(elements, inline)
- end
- end
+ if strings[i + 1] ~= "" then
+ table.insert(output, PlainText:new(strings[i + 1]))
end
+
end
- return elements
+ -- util.debug(output)
+ return output
end
local function merge_fragments_at(fragments, i)
@@ -792,6 +1029,9 @@
return inlines
end
+--- at param ir IrNode
+--- at param override_delim boolean
+--- at return InlineElement[]
function OutputFormat:flatten_seq_ir(ir, override_delim)
-- if not ir.children then
-- print(debug.traceback())
@@ -1174,10 +1414,14 @@
return inlines
end
+--- at param inlines InlineElement[]
+--- at param affixes table
+--- at param localized_quotes LocalizedQuotes
+--- at return InlineElement[]
function OutputFormat:affixed_quoted(inlines, affixes, localized_quotes)
inlines = util.clone(inlines)
if localized_quotes then
- inlines = self:quoted(inlines, localized_quotes)
+ inlines = {Quoted:new(inlines, localized_quotes)}
end
if affixes and affixes.prefix and affixes.prefix ~= "" then
table.insert(inlines, 1, PlainText:new(affixes.prefix))
@@ -1188,10 +1432,6 @@
return inlines
end
-function OutputFormat:quoted(inlines, localized_quotes)
- return {Quoted:new(inlines, localized_quotes)}
-end
-
function OutputFormat:with_display(nodes, display)
if display then
return {Div:new(nodes, display)}
@@ -1242,7 +1482,8 @@
["font-weight"] = "normal",
["text-decoration"] = "none",
["vertical-alignment"] = "baseline",
- in_inner_quotes = false,
+ in_quotes = false,
+ inner_quotes = false,
}
self:flip_flop(inlines, flip_flop_state)
end
@@ -1275,9 +1516,13 @@
self:flip_flop(inline.inlines, new_state)
elseif inline._type == "Quoted" then
- inline.is_inner = state.in_inner_quotes
+ --- at cast inline Quoted
+ if state.in_quotes then
+ inline.is_inner = not state.inner_quotes
+ end
local new_state = util.clone(state)
- new_state.in_inner_quotes = not new_state.in_inner_quotes
+ new_state.in_quotes = true
+ new_state.inner_quotes = inline.is_inner
self:flip_flop(inline.inlines, new_state)
elseif inline._type == "NoDecor" then
@@ -1337,9 +1582,13 @@
self:flip_flop_micro_inlines(inline.inlines, new_state)
elseif inline._type == "Quoted" then
- inline.is_inner = state.in_inner_quotes
+ --- at cast inline Quoted
+ if state.in_quotes then
+ inline.is_inner = not state.inner_quotes
+ end
local new_state = util.clone(state)
- new_state.in_inner_quotes = not new_state.in_inner_quotes
+ new_state.in_quotes = true
+ new_state.inner_quotes = inline.is_inner
self:flip_flop_micro_inlines(inline.inlines, new_state)
elseif inline._type == "NoDecor" then
@@ -1410,6 +1659,7 @@
--- "'Foo,' bar" => ,
--- at param inline InlineElement
+--- at return boolean
local function find_right_quoted(inline)
if inline._type == "Quoted" and #inline.inlines > 0 then
--- at cast inline Quoted
@@ -2024,6 +2274,8 @@
-- Omit formatting and quotes
+
+--- at class DisamStringFormat: OutputFormat
local DisamStringFormat = OutputFormat:new()
function DisamStringFormat:output(inlines, context)
Modified: trunk/Master/texmf-dist/scripts/citation-style-language/citeproc.lua
===================================================================
--- trunk/Master/texmf-dist/scripts/citation-style-language/citeproc.lua 2024-08-15 20:00:44 UTC (rev 72037)
+++ trunk/Master/texmf-dist/scripts/citation-style-language/citeproc.lua 2024-08-15 20:01:24 UTC (rev 72038)
@@ -16,7 +16,7 @@
util = require("citeproc.util")
end
-citeproc.__VERSION__ = "0.6.0"
+citeproc.__VERSION__ = "0.6.1"
citeproc.new = engine.CiteProc.new
citeproc.util = util
Modified: trunk/Master/texmf-dist/tex/latex/citation-style-language/citation-style-language.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/citation-style-language/citation-style-language.sty 2024-08-15 20:00:44 UTC (rev 72037)
+++ trunk/Master/texmf-dist/tex/latex/citation-style-language/citation-style-language.sty 2024-08-15 20:01:24 UTC (rev 72038)
@@ -9,7 +9,7 @@
\RequirePackage{expl3}
\RequirePackage{xparse}
-\ProvidesExplPackage {citation-style-language} {2024-07-31} {0.6.0}
+\ProvidesExplPackage {citation-style-language} {2024-08-15} {0.6.1}
{Citation Style Language for LaTeX}
\RequirePackage { l3keys2e }
Modified: trunk/Master/texmf-dist/tex/latex/citation-style-language/locales/csl-locales-en-US.xml
===================================================================
--- trunk/Master/texmf-dist/tex/latex/citation-style-language/locales/csl-locales-en-US.xml 2024-08-15 20:00:44 UTC (rev 72037)
+++ trunk/Master/texmf-dist/tex/latex/citation-style-language/locales/csl-locales-en-US.xml 2024-08-15 20:01:24 UTC (rev 72038)
@@ -17,7 +17,7 @@
<name>Brenton M. Wiernik</name>
</translator>
<rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>
- <updated>2024-03-12T12:31:23-04:00</updated>
+ <updated>2024-08-12T16:22:23-04:00</updated>
</info>
<style-options punctuation-in-quote="true"/>
<date form="text">
@@ -685,7 +685,6 @@
</term>
<!-- VERB ROLE FORMS -->
- <term name="author" form="verb">by</term>
<term name="chair" form="verb">chaired by</term>
<term name="collection-editor" form="verb">edited by</term>
<term name="compiler" form="verb">compiled by</term>
Modified: trunk/Master/texmf-dist/tex/latex/citation-style-language/locales/csl-locales-zh-TW.xml
===================================================================
--- trunk/Master/texmf-dist/tex/latex/citation-style-language/locales/csl-locales-zh-TW.xml 2024-08-15 20:00:44 UTC (rev 72037)
+++ trunk/Master/texmf-dist/tex/latex/citation-style-language/locales/csl-locales-zh-TW.xml 2024-08-15 20:01:24 UTC (rev 72038)
@@ -5,7 +5,7 @@
<name>sati-bodhi</name>
</translator>
<rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>
- <updated>2024-03-09T15:20:54-05:00</updated>
+ <updated>2024-08-12T16:22:23-04:00</updated>
</info>
<style-options punctuation-in-quote="false"/>
<date form="text">
@@ -433,7 +433,6 @@
<single>series creator</single>
<multiple>series creators</multiple>
</term>
- <term name="author">作者</term>
<term name="director">導演</term>
<term name="editor">編輯</term>
<term name="editorial-director">主編</term>
@@ -485,7 +484,6 @@
<single>cre.</single>
<multiple>cres.</multiple>
</term>
- <term name="author" form="short">作者</term>
<term name="director" form="short">導演</term>
<term name="editor" form="short">編輯</term>
<term name="editorial-director" form="short">主編</term>
@@ -511,7 +509,6 @@
<term name="producer" form="verb">produced by</term>
<term name="script-writer" form="verb">written by</term>
<term name="series-creator" form="verb">created by</term>
- <term name="author" form="verb">著</term>
<term name="container-author" form="verb">著</term>
<term name="director" form="verb">指導</term>
<term name="editor" form="verb">編輯</term>
Modified: trunk/Master/texmf-dist/tex/latex/citation-style-language/styles/american-medical-association.csl
===================================================================
--- trunk/Master/texmf-dist/tex/latex/citation-style-language/styles/american-medical-association.csl 2024-08-15 20:00:44 UTC (rev 72037)
+++ trunk/Master/texmf-dist/tex/latex/citation-style-language/styles/american-medical-association.csl 2024-08-15 20:01:24 UTC (rev 72038)
@@ -27,7 +27,7 @@
<category citation-format="numeric"/>
<category field="medicine"/>
<summary>The American Medical Association style as used in JAMA. Version 11 as per November-2019.</summary>
- <updated>2022-09-28T07:33:04-04:00</updated>
+ <updated>2024-08-04T17:48:30-04:00</updated>
<rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>
</info>
<locale xml:lang="en">
@@ -66,7 +66,7 @@
<group delimiter=". ">
<choose>
<if type="webpage post post-weblog" match="any">
- <date variable="issued" prefix="Published " form="text"/>
+ <date variable="issued" form="text"/>
</if>
</choose>
<group>
@@ -173,7 +173,7 @@
<if variable="URL">
<group delimiter=". " suffix=".">
<text variable="URL"/>
- <group prefix="Published ">
+ <group>
<date variable="issued">
<date-part name="month" suffix=" "/>
<date-part name="day" suffix=", "/>
Modified: trunk/Master/texmf-dist/tex/latex/citation-style-language/styles/apa.csl
===================================================================
--- trunk/Master/texmf-dist/tex/latex/citation-style-language/styles/apa.csl 2024-08-15 20:00:44 UTC (rev 72037)
+++ trunk/Master/texmf-dist/tex/latex/citation-style-language/styles/apa.csl 2024-08-15 20:01:24 UTC (rev 72038)
@@ -14,7 +14,7 @@
<category citation-format="author-date"/>
<category field="psychology"/>
<category field="generic-base"/>
- <updated>2024-07-19T10:52:31-04:00</updated>
+ <updated>2024-08-06T11:26:59-04:00</updated>
<rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>
</info>
<locale xml:lang="en">
@@ -139,12 +139,23 @@
<names variable="author"/>
<!-- Note: `narrator` only cited in secondary-contributors -->
<names variable="illustrator"/>
- <names variable="script-writer director">
- <!-- Note: Actors/performers and producers [not executive] not cited in APA style. -->
+ <!-- TODO: Replace `delimiter` with `collapse` to combine names variables when that becomes available. -->
+ <choose>
+ <if type="broadcast">
+ <names variable="script-writer director" delimiter=", & ">
+ <!-- Note: Actors/performers and producers [not executive] not cited in APA style. -->
+ <name name-as-sort-order="all" and="symbol" sort-separator=", " initialize-with=". " delimiter=", " delimiter-precedes-last="always"/>
+ <label form="long" prefix=" (" suffix=")" text-case="title"/>
+ </names>
+ </if>
+ </choose>
+ <names variable="director">
+ <!-- For non-broadcast items, APA only cites directors and not writers. -->
<name name-as-sort-order="all" and="symbol" sort-separator=", " initialize-with=". " delimiter=", " delimiter-precedes-last="always"/>
<label form="long" prefix=" (" suffix=")" text-case="title"/>
</names>
- <names variable="guest host">
+ <!-- TODO: Replace `delimiter` with `collapse` to combine names variables when that becomes available. -->
+ <names variable="guest host" delimiter=", & ">
<name name-as-sort-order="all" and="symbol" sort-separator=", " initialize-with=". " delimiter=", " delimiter-precedes-last="always"/>
<label form="long" prefix=" (" suffix=")" text-case="title"/>
</names>
@@ -174,17 +185,20 @@
</choose>
</if>
</choose>
- <names variable="series-creator executive-producer">
+ <names variable="executive-producer">
<name name-as-sort-order="all" and="symbol" sort-separator=", " initialize-with=". " delimiter=", " delimiter-precedes-last="always"/>
<label form="long" prefix=" (" suffix=")" text-case="title"/>
</names>
- <names variable="editor-translator" delimiter=", ">
+ <names variable="series-creator">
<name name-as-sort-order="all" and="symbol" sort-separator=", " initialize-with=". " delimiter=", " delimiter-precedes-last="always"/>
+ <label form="long" prefix=" (" suffix=")" text-case="title"/>
+ </names>
+ <names variable="editor-translator">
+ <name name-as-sort-order="all" and="symbol" sort-separator=", " initialize-with=". " delimiter=", " delimiter-precedes-last="always"/>
<label form="short" prefix=" (" suffix=")" text-case="title"/>
</names>
- <!-- TODO: Split editor and translator into separate lines once processors begin to automatically create
- the editor-translator variable. -->
- <names variable="editor translator" delimiter=", ">
+ <!-- Note: Translator is not cited as a primary creator (only as Ed. & Trans.). -->
+ <names variable="editor">
<name name-as-sort-order="all" and="symbol" sort-separator=", " initialize-with=". " delimiter=", " delimiter-precedes-last="always"/>
<label form="short" prefix=" (" suffix=")" text-case="title"/>
</names>
@@ -279,8 +293,15 @@
<substitute>
<names variable="author"/>
<names variable="illustrator"/>
- <names variable="script-writer director"/>
- <names variable="guest host"/>
+ <!-- TODO: Replace `delimiter` with `collapse` to combine names variables when that becomes available. -->
+ <choose>
+ <if type="broadcast">
+ <names variable="script-writer director" delimiter=", & "/>
+ </if>
+ </choose>
+ <names variable="director"/>
+ <!-- TODO: Replace `delimiter` with `collapse` to combine names variables when that becomes available. -->
+ <names variable="guest host" delimiter=", & "/>
<names variable="producer"/>
<choose>
<if variable="container-title">
@@ -291,7 +312,8 @@
</choose>
</if>
</choose>
- <names variable="series-creator executive-producer"/>
+ <names variable="executive-producer"/>
+ <names variable="series-creator"/>
<names variable="editor"/>
<names variable="editorial-director"/>
<names variable="compiler"/>
@@ -1172,33 +1194,44 @@
</names>
</if>
</choose>
- <!-- TODO: When editor-translator becomes available in processors, add a test:
- variable="editor-translator" match="none"; then print translator -->
<choose>
<if type="post webpage" match="none">
<!-- Webpages treat container-title like publisher -->
- <choose>
- <if variable="container-title" match="none">
- <group delimiter="; ">
- <names variable="container-author">
- <label form="verb-short" suffix=" " text-case="title"/>
- <name and="symbol" initialize-with=". " delimiter=", "/>
- </names>
- <names variable="editor translator" delimiter="; ">
- <name and="symbol" initialize-with=". " delimiter=", "/>
- <label form="short" prefix=", " text-case="title"/>
- </names>
- <names variable="illustrator narrator" delimiter="; ">
- <name and="symbol" initialize-with=". " delimiter=", "/>
- <label form="short" prefix=", " text-case="title"/>
- </names>
- <names variable="compiler chair organizer curator series-creator executive-producer" delimiter="; ">
- <name and="symbol" initialize-with=". " delimiter=", "/>
- <label form="long" prefix=", " text-case="title"/>
- </names>
- </group>
- </if>
- </choose>
+ <group delimiter="; ">
+ <names variable="illustrator narrator" delimiter="; ">
+ <name and="symbol" initialize-with=". " delimiter=", "/>
+ <label form="short" prefix=", " text-case="title"/>
+ </names>
+ <choose>
+ <if variable="container-title" match="none">
+ <group delimiter="; ">
+ <names variable="container-author">
+ <label form="verb-short" suffix=" " text-case="title"/>
+ <name and="symbol" initialize-with=". " delimiter=", "/>
+ </names>
+ <names variable="editor translator" delimiter="; ">
+ <name and="symbol" initialize-with=". " delimiter=", "/>
+ <label form="short" prefix=", " text-case="title"/>
+ </names>
+ <names variable="compiler chair organizer curator series-creator executive-producer" delimiter="; ">
+ <name and="symbol" initialize-with=". " delimiter=", "/>
+ <label form="long" prefix=", " text-case="title"/>
+ </names>
+ </group>
+ </if>
+ <else>
+ <choose>
+ <!-- TODO: Check logic once processors start to automatically populate editor-translator. -->
+ <if variable="editor-translator" match="none">
+ <names variable="translator" delimiter="; ">
+ <name and="symbol" initialize-with=". " delimiter=", "/>
+ <label form="short" prefix=", " text-case="title"/>
+ </names>
+ </if>
+ </choose>
+ </else>
+ </choose>
+ </group>
</if>
<else>
<group delimiter="; ">
@@ -1280,17 +1313,10 @@
</choose>
</macro>
<macro name="version">
- <choose>
- <if is-numeric="version">
- <group delimiter=" ">
- <label variable="version" text-case="capitalize-first"/>
- <text variable="version"/>
- </group>
- </if>
- <else>
- <text variable="version"/>
- </else>
- </choose>
+ <group delimiter=" ">
+ <label variable="version" text-case="capitalize-first"/>
+ <text variable="version"/>
+ </group>
</macro>
<macro name="edition">
<choose>
@@ -1539,17 +1565,19 @@
</else>
</choose>
<group delimiter=", ">
- <names variable="series-creator executive-producer" delimiter=", & ">
+ <names variable="executive-producer">
<name and="symbol" initialize-with=". " delimiter=", "/>
<label form="long" text-case="title" prefix=" (" suffix=")"/>
<substitute>
+ <names variable="series-creator"/>
<names variable="editor-translator">
<name and="symbol" initialize-with=". " delimiter=", "/>
<label form="short" text-case="title" prefix=" (" suffix=")"/>
</names>
- <!-- TODO: Split editor and translator lines once processors start to automatically
- create editor-translator variable. -->
- <names variable="editor translator">
+ <!-- TODO: Translator omitted here on the assumption that editor-translators are uncommon
+ for chapter citations. If needed, direct entry or automatic population of
+ `editor-translator` can produce combined labels. -->
+ <names variable="editor">
<name and="symbol" initialize-with=". " delimiter=", "/>
<label form="short" text-case="title" prefix=" (" suffix=")"/>
</names>
More information about the tex-live-commits
mailing list.