Module:Footnotes: Difference between revisions
no edit summary
m (1 revision imported) |
No edit summary |
||
Line 1: | Line 1: | ||
require('Module:No globals'); | require('Module:No globals'); | ||
local getArgs = require ('Module:Arguments').getArgs; | |||
--[[--------------------------< A R G S _ D E F A U L T >------------------------------------------------------ | --[[--------------------------< A R G S _ D E F A U L T >------------------------------------------------------ | ||
Line 19: | Line 21: | ||
pages_sep = ", pp. ", | pages_sep = ", pp. ", | ||
ref = '', | ref = '', | ||
template = 'harv', -- if template name not provided in {{#invoke:}} use this | |||
}; | }; | ||
--[[--------------------------< T A R G E T _ C H E C K >------------------------------------------------------ | |||
look for anchor_id (CITEREF name-list and year or text from |ref=) in anchor_id_list | |||
the 'no target' error may be suppressed with |ignore-err=yes when target cannot be found because target is inside | |||
a template that wraps another template; 'multiple targets' error may not be suppressed | |||
]] | |||
local function target_check (anchor_id, args) | |||
local namespace = mw.title.getCurrentTitle().namespace; | |||
local anchor_id_list_module = mw.loadData ('Module:Footnotes/anchor_id_list'); | |||
local anchor_id_list = anchor_id_list_module.anchor_id_list; | |||
local article_whitelist = anchor_id_list_module.article_whitelist; | |||
local template_list = anchor_id_list_module.template_list; | |||
local whitelist_module = mw.loadData ('Module:Footnotes/whitelist'); | |||
local whitelist = whitelist_module.whitelist; | |||
local special_patterns = whitelist_module.special_patterns; | |||
local DNB_special_patterns = whitelist_module.DNB_special_patterns; | |||
local DNB_template_names = whitelist_module.DNB_template_names; | |||
if 10 == namespace then | |||
return ''; -- automatic form of |template-doc-demo=true; TODO: is this too broad? | |||
end | |||
local tally = anchor_id_list[anchor_id]; -- nil when anchor_id not in list; else a tally | |||
local msg; | |||
local category; | |||
if not tally then | |||
if args.ignore then | |||
return ''; -- if ignore is true then no message, no category | |||
end | |||
if article_whitelist and article_whitelist[anchor_id] then -- if an article-local whitelist and anchor ID is in it | |||
return ''; -- done | |||
end | |||
local wl_anchor_id = anchor_id; -- copy to be modified to index into the whitelist | |||
if args.year then -- for anchor IDs created by this template (not in |ref=) that have a date | |||
if args.year:match ('%d%l$') or -- use the date value to determine if we should remove the disambiguator | |||
args.year:match ('n%.d%.%l$') or | |||
args.year:match ('nd%l$') then | |||
wl_anchor_id = wl_anchor_id:gsub ('%l$', ''); -- remove the disambiguator | |||
end | |||
end | |||
local t_tbl = whitelist[wl_anchor_id]; -- get list of templates associated with this anchor ID | |||
if t_tbl then -- when anchor ID not whitelisted t_tbl is nil | |||
for _, t in ipairs (t_tbl) do -- spin through the list of templates associated with this anchor ID | |||
if template_list[t] then -- if associated template is found in the list of templates in the article | |||
return ''; -- anchor ID is whitlisted and article has matching template so no error | |||
end | |||
end | |||
end | |||
for _, pattern in ipairs (special_patterns) do -- spin through the spcial patterns and try to match | |||
if anchor_id:match (pattern) then | |||
return ''; | |||
end | |||
end | |||
for _, dnb_t in ipairs (DNB_template_names or {}) do -- getting desparate now, are there any DNB templates? DNB_template_names may be nil; empty table prevents script error | |||
if template_list[dnb_t] then -- if the article has this DNB template | |||
for _, pattern in ipairs (DNB_special_patterns) do -- spin through the DNB-specifiec wildcard patterns | |||
if anchor_id:match (pattern) then -- and attempt a match | |||
return ''; -- found a match | |||
end | |||
end | |||
end | |||
end | |||
msg = 'no target: ' .. anchor_id; -- anchor_id not found | |||
category = '[[Category:Harv and Sfn no-target errors]]'; | |||
elseif 1 < tally then | |||
msg = 'multiple targets (' .. tally .. '×): ' .. anchor_id; -- more than one anchor_id in this article | |||
category = '[[Category:Harv and Sfn multiple-target errors]]'; | |||
end | |||
-- category = 0 == namespace and '[[Category:Harv and Sfn template errors]]' or ''; -- only categorize in article space | |||
category = 0 == namespace and category or ''; -- only categorize in article space | |||
--use this version to show error messages | |||
-- return msg and '<span class="error harv-error" style="display: inline; font-size:100%"> ' .. args.template .. ' error: ' .. msg .. ' ([[:Category:Harv and Sfn template errors|help]])</span>' .. category or ''; | |||
--use this version to hide error messages | |||
return msg and '<span class="error harv-error" style="display: none; font-size:100%"> ' .. args.template .. ' error: ' .. msg .. ' ([[:Category:Harv and Sfn template errors|help]])</span>' .. category or ''; | |||
end | |||
Line 30: | Line 127: | ||
c. YYYY | c. YYYY | ||
YYYY–YYYY (separator is endash) | YYYY–YYYY (separator is endash) | ||
YYYY–YY (separator is endash) | |||
return true when param has a recognized form; false else | return true when param has a recognized form; false else | ||
Line 35: | Line 133: | ||
]] | ]] | ||
local | local patterns_date= { | ||
'^%d%d%d%d?%l?$', | |||
'^n%.d%.%l?$', | |||
'^nd%l?$', | |||
'^c%. %d%d%d%d?%l?$', | |||
'^%d%d%d%d–%d%d%d%d%l?$', | |||
'^%d%d%d%d–%d%d%l?$', | |||
} | |||
local function is_year (param, args) | |||
args.year = ''; -- used for harv error; | |||
for _, pattern in ipairs (patterns_date) do | |||
if mw.ustring.match (param, pattern) then | |||
args.year = param; -- used for harv error; | |||
return true; | |||
end | |||
end | |||
end | end | ||
Line 48: | Line 162: | ||
local function core( args ) | local function core( args ) | ||
local result; | local result; | ||
local err_msg = '' | |||
if args.P5 ~= '' then | if args.P5 ~= '' then | ||
if is_year (args.P5) then | if is_year (args.P5, args) then | ||
result = table.concat ({args.P1, ' et al. ', args.bracket_year_left, args.P5, args.bracket_year_right}); | result = table.concat ({args.P1, ' et al. ', args.bracket_year_left, args.P5, args.bracket_year_right}); | ||
else | else | ||
Line 58: | Line 173: | ||
elseif args.P4 ~= '' then | elseif args.P4 ~= '' then | ||
if is_year (args.P4) then | if is_year (args.P4, args) then | ||
result = table.concat ({args.P1, ', ', args.P2, ' & ', args.P3, ' ', args.bracket_year_left, args.P4, args.bracket_year_right}); -- three names and a year | result = table.concat ({args.P1, ', ', args.P2, ' & ', args.P3, ' ', args.bracket_year_left, args.P4, args.bracket_year_right}); -- three names and a year | ||
else | else | ||
Line 65: | Line 180: | ||
elseif args.P3 ~= '' then | elseif args.P3 ~= '' then | ||
if is_year (args.P3) then | if is_year (args.P3, args) then | ||
result = table.concat ({args.P1, ' & ', args.P2, ' ', args.bracket_year_left, args.P3, args.bracket_year_right}); -- two names and a year | result = table.concat ({args.P1, ' & ', args.P2, ' ', args.bracket_year_left, args.P3, args.bracket_year_right}); -- two names and a year | ||
else | else | ||
Line 72: | Line 187: | ||
elseif args.P2 ~= '' then | elseif args.P2 ~= '' then | ||
if is_year (args.P2) then | if is_year (args.P2, args) then | ||
result = table.concat ({args.P1, ' ', args.bracket_year_left, args.P2, args.bracket_year_right}); -- one name and year | result = table.concat ({args.P1, ' ', args.bracket_year_left, args.P2, args.bracket_year_right}); -- one name and year | ||
else | else | ||
Line 91: | Line 206: | ||
if args.ref ~= 'none' then | if args.ref ~= 'none' then | ||
local anchor_id; | |||
if args.ref ~= '' then | if args.ref ~= '' then | ||
result = table.concat ({'[[#', | anchor_id = mw.uri.anchorEncode (args.ref); | ||
err_msg = target_check (anchor_id, args); | |||
result = table.concat ({'[[#', anchor_id, '|', result, ']]'}); | |||
else | else | ||
anchor_id = mw.uri.anchorEncode (table.concat ({'CITEREF', args.P1, args.P2, args.P3, args.P4, args.P5})); | |||
err_msg = target_check (anchor_id, args); | |||
result = table.concat ({'[[#', anchor_id, '|', result, ']]'}); | |||
end | end | ||
end | end | ||
Line 109: | Line 229: | ||
result = table.concat ({args.bracket_left, result, args.bracket_right, args.postscript}):gsub ('%s+', ' '); -- strip redundant spaces | result = table.concat ({args.bracket_left, result, args.bracket_right, args.postscript}):gsub ('%s+', ' '); -- strip redundant spaces | ||
return result; | return result .. err_msg; | ||
end | end | ||
Line 136: | Line 256: | ||
args.location = pframe.args.loc or ''; | args.location = pframe.args.loc or ''; | ||
args.ref = pframe.args.ref or pframe.args.Ref or ''; | args.ref = pframe.args.ref or pframe.args.Ref or ''; | ||
args.ignore = ('yes' == pframe.args['ignore-false-positive']) or ('yes' == pframe.args['ignore-err']); | |||
for i, v in ipairs ({'P1', 'P2', 'P3', 'P4', 'P5'}) do -- loop through the five positional parameters and trim if set else empty string | for i, v in ipairs ({'P1', 'P2', 'P3', 'P4', 'P5'}) do -- loop through the five positional parameters and trim if set else empty string | ||
args[v] = (pframe.args[i] and mw.text.trim (pframe.args[i])) or ''; | args[v] = (pframe.args[i] and mw.text.trim (pframe.args[i])) or ''; | ||
end | end | ||
if args.P5 and not is_year (args.P5, args) then | |||
local i = 6; -- initialize the indexer to the sixth positional parameter | |||
while pframe.args[i] do -- in case there are too many authors loop through the authors looking for a year | |||
local v = mw.text.trim (pframe.args[i]); -- trim | |||
if is_year (v, args) then -- if a year | |||
args.P5 = v; -- overwrite whatever was in args.P5 with year | |||
break; -- and abandon the search | |||
end | |||
i = i + 1; -- bump the indexer | |||
end | |||
end | |||
return args; | return args; | ||
end | end | ||
Line 178: | Line 310: | ||
local function strip_url (pages) | local function strip_url (pages) | ||
local escaped_uri; | local escaped_uri; | ||
if not pages or ('' == pages) then | if not pages or ('' == pages) then | ||
return pages; | return pages; | ||
Line 203: | Line 335: | ||
local result = core (args); -- go make a CITEREF anchor | local result = core (args); -- go make a CITEREF anchor | ||
-- put it all together and then strip redundant spaces | -- put it all together and then strip redundant spaces | ||
local name = table.concat ({'FOOTNOTE', args.P1, args.P2, args.P3, args.P4, args.P5, strip_url (args.page), strip_url (args.pages), strip_url (args.location)}):gsub ('%s+', ' '); | local name = table.concat ({'FOOTNOTE', args.P1, args.P2, args.P3, args.P4, args.P5, strip_url (args.page), strip_url (args.pages), strip_url (args.location)}):gsub ('%s+', ' '); | ||
Line 279: | Line 410: | ||
args.pages = pframe.args[table.concat ({n, 'pp'})] or ''; | args.pages = pframe.args[table.concat ({n, 'pp'})] or ''; | ||
args.location = pframe.args[table.concat ({n, 'loc'})] or ''; | args.location = pframe.args[table.concat ({n, 'loc'})] or ''; | ||
args.ignore = ('yes' == pframe.args[table.concat ({n, 'ignore-false-positive'})]) or ('yes' == pframe.args[table.concat ({n, 'ignore-err'})]); | |||
-- args.ignore = 'yes' == pframe.args[table.concat ({n, 'ignore-err'})]; | |||
table.insert (out, core (args)); -- save the rendering of this source | table.insert (out, core (args)); -- save the rendering of this source | ||
Line 313: | Line 446: | ||
--[[--------------------------< | --[[--------------------------< S F N R E F >------------------------------------------------------------------ | ||
implements {{sfnref}} | |||
]] | |||
local function sfnref (frame) | |||
local args = getArgs (frame); | |||
local out = {}; | |||
for i=1, 5 do -- get the first five args if there are five args | |||
if args[i] then | |||
out[i] = args[i]; | |||
else | |||
break; -- less than 5 args break out | |||
end | |||
end | |||
if 5 == #out then -- when we have seen five args there may bemore | |||
local i = 6; -- initialize the indexer to the sixth positional parameter | |||
while args[i] do -- in case there are too many authors loop through the authors looking for a year | |||
if is_year (args[i], args) then -- if a year | |||
out[5] = args[i]; -- overwrite whatever was in args[5] with year | |||
break; -- and abandon the search | |||
end | |||
i = i + 1; -- bump the indexer | |||
end | |||
end | |||
return mw.uri.anchorEncode ('CITEREF' .. table.concat (out)); | |||
end | |||
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------ | |||
]] | ]] | ||
Line 320: | Line 486: | ||
sfn = sfn, | sfn = sfn, | ||
sfnm = sfnm, | sfnm = sfnm, | ||
sfnref = sfnref, | |||
}; | }; |