end  
if is_set (args.p) and is_set (args.pp) then
args.err_msg = string.format ('%s more than one of <code>|page=</code> and <code>|pages=</code>; ', args.err_msg, code_style, code_style);
end  
return table.concat (output, ', '); -- concatenate with comma space as separator
end  
--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 separators
end  
--oclc= and |accession into the identifiers portion of the citation. Neither of these
parameters are required.  
local function make_identifiers (args)
local output = {}; -- table ofidentifier bits
if is_set (args.oclc) then
table.insert (output, string.format ('OCLC&nbsp;%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 separator
end  
--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 * ~= args.ref and 'harv' ~= args.ref then -- |ref= has a value that is not * and not 'harv' so use that value as the anchor ID
cite_open_tag = '<cite id="' .. args.ref .. '">';
elseif 0 ~= #args.citeref and * ~= args.ref then -- there is an author list and |ref= has a value that is not * so create a CITEREF anchor
cite_open_tag = '<cite id="CITEREF' .. table.concat (args.citeref) .. args.year .. '">';
else
cite_open_tag = '<cite>'; -- no author list or |ref=; 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 = '<span> cite archive:' .. args.err_msg .. ' (help)</span>';
end  
-- and put it all together and be done
return string.format ('%s%s%s</cite>%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 parameters, does a bit of simple error checking
and calls _cite_archive if required parameters are present.  
function f.cite_archive
local args = {
err_msg = '',
page_sep = "p.&nbsp;", -- cs1|2 style page(s) prefixes
pages_sep = "pp.&nbsp;",
retrieved = 'Retrieved ', -- cs1 style access date static text
sepc = '.', -- default to cs1 stylre
ps = '.', -- default to cs1 stylre
last = {}, -- table of author last name values
first = {}, -- table of author first name values
link = {}, -- table of author link values
mask = {}, -- table of author mask values
citeref = {} -- table of last names that will be used in making the CITEREF anchor
}  
local pframe = :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 (' <code>|collection=</code> required; ', code_style);
end
if not is_set (args.institution) then
args.err_msg = string.format ('%s <code>|institution=</code> 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 '<span>cite archive:' .. args.err_msg .. ' (help)</span>'; -- with an error message
end  
-- 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 ({ -- get first author's last name
['last']=pframe.args.last,
['last1'] = pframe.args.last1,
['author'] = pframe.args.author,
['author1'] = pframe.args.author1}, args);
args.citeref[1] = args.last[1]; -- add it to the citeref  
args.first[1] = select_one ({ -- get first author's first name
['first'] = pframe.args.first,
['first1'] = pframe.args.first1}, args);
args.link[1] = select_one ({ -- get first author's article link
['author-link'] = pframe.args['author-link'],
['author-link1'] = pframe.args['author-link1']}, args);
args.mask[1] = select_one ({ -- get first author's mask
['author-mask'] = pframe.args['author-mask'],
['author-mask1'] = pframe.args['author-mask1']}, 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