add _extensions
This commit is contained in:
@@ -0,0 +1,213 @@
|
||||
--- Localize Chinese bibliographies generated by Pandoc Citeproc and CSL
|
||||
|
||||
--- Copyright: © 2024–Present Tom Ben
|
||||
--- License: MIT License
|
||||
|
||||
-- Function to check if a string contains Chinese characters
|
||||
function contains_chinese(text)
|
||||
return text and text:find("[\228-\233][\128-\191][\128-\191]") ~= nil
|
||||
end
|
||||
|
||||
-- Function to extract digits from a string
|
||||
function extract_digits(text)
|
||||
return text and text:match("%d+")
|
||||
end
|
||||
|
||||
-- Helper to find the closest previous Str (skips spaces and empty strings)
|
||||
local function find_prev_str(content, start_index)
|
||||
for idx = start_index - 1, 1, -1 do
|
||||
local item = content[idx]
|
||||
if item and item.t == "Str" and item.text ~= "" then
|
||||
return item, idx
|
||||
end
|
||||
end
|
||||
return nil, nil
|
||||
end
|
||||
|
||||
-- Helper to find the closest next Str (skips spaces and empty strings)
|
||||
local function find_next_str(content, start_index)
|
||||
for idx = start_index + 1, #content do
|
||||
local item = content[idx]
|
||||
if item and item.t == "Str" and item.text ~= "" then
|
||||
return item, idx
|
||||
end
|
||||
end
|
||||
return nil, nil
|
||||
end
|
||||
|
||||
-- Function to check if Emph contains "et al." or "et al.,"
|
||||
function is_et_al_emph(emph)
|
||||
if emph.t ~= "Emph" or #emph.content < 3 then
|
||||
return false
|
||||
end
|
||||
|
||||
local has_et = emph.content[1].t == "Str" and emph.content[1].text == "et"
|
||||
local has_space = emph.content[2].t == "Space"
|
||||
local has_al = emph.content[3].t == "Str" and
|
||||
(emph.content[3].text == "al." or emph.content[3].text == "al.,")
|
||||
|
||||
return has_et and has_space and has_al
|
||||
end
|
||||
|
||||
-- Function to process `et al.` in citations for author-date style
|
||||
function process_citation(el)
|
||||
local new_inlines = {}
|
||||
local i = 1
|
||||
|
||||
while i <= #el.content do
|
||||
local current = el.content[i]
|
||||
|
||||
-- Handle italic et al. (wrapped in Emph)
|
||||
if current.t == "Emph" and is_et_al_emph(current) and i > 1 then
|
||||
local prev = el.content[i - 1]
|
||||
if prev.t == "Str" and contains_chinese(prev.text) then
|
||||
-- Replace the Emph element with plain "等" or "等,"
|
||||
if current.content[3].text == "al.," then
|
||||
table.insert(new_inlines, pandoc.Str("等,"))
|
||||
else
|
||||
table.insert(new_inlines, pandoc.Str("等"))
|
||||
end
|
||||
i = i + 1
|
||||
else
|
||||
table.insert(new_inlines, current)
|
||||
i = i + 1
|
||||
end
|
||||
-- Handle non-italic et al.
|
||||
elseif current.t == "Str" and contains_chinese(current.text) and current.text:sub(-2) == "et" and
|
||||
i + 2 <= #el.content and el.content[i + 1].t == "Space" and el.content[i + 2].t == "Str" then
|
||||
local modified_text
|
||||
if el.content[i + 2].text == "al." then
|
||||
modified_text = current.text:sub(1, -3) .. "等"
|
||||
elseif el.content[i + 2].text == "al.," then
|
||||
modified_text = current.text:sub(1, -3) .. "等,"
|
||||
end
|
||||
if modified_text then
|
||||
table.insert(new_inlines, pandoc.Str(modified_text))
|
||||
i = i + 3 -- Skip the next Space and 'al.' or 'al.,'
|
||||
else
|
||||
table.insert(new_inlines, current)
|
||||
i = i + 1
|
||||
end
|
||||
else
|
||||
table.insert(new_inlines, current)
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
el.content = new_inlines
|
||||
return el
|
||||
end
|
||||
|
||||
-- Function to process localizations in bibliography entries
|
||||
function process_bibliography(elem)
|
||||
local new_inlines = {}
|
||||
local i = 1
|
||||
|
||||
-- Process both italic and non-italic `et al.`
|
||||
while i <= #elem.content do
|
||||
local current = elem.content[i]
|
||||
|
||||
-- Handle italic et al. (wrapped in Emph)
|
||||
if current.t == "Emph" and is_et_al_emph(current) and i > 2 then
|
||||
local prev = elem.content[i - 2]
|
||||
if prev and prev.t == "Str" and contains_chinese(prev.text) then
|
||||
-- Replace with plain "等." or "等,"
|
||||
if current.content[3].text == "al.," then
|
||||
table.insert(new_inlines, pandoc.Str("等,"))
|
||||
else
|
||||
table.insert(new_inlines, pandoc.Str("等."))
|
||||
end
|
||||
i = i + 1
|
||||
else
|
||||
table.insert(new_inlines, current)
|
||||
i = i + 1
|
||||
end
|
||||
-- Handle non-italic et al.
|
||||
elseif i <= #elem.content - 2 and current.t == "Str" and current.text == "et" and
|
||||
elem.content[i + 1].t == "Space" and i > 2 then
|
||||
local prev = elem.content[i - 2]
|
||||
if prev and prev.t == "Str" and contains_chinese(prev.text) then
|
||||
if elem.content[i + 2].t == "Str" and elem.content[i + 2].text == "al.," then
|
||||
table.insert(new_inlines, pandoc.Str("等,"))
|
||||
i = i + 3
|
||||
elseif elem.content[i + 2].t == "Str" and elem.content[i + 2].text == "al." then
|
||||
table.insert(new_inlines, pandoc.Str("等."))
|
||||
i = i + 3
|
||||
else
|
||||
table.insert(new_inlines, current)
|
||||
i = i + 1
|
||||
end
|
||||
else
|
||||
table.insert(new_inlines, current)
|
||||
i = i + 1
|
||||
end
|
||||
else
|
||||
table.insert(new_inlines, current)
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
elem.content = new_inlines
|
||||
|
||||
-- Process other localizations
|
||||
for i = 1, #elem.content do
|
||||
local v = elem.content[i]
|
||||
local prev_str, prev_idx = find_prev_str(elem.content, i)
|
||||
local next_str, next_idx = find_next_str(elem.content, i)
|
||||
|
||||
if v and v.t == "Str" then
|
||||
local text = v.text:lower()
|
||||
|
||||
if text == "vol." and next_str then
|
||||
if prev_str and contains_chinese(prev_str.text) then
|
||||
local vol_num, identifier = next_str.text:match("([^%[]+)%[(.+)%]")
|
||||
if vol_num and identifier then
|
||||
elem.content[i] = pandoc.Str("第" .. vol_num .. "卷[" .. identifier .. "].")
|
||||
for remove_idx = next_idx, i + 1, -1 do
|
||||
table.remove(elem.content, remove_idx)
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif (text == "tran." or text == "trans.") and i > 2 then
|
||||
if prev_str and contains_chinese(prev_str.text) and prev_str.text:match(",$") then
|
||||
elem.content[i] = pandoc.Str("译.")
|
||||
end
|
||||
elseif (text == "ed." or text == "eds.") and i > 2 and prev_str and prev_str.t == "Str" then
|
||||
if contains_chinese(prev_str.text) and prev_str.text:match(",$") then
|
||||
elem.content[i] = pandoc.Str("编.")
|
||||
else
|
||||
local ed_num = extract_digits(prev_str.text)
|
||||
local prev_prev_str = prev_idx and select(1, find_prev_str(elem.content, prev_idx))
|
||||
if ed_num and prev_prev_str and contains_chinese(prev_prev_str.text) then
|
||||
elem.content[prev_idx] = pandoc.Str(ed_num .. "版.")
|
||||
table.remove(elem.content, i)
|
||||
if elem.content[i - 1] and elem.content[i - 1].t == "Space" then
|
||||
table.remove(elem.content, i - 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return elem
|
||||
end
|
||||
|
||||
function process_div(el)
|
||||
if el.classes:includes("csl-entry") then
|
||||
for _, block in ipairs(el.content) do
|
||||
if block.t == "Para" then
|
||||
process_bibliography(block)
|
||||
end
|
||||
end
|
||||
end
|
||||
return el
|
||||
end
|
||||
|
||||
return {
|
||||
{
|
||||
Cite = process_citation,
|
||||
Link = process_citation,
|
||||
Div = process_div,
|
||||
Span = process_bibliography
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user