Module:Harvc
local f = {};
--[[--------------------------< I S _ S E T >------------------------------------------------------------------
Whether variable is set or not. A varable is set when it is not nil and not empty.
]]
local function is_set( var ) return not (var == nil or var == ); end
--[[--------------------------< M A K E _ N A M E >------------------------------------------------------------
Assembles last, first, link, or mask into a displayable contributor name.
]]
local function make_name (last, first, link, mask) local name = last;
if is_set (first) then name = name .. ', ' .. first; -- concatenate first onto last end
if is_set (link) then name = '' .. name .. ''; -- form a wikilink around the name end
if is_set (mask) then -- mask this author mask = tonumber (mask); -- because the value provided might not be a number if is_set (mask) then name = string.rep ('—', mask) -- make a string that number length of mdashes end end
return name; end
--[[--------------------------< C O R E >----------------------------------------------------------------------
Assembles the various parts provided by the template into a properly formatted bridging citation. Adds punctuation and text; encloses the whole within a span with id and class attributes.
This creates a CITEREF anchor from |last1= through |last4= and |year=. It also creates a CITEREF link from |in1= through |in4= and |year=. It is presumed that the dates of contributions are the same as the date of the enclosing work.
Even though not displayed, a year parameter is still required for the CITEREF anchor
]]
local function core( args ) local span_open_tag; -- holds CITEREF and css local contributors = ; -- chapter or contribution authors local source = ; -- editor/author date list that forms a CITEREF link to a full citation; mimics harvnb output except year in parentheses local in_text = ' In '; -- local result; -- the assemby of the above output
-- form the CITEREF anchor if is_set (args.id) then span_open_tag = ''; -- for use when contributor name is same as source name else span_open_tag = ''; end
--[[ form the contributors display list: if |name-list-format=harv, display is similar to [1] and ]], 1 to 4 last names; if |display-authors= is empty or omitted, display is similar to cs1|2: display all names in last, first order if |display-authors=etal then displays all author names in last, first order and append et al. if value assigned to |display-authors= is less than the number of author last names, displays the specified number of author names in last, first order followed by et al. if 'harv' ~= args.name_list_format then -- default cs1|2 style contributor list local i = 1; local count; local etal = false; -- when |display-authors= is same as number of authors in contributor list
if is_set (args.display_authors) then if 'etal' == args.display_authors:lower():gsub("[ '%.]", ) then -- the :gsub() portion makes 'etal' from a variety of 'et al.' spellings and stylings count = #args.last; -- display all authors and ... etal = true; -- ... append 'et al.' else count = tonumber (args.display_authors) or 0; -- 0 if can't be converted to a number if 0 >= count then args.err_msg = args.err_msg .. ' invalid |display-authors='; -- if zero, then emit error message end end if count > #args.last then count = #args.last; -- when |display-authors= is more than the number of authors, use the number of authors end if count < #args.last then -- when |display-authors= is less than the number of authors etal = true; -- append 'et al.' end else count = #args.last; -- set count to display all of the authors end
while i <= count do if is_set (contributors) then contributors = contributors .. '; ' .. make_name (args.last[i], args.first[i], args.link[i], args.mask[i]); -- the rest of the contributors else contributors = make_name (args.last[i], args.first[i], args.link[i], args.mask[i]); -- first contributor's name end i = i+1; -- bump the index end if true == etal then contributors = contributors .. ' et al.'; -- append et al. elseif 'yes' == args.last_author_amp then contributors = contributors:gsub('; ([^;]+)$', ' & %1') -- replace last separator with ' & ' end else -- do default harv- or sfn-style contributor display if 4 <= #args.last then -- four or more contributors (first followed by et al.) contributors = args.last[1] .. ' et al.'; elseif 3 == #args.last then -- three (display them all) contributors = args.last[1] .. ', ' .. args.last[2] .. ' & ' .. args.last[3]; elseif 2 == #args.last then -- two (first & second) contributors = args.last[1] .. ' & ' .. args.last[2]; elseif 1 == #args.last then -- just one (first) contributors = args.last[1]; else args.err_msg = args.err_msg .. ' no authors in contributor list.'; -- this code used to find holes in the list; no more end end
--form the source author-date list if is_set (args.in4) and is_set (args.in3) and is_set (args.in2) and is_set (args.in1) then source = args.in1 .. ' et al.'; elseif not is_set (args.in4) and is_set (args.in3) and is_set (args.in2) and is_set (args.in1) then source = args.in1 .. ', ' .. args.in2 .. ' & ' .. args.in3; elseif not is_set (args.in4) and not is_set (args.in3) and is_set (args.in2) and is_set (args.in1) then source = args.in1 .. ' & ' .. args.in2; elseif not is_set (args.in4) and not is_set (args.in3) and not is_set (args.in2) and is_set (args.in1) then source = args.in1; else args.err_msg = args.err_msg .. ' author missing from source list.' end
if args.year:match('^[1-9]%d%d%d?%l?$') or args.year:match('^n%.d%.%l?$') or args.year:match('^nd%l?$') then -- 3 or 4 digits, n.d., or nd and optional disambiguator
source = source .. ' (' .. args.year .. ')'; else args.err_msg = args.err_msg .. ' invalid or missing year.'; -- error message if year not provided or is imalformed end
--assemble CITEREF wikilink source = "[[#CITEREF" .. mw.uri.anchorEncode(table.concat ({args.in1, args.in2, args.in3, args.in4, args.year})) .. "|" .. source .. "]]";
--combine contribution with url to make external link if args.url ~= then args.contribution = '[' .. args.url .. ' ' .. args.contribution .. ']'; -- format external link end if args.sepc ~= contributors:sub(-1) and args.sepc .. ']]' ~= contributors:sub(-3) then contributors = contributors .. args.sepc; -- add separator if not same as last character in name list (|first=John S. or et al.) end
-- pages and other insource location if args.p ~= then args.p = args.page_sep .. args.p; elseif args.pp ~= then args.p = args.pages_sep .. args.pp; -- args.p not set so use it to hold common insource location info end
if args.loc ~= then args.p = args.p .. ', ' .. args.loc; -- add arg.loc to args.p end
--wrap error messages in span and add help link if is_set (args.err_msg) then args.err_msg = ' harvc:' .. args.err_msg .. ' (help)'; end
if ',' == args.sepc then in_text = in_text:lower(); -- CS2 style use lower case end
-- and put it all together result = span_open_tag .. contributors .. ' "' .. args.contribution .. '"' .. args.sepc .. in_text .. source .. args.p .. args.ps .. '' .. args.err_msg;
return result; end
--[[--------------------------< F . H A R V C >----------------------------------------------------------------
Entry point from . "". In [[#CITEREF|]]. harvc: required contribution is missing. author missing from source list. invalid or missing year. (help) template. Fetches parent frame parameters, does a bit of simple error checking
]] function f.harvc (frame) local args = { err_msg = , page_sep = ", p. ", pages_sep = ", pp. ", sepc = '.', ps = '.', last = {}, first = {}, link = {}, mask = {}, citeref = {} }
local pframe = frame:getParent();
args.contribution = pframe.args.c or -- chapter or contribution pframe.args.chapter or pframe.args.contribution or ;
args.id = pframe.args.id or ;
args.in1 = pframe.args['in'] or pframe.args.in1 or ; -- source editor surnames; 'in' is a Lua reserved keyword args.in2 = pframe.args.in2 or ; args.in3 = pframe.args.in3 or ; args.in4 = pframe.args.in4 or ;
args.display_authors = pframe.args['display-authors']; -- the number of contributor names to display; cs1/2 format includes first names args.name_list_format = pframe.args['name-list-format']; -- when set to 'harv' display contributor list in sfn or harv style args.last_author_amp = pframe.args['last-author-amp'] or -- yes only; |last-author-amp=no does not work (though it does in CS1|2) pframe.args['lastauthoramp'] or ; args.last_author_amp:lower(); -- make it case agnostic
if is_set (pframe.args['last1']) or is_set (pframe.args['last']) then -- must have at least this to continue args.last[1] = pframe.args.last or pframe.args.last1; -- get first contributor's last name args.citeref[1] = args.last[1]; -- add it to the citeref args.first[1] = pframe.args.first or pframe.args.first1; -- get first contributor's first name args.link[1] = pframe.args['author-link'] or pframe.args['author-link1']; -- get first contributor's article link args.mask[1] = pframe.args['author-mask'] or pframe.args['author-mask1']; -- get first contributor's article link
local i = 2; -- index for the rest of the names while is_set (pframe.args['last'..i]) do -- loop through pfram.args and get the rest of the names args.last[i] = pframe.args['last'..i]; -- last names args.first[i] = pframe.args['first'..i]; -- first names args.link[i] = pframe.args['author-link'..i]; -- first names args.mask[i] = pframe.args['author-mask'..i]; -- first names if 5 > i then args.citeref[i] = args.last[i]; -- collect first four last names for CITEREF anchor end i = i + 1 -- bump the index end end
args.p = pframe.args.p or ; -- source page number(s) or location args.pp = pframe.args.pp or ; args.loc = pframe.args.loc or ;
if 'cs2' == pframe.args.mode then args.ps = ; -- set postscript character to empty string, cs2 mode args.sepc = ','; -- set seperator character to comma, cs2 mode end do -- to limit scope of local temp local temp = pframe.args.ps or pframe.args.postscript;
if is_set (temp) then if 'none' == temp:lower() then -- if |ps=none or |postscript=none then args.ps = ; -- no postscript else args.ps = temp; -- override default postscript end end end -- end of scope limit
args.url = pframe.args.url or -- url for chapter or contribution pframe.args['chapter-url'] or pframe.args['contribution-url'] or ;
args.year = pframe.args.year or ; -- required
if not is_set (args.contribution) then args.err_msg = args.err_msg .. ' required contribution is missing.'; -- error message if source not provided args.contribution = args.url; -- if set it will give us linkable text end
if args.last[1] == args.in1 and args.last[2] == args.in2 and args.last[3] == args.in3 and args.last[4] == args.in4 and not is_set (args.id) then args.err_msg = args.err_msg .. ' required |id= parameter missing.'; -- error message if contributor and source are the same end
return core (args); end
return f;
- ↑ [[#CITEREF|]].