require('strict')local f = ;local code_style="color:inherit; border:inherit; padding:inherit;"; -- used in styling error messages
local lock_icons =
----------------------------< I S _ S E T >------------------------------------------------------------------
Whether variable is set or not. A variable is set when it is not nil and not empty.
local function is_set(var) return not (var
);end
----------------------------< S E L E C T _ O N E >----------------------------------------------------------
Choose one parameter value from a list of parameter values. If more than one is set, emit error message.
local function select_one (list, args) local selected_param; local selected_val=;
for param, value in pairs (list) do -- loop through the list if not is_set (selected_param) then -- if we have not yet selected a parameter value if is_set (value) then -- is this value set? selected_val = value; -- select it selected_param = param; -- remember the name for possible error message end else if is_set (value) then -- error message if we have selected and found another set parameter args.err_msg = string.format (' more than one of |%s=
and |%s=
', code_style, selected_param, code_style, param ) break; end end end return selected_val or ; -- return selected value or empty string if none setend
----------------------------< M A K E _ N A M E >------------------------------------------------------------
Assembles last, first, link, or mask into a displayable author 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
--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.
local function make_author_list (args, number_of_authors) local authors = ; 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'
|display-authors=
; ', args.err_msg, code_style);-- args.err_msg = args.err_msg .. ' invalid |display-authors='; -- if zero, then emit error message count = number_of_authors; -- and display all authors end end if count > number_of_authors then count = number_of_authors; -- when |display-authors= is more than the number of authors, use the number of authors end if count < number_of_authors then -- when |display-authors= is less than the number of authors etal = true; -- append 'et al.' end else count = number_of_authors; -- set count to display all of the authors end while i <= count do if is_set (authors) then authors = authors .. '; ' .. make_name (args.last[i], args.first[i], args.link[i], args.mask[i]); -- the rest of the authors else authors = make_name (args.last[i], args.first[i], args.link[i], args.mask[i]); -- first author's name end i = i+1; -- bump the index end if true etal then authors = authors .. '; et al.'; -- append et al. elseif 'yes'
-- if args.sepc ~= authors:sub(-1) and args.sepc .. ']]' ~= authors:sub(-3) then-- authors = authors; -- add separator if not same as last character in name list (|first=John S. or et al.)-- end -- TODO: better way to handle wikilink case? authors = authors:gsub ('%' .. args.sepc .. '$', , 1); -- remove trailing separator character authors = authors:gsub ('%' .. args.sepc .. ']]$', ']]', 1); -- remove trailing separator character inside wikilink
return authors;end
--item= and, if present, |item-url= into the linked part and if present appends |date= and|type= with appropriate markup to complete the item portion of the citation. This function assumes that itemhas a value when it is called.
local function make_item (item, url, item_date, item_type, item_access) local output = ; -- table of item bits if is_set (url) then item = string.format ('[%s %s]', url, item); -- make item into an external wikilink end if item_access and ('subscription'
item_access) then table.insert (output, table.concat); else table.insert (output, string.format ('"%s"', item)); -- enclose in quotes and add to table end if is_set (item_date) then table.insert (output, string.format ('(%s)', item_date)); -- enclose in parentheses and add to table end if is_set (item_type) then table.insert (output, string.format ('[%s]', item_type)); -- enclose in square brackets and add to table end return table.concat (output, ' '); -- concatenate with space as separatorend
--collection= and, if present, |collection-url= into the linked part and if present, appendsthe values from |fonds=, |series=, |box=, |file=, |itemid=, and |page= or |pages= to complete the collectionportion of the citation. This function assumes that collection has a value when it is called (because that is oneof the two required parameters)
local function make_collection (args) local output = ; -- table of collections bits local collection = args.collection; if is_set (args.collectionURL) then collection = string.format ('[%s %s]', args.collectionURL, collection); -- make collection into an external wikilink end table.insert (output, string.format ('%s', collection)); -- enclose in quotes and add to table if is_set (args.fonds) then table.insert (output, string.format ('Fonds: %s', args.fonds)); -- format and add to table end if is_set (args.series) then table.insert (output, string.format ('Series: %s', args.series)); -- format and add to table end if is_set (args.box) then table.insert (output, string.format ('Box: %s', args.box)); -- format and add to table end if is_set (args.file) then table.insert (output, string.format ('File: %s', args.file)); -- format and add to table end if is_set (args.itemID) then table.insert (output, string.format ('ID: %s', args.itemID)); -- format and add to table end if is_set (args.p) then table.insert (output, string.format ('%s%s', args.page_sep, args.p)); elseif is_set (args.pp) then table.insert (output, string.format ('%s%s', args.pages_sep, args.pp)); end if is_set (args.p) and is_set (args.pp) then args.err_msg = string.format ('%s more than one of |page=
and |pages=
; ', args.err_msg, code_style, code_style); end return table.concat (output, ', '); -- concatenate with comma space as separatorend
--location=, |repository, and |institution= into the location portion of the citation.This function assumes that |institution= (a required parameter) has a value when it is called.
Unlike other groups of parameters, the required parameter is the 'last' and separator characters are not all the same.
local function make_location (location, repository, institution) local output = ; -- table of location bits if is_set (location) then location = string.format ('%s: ', location); -- format end if is_set (repository) then table.insert (output, repository); -- and add to table end table.insert (output, institution); -- and add to table return string.format ('%s%s', location, table.concat (output, ', ')); -- concatenate with comma space separatorsend
--oclc= and |accession into the identifiers portion of the citation. Neither of theseparameters are required.
local function make_identifiers (args) local output = ; -- table ofidentifier bits if is_set (args.oclc) then table.insert (output, string.format ('OCLC %s', args.oclc)); end if is_set (args.accession) then table.insert (output, args.accession); end return table.concat (output, args.sepc .. ' '); -- concatenate with sepc space as separatorend
--last1= through |last4= and the year portion of |date= when |ref=harv.
local function _cite_archive (args) local cite_open_tag; -- holds CITEREF and css local authors = ; -- list of authors local identifiers = ; -- OCLC and accession identifiers list local result = ; -- the assembly of the citation's output
-- form the anchor ID if is_set (args.ref) and 'none' ~= args.ref and 'harv' ~= args.ref then -- |ref= has a value that is not 'none' and not 'harv' so use that value as the anchor ID cite_open_tag = ''; elseif 0 ~= #args.citeref and 'none' ~= args.ref then -- there is an author list and |ref= has a value that is not 'none' so create a CITEREF anchor cite_open_tag = ''; else cite_open_tag = ''; -- no author list or |ref=none; no anchor ID end
if 0 ~= #args.last then -- if there are author names table.insert (result, make_author_list (args, #args.last)); -- assemble author name list and add to result table end if is_set (args.item) then -- if there is an item table.insert (result, make_item (args.item, args.itemURL, args.date, args.type, args.item_access)); -- build the item portion of the citation end
table.insert (result, make_collection (args)); -- build the collection portion of the citation (|collection= is required)
table.insert (result, make_location (args.location, args.repository, args.institution)); -- build the location portion of the citation (institution= is required)
identifiers = make_identifiers (args); -- build the identifiers (oclc and accession) portion of the citation if is_set (identifiers) then table.insert (result, identifiers); end
if is_set (args.accessdate) then table.insert (result, args.retrieved .. args.accessdate); end
-- wrap error messages in span and add help link if is_set (args.err_msg) then args.err_msg = '
cite archive:' .. args.err_msg .. ' (help)'; end-- and put it all together and be done return string.format ('%s%s%s%s', cite_open_tag, table.concat (result, args.sepc .. ' '), args.ps, args.err_msg);end
----------------------------< F . C I T E _ A R C H I V E >--------------------------------------------------
Entry point from template. Fetches parent frame parameters, does a bit of simple error checkingand calls _cite_archive if required parameters are present.
function f.cite_archive (frame) local args =
local pframe = frame:getParent; -- get template's parameters
args.item = pframe.args.item or ; -- these are the 'item' group args.itemURL = pframe.args['item-url'] or ; args.item_access = pframe.args['item-url-access']; args.type = pframe.args.type or ; args.date = pframe.args.date or ;
args.year = args.date:match ('%d%d%d%d') or ; -- used in creation of the CITEREF anchor
args.collection = pframe.args.collection or ; -- these are the collection group args.collectionURL = pframe.args['collection-url'] or ; args.fonds = pframe.args.fonds or ; args.series = pframe.args.series or ; args.file = pframe.args.file or ; args.box = pframe.args.box or ; args.itemID = pframe.args['item-id'] or ; args.p = pframe.args.page or pframe.args.p or ; -- if both are set, the singular is rendered args.pp = pframe.args.pages or pframe.args.pp or ;
args.repository = pframe.args.repository or ; -- these are the location group args.location = pframe.args.location or ; args.institution = pframe.args.institution or ; -- required parameter
args.oclc = pframe.args.oclc or ; -- these are the identifiers group args.accession = pframe.args.accession or ; if not is_set (args.collection) then -- check for required parameters args.err_msg = string.format (' |collection=
required; ', code_style); end if not is_set (args.institution) then args.err_msg = string.format ('%s |institution=
required; ', args.err_msg, code_style); end if is_set (args.err_msg) then -- if set here, then we are missing one or both required parameters so quit return '
-- standard cs1|2 parameters args.accessdate = pframe.args['access-date'] or pframe.args.accessdate or ;
args.ref = pframe.args.ref or ; args.display_authors = pframe.args['display-authors']; -- the number of author names to display args.last_author_amp = pframe.args['last-author-amp'] or -- yes only; |last-author-amp=no does not work 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']) or is_set (pframe.args['author1']) or is_set (pframe.args['author']) then -- must have at least this to continue args.last[1] = select_one (args); args.citeref[1] = args.last[1]; -- add it to the citeref
args.first[1] = select_one (args); args.link[1] = select_one (args); args.mask[1] = select_one (args); local i = 2; -- index for the rest of the names while is_set (pframe.args['last'..i]) or is_set (pframe.args['author'..i]) do -- loop through pframe.args and get the rest of the names args.last[i] = pframe.args['last'..i] or pframe.args['author'..i]; -- last names args.first[i] = pframe.args['first'..i]; -- first names args.link[i] = pframe.args['author-link'..i]; -- author-links args.mask[i] = pframe.args['author-mask'..i]; -- author-masks 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
if 'cs2'
return table.concat ;end
return f;