else
table.insert (vnames, split[i]); -- and add name to the vnames table
end
i=i+1; -- bump indexer
if 5 == i then break; end -- limit to four names
end  
for i, vname in ipairs (vnames) do
if not vname:match ('%(%(.-%)%)') then -- without accept-this-value-as-written markup
vnames[i] = vname:gsub ('(.-)%s+%u+$', '%1'); -- extract and save surname(s)
end
end
for i, vname in ipairs (vnames) do -- repeat, this time for accept-this-value-as-written markup
vnames[i] = vname:gsub ('%(%((.-)%)%)', '%1'); -- remove markup if present and save the whole name
end
end  
return 0 ~= #vnames and table.concat (vnames) or nil -- return a concatenation of the vnames; nil else
end  
--2 makes anchor id from contributor, author, or editor name-lists in that order  
get the names from the cs1|2 template; if there are no contributor names, try author names, then try editor names.  
returns concatenated names in enumeration order when successful; nil else  
empty name (nameholding parameter n is present without value) and missing name (nameholding parameter n is not
present) are included as empty string with all other names  
local function names_get (params, aliases_list)
local names = {}; -- first four author or editor names go here
local enum_alias; -- alias with '#' replaced with a digit  
for enum=1, 4 do -- four names only
for i, alias in ipairs (aliases_list) do
if not names[enum] then -- hanven't found a previous alias with this [enum]? see if we can find this alias with this enum
enum_alias = alias:gsub ('#', enum); -- replace '#' to make 'lastn'  
if 1 == enum then -- because |last= and last1= are exact aliases
if params[enum_alias] then -- test |last1= first
names[enum] = params[enum_alias]; -- found so save the value assigned to |last1=
break; -- next enum
else
enum_alias = alias:gsub ('#', ''); -- replace '#' to make 'last'
if params[enum_alias] then
names[enum] = params[enum_alias]; -- found so save the value assigned to |last=
break; -- next enum
end
end
else -- here for enum 2, 3, 4
if params[enum_alias] then
names[enum] = params[enum_alias]; -- found so save the value assigned to |lastn=
break; -- next enum
end
end
end
end
end  
for enum=1, 4 do -- spin through the names table and
local name = names[enum];
if not name then -- when nameholding parameter n is not present (nil)
name = ''; -- convert to empty string for concatenation
end
name = name:gsub('%(%((.-)%)%)', '%1'); -- remove accept-as-written markup if present
names[enum] = name; -- save the modified name
end  
local name_str = table.concat (names); -- concatenate the names
return '' ~= name_str and name_str or nil; -- return the concatenation if not empty string; nil else
end  
--2 does
not see the template markup but instead sees the result of the template as html. cs1|2 strips the html which
leaves the displayed value for the anchor id. We can't do that here so, because templates aren't allowed in
parameters, we simply discard any templates found in the cs1|2 template.  
this may leave a |lastn= parameter empty which will be treated as if it were really empty as cs1|2 do (three authors,
|last2= empty -> CITEREFLast1Last3YYYY (the harv and sfn render: 'Last1, & Last3 YYYY' with CITEREFLast1Last3YYYY).  
local function template_strip (template)
template = template:gsub ('^$', '', 1); -- remove outer (cs1|2 template delimiters with trailing/leading whitespace)
template = template:gsub ('%b{}', ''); -- remove any templates from the cs1|2 template
return template;
end  
----------------------------< E S C A P E _ L U A _ M A G I C _ C H A R S >----------------------------------  
Returns a string where all of lua's magic characters have been escaped. This is important because functions like
string.gsub treat their pattern and replace strings as patterns, not literal strings.  
local function escape_lua_magic_chars (argument)
argument = argument:gsub("%%", "%%%%"); -- replace % with %%
argument = argument:gsub("([%^%$%(%)%.%[%]%*%+%-%?])", "%%%1"); -- replace all other lua magic pattern characters
return argument;
end  
--[=[-------------------------< W I K I L I N K _ S T R I P >--------------------------------------------------  
Wikilink markup does not belong in an anchor id and can / does confuse the code that parses apart citation and
harvc templates so here we remove any wiki markup:
label -> label
link -> link  
]=]  
local function wikilink_strip (template)
for wikilink in template:gmatch ('%[%b[]%]') do -- get a wikilink
template = template:gsub ('%[%b[]%]', '__57r1P__', 1); -- install a marker
if wikilink:match ('%[%[.-|(.-)%]%]') then
wikilink = wikilink:match ('%[%[.-|(.-)%]%]'); -- extract label from complex label wikilink
else
wikilink = wikilink:match ('%[%[(.-)%]%]'); -- extract link from simple link wikilinks
end
wikilink = escape_lua_magic_chars (wikilink); -- in case there are lua magic characters in wikilink
template = template:gsub ('__57r1P__', wikilink, 1); -- replace the marker with the appropriate text
end  
return template;
end  
----------------------------< T E M P L A T E _ N A M E _ G E T >--------------------------------------------  
return the citation or harvc template's name; convert to lower case and trim leading and trailing whitespace;  
when the template is a sandbox the subpage portion of the template name is omitted from the returned template name
returns cite book  
local function template_name_get (template)
local template_name = template:match ('^ (no spaces between assignment operator and pipe or closing brace)
ref = mw.text.trim (ref); -- something, could be just whitespace, so trim leading / trailing whitespace
if '' == ref then -- trimming a string of whitespace makes an empty string
ref = nil; -- make empty ref same as missing ref
end
end
end
end  
template_params_get (template, params); -- build a table of template parameters and their values  
if whitelist.wrapper_templates[template_name][1] then -- is this wrapper a simple-default wrapper?
name_default = whitelist.wrapper_templates[template_name][1]; -- get the default names
date_default = whitelist.wrapper_templates[template_name][2]; -- get the default date
else
vol = params['volume'] or 'default';
if not whitelist.wrapper_templates[template_name][vol] then -- make sure this volume exists
vol = 'default'; -- doesn't exist, use default volume
end
name_default = whitelist.wrapper_templates[template_name][vol][1]; -- get the default names
date_default = whitelist.wrapper_templates[template_name][vol][2]; -- get the default date
end  
if 'harv' == ref or not ref then -- |ref=harv specified or |ref= missing or empty
anchor_id = names_get (params, aliases_contributor) or -- get contributor, author, or editor names
names_get (params, aliases_author) or
vnames_get (params, 'vauthors') or -- |vauthors=
names_get (params, aliases_editor) or
vnames_get (params, 'veditors') or -- |veditors=
name_default; -- default names from whitelist
-- whitelist.wrapper_templates[template_name][1]; -- default names from whitelist  
if '' == date then -- if date not provided in the template
date = date_default; -- use the default date from whitelist
end  
if anchor_id then -- if names were gotten
anchor_id = 'CITEREF' .. anchor_id .. date;
end  
elseif ref:match ('%b{}') then -- ref holds a template
anchor_id = sfnref_get (ref); -- returns content of or ; nil else  
elseif '' == ref then -- |ref=
return nil; -- anchor id expicitly suppressed  
else
anchor_id = ref; -- |ref=<text> may match an anchor id override value in template |ref= parameter
end  
return anchor_id; -- anchor_id text; nil else
end  
--2 template and cs1-like templates  
inspect |ref= to decide what to do:
|ref= - empty or missing: get names and date from template parameters; all cs1|2 create CITEREF anchor IDs
|ref=harv - get names and date from template parameters
|ref= - assemble an anchor id from positional parameters
|ref= - assemble an anchor id from positional parameters