<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://www.1ok.de/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Timetrave</id>
	<title>Our Time Travel Wiki - Benutzerbeiträge [de]</title>
	<link rel="self" type="application/atom+xml" href="https://www.1ok.de/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Timetrave"/>
	<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Spezial:Beitr%C3%A4ge/Timetrave"/>
	<updated>2026-04-22T16:10:05Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.43.1</generator>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Modul:Navbar/configuration&amp;diff=1539</id>
		<title>Modul:Navbar/configuration</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Modul:Navbar/configuration&amp;diff=1539"/>
		<updated>2022-08-12T16:59:12Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;return {&lt;br /&gt;
	[&#039;templatestyles&#039;] = &#039;Module:Navbar/styles.css&#039;,&lt;br /&gt;
	[&#039;box_text&#039;] = &#039;This box: &#039;,			-- default text box when not plain or mini&lt;br /&gt;
	[&#039;title_namespace&#039;] = &#039;Template&#039;,		-- namespace to default to for title&lt;br /&gt;
	[&#039;invalid_title&#039;] = &#039;Invalid title &#039;,&lt;br /&gt;
	[&#039;classes&#039;] = { -- set a line to nil if you don&#039;t want it&lt;br /&gt;
		[&#039;navbar&#039;] = &#039;navbar&#039;,&lt;br /&gt;
		[&#039;plainlinks&#039;] = &#039;plainlinks&#039;, -- plainlinks&lt;br /&gt;
		[&#039;horizontal_list&#039;] = &#039;hlist&#039;, -- horizontal list class&lt;br /&gt;
		[&#039;mini&#039;] = &#039;navbar-mini&#039;, -- class indicating small links in the navbar&lt;br /&gt;
		[&#039;this_box&#039;] = &#039;navbar-boxtext&#039;,&lt;br /&gt;
		[&#039;brackets&#039;] = &#039;navbar-brackets&#039;,&lt;br /&gt;
		-- &#039;collapsible&#039; is the key for a class to indicate the navbar is&lt;br /&gt;
		-- setting up the collapsible element in addition to the normal&lt;br /&gt;
		-- navbar.&lt;br /&gt;
		[&#039;collapsible&#039;] = &#039;navbar-collapse&#039;,&lt;br /&gt;
		[&#039;collapsible_title_mini&#039;] = &#039;navbar-ct-mini&#039;,&lt;br /&gt;
		[&#039;collapsible_title_full&#039;] = &#039;navbar-ct-full&#039;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Modul:Navbar&amp;diff=1537</id>
		<title>Modul:Navbar</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Modul:Navbar&amp;diff=1537"/>
		<updated>2022-08-12T16:59:12Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;local p = {}&lt;br /&gt;
local cfg = mw.loadData(&#039;Module:Navbar/configuration&#039;)&lt;br /&gt;
&lt;br /&gt;
local function get_title_arg(is_collapsible, template)&lt;br /&gt;
	local title_arg = 1&lt;br /&gt;
	if is_collapsible then title_arg = 2 end&lt;br /&gt;
	if template then title_arg = &#039;template&#039; end&lt;br /&gt;
	return title_arg&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function choose_links(template, args)&lt;br /&gt;
	-- The show table indicates the default displayed items.&lt;br /&gt;
	-- view, talk, edit, hist, move, watch&lt;br /&gt;
	-- TODO: Move to configuration.&lt;br /&gt;
	local show = {true, true, true, false, false, false}&lt;br /&gt;
	if template then&lt;br /&gt;
		show[2] = false&lt;br /&gt;
		show[3] = false&lt;br /&gt;
		local index = {t = 2, d = 2, e = 3, h = 4, m = 5, w = 6,&lt;br /&gt;
			talk = 2, edit = 3, hist = 4, move = 5, watch = 6}&lt;br /&gt;
		-- TODO: Consider removing TableTools dependency.&lt;br /&gt;
		for _, v in ipairs(require (&#039;Module:TableTools&#039;).compressSparseArray(args)) do&lt;br /&gt;
			local num = index[v]&lt;br /&gt;
			if num then show[num] = true end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local remove_edit_link = args.noedit&lt;br /&gt;
	if remove_edit_link then show[3] = false end&lt;br /&gt;
	&lt;br /&gt;
	return show&lt;br /&gt;
	&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function add_link(link_description, ul, is_mini, font_style)&lt;br /&gt;
	local l&lt;br /&gt;
	if link_description.url then&lt;br /&gt;
		l = {&#039;[&#039;, &#039;&#039;, &#039;]&#039;}&lt;br /&gt;
	else&lt;br /&gt;
		l = {&#039;[[&#039;, &#039;|&#039;, &#039;]]&#039;}&lt;br /&gt;
	end&lt;br /&gt;
	ul:tag(&#039;li&#039;)&lt;br /&gt;
		:addClass(&#039;nv-&#039; .. link_description.full)&lt;br /&gt;
		:wikitext(l[1] .. link_description.link .. l[2])&lt;br /&gt;
		:tag(is_mini and &#039;abbr&#039; or &#039;span&#039;)&lt;br /&gt;
			:attr(&#039;title&#039;, link_description.html_title)&lt;br /&gt;
			:cssText(font_style)&lt;br /&gt;
			:wikitext(is_mini and link_description.mini or link_description.full)&lt;br /&gt;
			:done()&lt;br /&gt;
		:wikitext(l[3])&lt;br /&gt;
		:done()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function make_list(title_text, has_brackets, displayed_links, is_mini, font_style)&lt;br /&gt;
	&lt;br /&gt;
	local title = mw.title.new(mw.text.trim(title_text), cfg.title_namespace)&lt;br /&gt;
	if not title then&lt;br /&gt;
		error(cfg.invalid_title .. title_text)&lt;br /&gt;
	end&lt;br /&gt;
	local talkpage = title.talkPageTitle and title.talkPageTitle.fullText or &#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
	-- TODO: Get link_descriptions and show into the configuration module.&lt;br /&gt;
	-- link_descriptions should be easier...&lt;br /&gt;
	local link_descriptions = {&lt;br /&gt;
		{ [&#039;mini&#039;] = &#039;v&#039;, [&#039;full&#039;] = &#039;view&#039;, [&#039;html_title&#039;] = &#039;View this template&#039;,&lt;br /&gt;
			[&#039;link&#039;] = title.fullText, [&#039;url&#039;] = false },&lt;br /&gt;
		{ [&#039;mini&#039;] = &#039;t&#039;, [&#039;full&#039;] = &#039;talk&#039;, [&#039;html_title&#039;] = &#039;Discuss this template&#039;,&lt;br /&gt;
			[&#039;link&#039;] = talkpage, [&#039;url&#039;] = false },&lt;br /&gt;
		{ [&#039;mini&#039;] = &#039;e&#039;, [&#039;full&#039;] = &#039;edit&#039;, [&#039;html_title&#039;] = &#039;Edit this template&#039;,&lt;br /&gt;
			[&#039;link&#039;] = title:fullUrl(&#039;action=edit&#039;), [&#039;url&#039;] = true },&lt;br /&gt;
		{ [&#039;mini&#039;] = &#039;h&#039;, [&#039;full&#039;] = &#039;hist&#039;, [&#039;html_title&#039;] = &#039;History of this template&#039;,&lt;br /&gt;
			[&#039;link&#039;] = title:fullUrl(&#039;action=history&#039;), [&#039;url&#039;] = true },&lt;br /&gt;
		{ [&#039;mini&#039;] = &#039;m&#039;, [&#039;full&#039;] = &#039;move&#039;, [&#039;html_title&#039;] = &#039;Move this template&#039;,&lt;br /&gt;
			[&#039;link&#039;] = mw.title.new(&#039;Special:Movepage&#039;):fullUrl(&#039;target=&#039;..title.fullText), [&#039;url&#039;] = true },&lt;br /&gt;
		{ [&#039;mini&#039;] = &#039;w&#039;, [&#039;full&#039;] = &#039;watch&#039;, [&#039;html_title&#039;] = &#039;Watch this template&#039;, &lt;br /&gt;
			[&#039;link&#039;] = title:fullUrl(&#039;action=watch&#039;), [&#039;url&#039;] = true }&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	local ul = mw.html.create(&#039;ul&#039;)&lt;br /&gt;
	if has_brackets then&lt;br /&gt;
		ul:addClass(cfg.classes.brackets)&lt;br /&gt;
			:cssText(font_style)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	for i, _ in ipairs(displayed_links) do&lt;br /&gt;
		if displayed_links[i] then add_link(link_descriptions[i], ul, is_mini, font_style) end&lt;br /&gt;
	end&lt;br /&gt;
	return ul:done()&lt;br /&gt;
	&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._navbar(args)&lt;br /&gt;
	&lt;br /&gt;
	-- TODO: We probably don&#039;t need both fontstyle and fontcolor...&lt;br /&gt;
	local font_style = args.fontstyle&lt;br /&gt;
	local font_color = args.fontcolor&lt;br /&gt;
	local is_collapsible = args.collapsible&lt;br /&gt;
	local is_mini = args.mini&lt;br /&gt;
	local is_plain = args.plain&lt;br /&gt;
	&lt;br /&gt;
	local collapsible_class = nil&lt;br /&gt;
	if is_collapsible then&lt;br /&gt;
		collapsible_class = cfg.classes.collapsible&lt;br /&gt;
		if not is_plain then is_mini = 1 end&lt;br /&gt;
		if font_color then&lt;br /&gt;
			font_style = (font_style or &#039;&#039;) .. &#039;; color: &#039; .. font_color .. &#039;;&#039;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local navbar_style = args.style&lt;br /&gt;
	local div = mw.html.create():tag(&#039;div&#039;)&lt;br /&gt;
	div&lt;br /&gt;
		:addClass(cfg.classes.navbar)&lt;br /&gt;
		:addClass(cfg.classes.plainlinks)&lt;br /&gt;
		:addClass(cfg.classes.horizontal_list)&lt;br /&gt;
		:addClass(collapsible_class) -- we made the determination earlier&lt;br /&gt;
		:cssText(navbar_style)&lt;br /&gt;
&lt;br /&gt;
	if is_mini then div:addClass(cfg.classes.mini) end&lt;br /&gt;
&lt;br /&gt;
	local box_text = (args.text or cfg.box_text) .. &#039; &#039;&lt;br /&gt;
	 -- the concatenated space guarantees the box text is separated&lt;br /&gt;
	if not (is_mini or is_plain) then&lt;br /&gt;
		div&lt;br /&gt;
			:tag(&#039;span&#039;)&lt;br /&gt;
				:addClass(cfg.classes.box_text)&lt;br /&gt;
				:cssText(font_style)&lt;br /&gt;
				:wikitext(box_text)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local template = args.template&lt;br /&gt;
	local displayed_links = choose_links(template, args)&lt;br /&gt;
	local has_brackets = args.brackets&lt;br /&gt;
	local title_arg = get_title_arg(is_collapsible, template)&lt;br /&gt;
	local title_text = args[title_arg] or (&#039;:&#039; .. mw.getCurrentFrame():getParent():getTitle())&lt;br /&gt;
	local list = make_list(title_text, has_brackets, displayed_links, is_mini, font_style)&lt;br /&gt;
	div:node(list)&lt;br /&gt;
&lt;br /&gt;
	if is_collapsible then&lt;br /&gt;
		local title_text_class&lt;br /&gt;
		if is_mini then&lt;br /&gt;
			title_text_class = cfg.classes.collapsible_title_mini&lt;br /&gt;
		else&lt;br /&gt;
			title_text_class = cfg.classes.collapsible_title_full&lt;br /&gt;
		end&lt;br /&gt;
		div:done()&lt;br /&gt;
			:tag(&#039;div&#039;)&lt;br /&gt;
			:addClass(title_text_class)&lt;br /&gt;
			:cssText(font_style)&lt;br /&gt;
			:wikitext(args[1])&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return mw.getCurrentFrame():extensionTag{&lt;br /&gt;
		name = &#039;templatestyles&#039;, args = { src = cfg.templatestyles }&lt;br /&gt;
	} .. tostring(div:done())&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.navbar(frame)&lt;br /&gt;
	return p._navbar(require(&#039;Module:Arguments&#039;).getArgs(frame))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Modul:Icon/data&amp;diff=1535</id>
		<title>Modul:Icon/data</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Modul:Icon/data&amp;diff=1535"/>
		<updated>2022-08-12T16:59:12Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module stores icon data for [[Module:Icon]].&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Icon data&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local data = {&lt;br /&gt;
	fa = {&lt;br /&gt;
		image = &amp;quot;Featured article star.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Featured article&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	far = {&lt;br /&gt;
		image = &amp;quot;Cscr-star piece.png&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Featured article review&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	farc = {&lt;br /&gt;
		image = &amp;quot;Cscr-star piece.png&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Featured article removal candidate&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	ffa = {&lt;br /&gt;
		aliases = {&amp;quot;dfa&amp;quot;},&lt;br /&gt;
		image = &amp;quot;Featured article star - cross.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Former featured article&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	fac = {&lt;br /&gt;
		aliases = {&amp;quot;fan&amp;quot;},&lt;br /&gt;
		image = &amp;quot;Cscr-candidate.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Featured article candidate&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	ffac = {&lt;br /&gt;
		aliases = {&amp;quot;nofa&amp;quot;},&lt;br /&gt;
		image = &amp;quot;Featured article star - cross.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Failed featured article candidate&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	fl = {&lt;br /&gt;
		image = &amp;quot;Featured article star.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Featured list&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	flrc = {&lt;br /&gt;
		aliases = {&amp;quot;flr&amp;quot;},&lt;br /&gt;
		image = &amp;quot;Cscr-star piece.png&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Featured list removal candidate&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	ffl = {&lt;br /&gt;
		aliases = {&amp;quot;dfl&amp;quot;},&lt;br /&gt;
		image = &amp;quot;Cscr-featured-strike.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Former featured list&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	flc = {&lt;br /&gt;
		aliases = {&amp;quot;fln&amp;quot;},&lt;br /&gt;
		image = &amp;quot;Cscr-candidate.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Featured list candidate&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	fflc = {&lt;br /&gt;
		aliases = {&amp;quot;nofl&amp;quot;},&lt;br /&gt;
		image = &amp;quot;Cscr-former.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Failed featured list candidate&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	a = {&lt;br /&gt;
		image = &amp;quot;Symbol a class.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;A-Class article&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	dac = {&lt;br /&gt;
		aliases = {&amp;quot;daa&amp;quot;},&lt;br /&gt;
		image = &amp;quot;Symbol unsupport A vote.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Demoted A-Class article&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	acc = {&lt;br /&gt;
		aliases = {&amp;quot;acn&amp;quot;, &amp;quot;aac&amp;quot;},&lt;br /&gt;
		image = &amp;quot;A candidate.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;A-Class article candidate&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	noac = {&lt;br /&gt;
		aliases = {&amp;quot;faac&amp;quot;},&lt;br /&gt;
		image = &amp;quot;Symbol unsupport A vote.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Failed A-Class article candidate&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	ga = {&lt;br /&gt;
		image = &amp;quot;Symbol support vote.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Good article&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	gar = {&lt;br /&gt;
		image = &amp;quot;GA Candidate Neutral vote(ChaosNil).svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Good article reassessment&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	dga = {&lt;br /&gt;
		image = &amp;quot;Symbol unsupport vote.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Delisted good article&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	gan = {&lt;br /&gt;
		aliases = {&amp;quot;gac&amp;quot;},&lt;br /&gt;
		image = &amp;quot;GA candidate.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Good article nominee&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	ga2 = {&lt;br /&gt;
		image = &amp;quot;Symbol neutral vote.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Good article, 2nd opinion&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	gah = {&lt;br /&gt;
		image = &amp;quot;Symbol wait.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Good article on hold&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	fgan = {&lt;br /&gt;
		aliases = {&amp;quot;noga&amp;quot;, &amp;quot;gaf&amp;quot;, &amp;quot;gf&amp;quot;},&lt;br /&gt;
		image = &amp;quot;Symbol oppose vote.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Failed good article nominee&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	fp = {&lt;br /&gt;
		image = &amp;quot;Cscr-featured.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Featured picture&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	fpc = {&lt;br /&gt;
		aliases = {&amp;quot;fpn&amp;quot;},&lt;br /&gt;
		image = &amp;quot;Cscr-candidate.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Featured picture candidate&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	ffp = {&lt;br /&gt;
		image = &amp;quot;Cscr-former.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Former featured picture&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	vp = {&lt;br /&gt;
		image = &amp;quot;ENWP VP Logo.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Valued picture&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	vpc = {&lt;br /&gt;
		image = &amp;quot;Valued pics 1.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Valued picture candidate&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	fs = {&lt;br /&gt;
		image = &amp;quot;Cscr-featured.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Featured sound&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	ffs = {&lt;br /&gt;
		image = &amp;quot;Cscr-former.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Former featured sound&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	fsc = {&lt;br /&gt;
		image = &amp;quot;Cscr-candidate.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Featured sound candidate&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	fpo = {&lt;br /&gt;
		image = &amp;quot;Linecons big-star.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Before the featured portal process ceased in 2017, this had been designated as a featured portal.&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	fpor = {&lt;br /&gt;
		image = &amp;quot;Cscr-star piece.png&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Featured portal review&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	ffpo = {&lt;br /&gt;
		image = &amp;quot;Featured article star - cross.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Former featured portal&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	fpoc = {&lt;br /&gt;
		image = &amp;quot;Cscr-candidate.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Featured portal candidate&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	ft = {&lt;br /&gt;
		image = &amp;quot;Cscr-featuredtopic.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Featured topic&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	ftrc = {&lt;br /&gt;
		image = &amp;quot;Cscr-star piece.png&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Featured topic removal candidate&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	fft = {&lt;br /&gt;
		aliases = {&amp;quot;dft&amp;quot;},&lt;br /&gt;
		image = &amp;quot;DFT candidate_cluster.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Former featured topic&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	ftc = {&lt;br /&gt;
		aliases = {&amp;quot;ftn&amp;quot;},&lt;br /&gt;
		image = &amp;quot;FT candidate cluster.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Featured topic candidate&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	gt = {&lt;br /&gt;
		image = &amp;quot;Support cluster.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Good topic&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	gtrc = {&lt;br /&gt;
		image = &amp;quot;Symbol unsupport vote.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Good topic removal candidate&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	gtc = {&lt;br /&gt;
		aliases = {&amp;quot;gtn&amp;quot;},&lt;br /&gt;
		image = &amp;quot;GA candidate cluster.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Good topic candidate&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	bplus = {&lt;br /&gt;
		aliases = {&amp;quot;b+&amp;quot;},&lt;br /&gt;
		image = &amp;quot;Symbol bplus class.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Bplus-Class article&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	b = {&lt;br /&gt;
		image = &amp;quot;Symbol b class.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;B-Class article&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	br = {&lt;br /&gt;
		aliases = {&amp;quot;bcr&amp;quot;},&lt;br /&gt;
		image = &amp;quot;Bclass-checklist.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;B-Class review&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	c = {&lt;br /&gt;
		image = &amp;quot;Symbol c class.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;C-Class article&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	start = {&lt;br /&gt;
		image = &amp;quot;Symbol start class.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Start-Class article&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	stub = {&lt;br /&gt;
		image = &amp;quot;Symbol stub class.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Stub-Class article&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	list = {&lt;br /&gt;
		aliases = {&amp;quot;comparison&amp;quot;},&lt;br /&gt;
		image = &amp;quot;Symbol list class.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;List-Class article&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	no = {&lt;br /&gt;
		image = &amp;quot;Crystal button cancel.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Unknown-Class article&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	book = {&lt;br /&gt;
		image = &amp;quot;Symbol book class2.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Wikipedia book&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	category = {&lt;br /&gt;
		aliases = {&amp;quot;cat&amp;quot;, &amp;quot;categ&amp;quot;},&lt;br /&gt;
		image = &amp;quot;Symbol category class.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Category&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	disambiguation = {&lt;br /&gt;
		aliases = {&amp;quot;dab&amp;quot;, &amp;quot;disamb&amp;quot;, &amp;quot;disambig&amp;quot;},&lt;br /&gt;
		image = &amp;quot;Symbol dab class.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Disambiguation page&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	image = {&lt;br /&gt;
		aliases = {&amp;quot;file&amp;quot;},&lt;br /&gt;
		image = &amp;quot;Symbol file class.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;File&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	needed = {&lt;br /&gt;
		image = &amp;quot;Symbol needed class.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Needed article&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	outline = {&lt;br /&gt;
		image = &amp;quot;Global thinking.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Outline&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	portal = {&lt;br /&gt;
		image = &amp;quot;Symbol portal class.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Portal&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	project = {&lt;br /&gt;
		image = &amp;quot;Symbol project class.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Project page&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	redirect = {&lt;br /&gt;
		aliases = {&amp;quot;red&amp;quot;, &amp;quot;redir&amp;quot;},&lt;br /&gt;
		image = &amp;quot;Symbol redirect vote2.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Redirect&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	template = {&lt;br /&gt;
		aliases = {&amp;quot;temp&amp;quot;, &amp;quot;templ&amp;quot;},&lt;br /&gt;
		image = &amp;quot;Symbol template class.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Template&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	essay = {&lt;br /&gt;
		image = &amp;quot;Essay.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Essay&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	na = {&lt;br /&gt;
		image = &amp;quot;Symbol na class.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Non-article page&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	aa = {&lt;br /&gt;
		image = &amp;quot;Yes check.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Audited article of limited subject matter&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	da = {&lt;br /&gt;
		image = &amp;quot;Symbol oppose vote.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Demoted article&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	dyk = {&lt;br /&gt;
		image = &amp;quot;Symbol question.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Did You Know?&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	dyk2 = {&lt;br /&gt;
		image = &amp;quot;DYK questionmark icon.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Did You Know?&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	pr = {&lt;br /&gt;
		image = &amp;quot;Nuvola apps kedit.png&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Peer review&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	ppr = {&lt;br /&gt;
		image = &amp;quot;Nuvola apps kedit.png&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Portal peer review&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	q = {&lt;br /&gt;
		aliases = {&amp;quot;question&amp;quot;},&lt;br /&gt;
		image = &amp;quot;Symbol question.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Question&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	cleanup = {&lt;br /&gt;
		image = &amp;quot;Edit-clear.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Cleanup work&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	qi = {&lt;br /&gt;
		image = &amp;quot;Quality images logo.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Quality image on Wikimedia Commons&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	vi = {&lt;br /&gt;
		image = &amp;quot;Valued image seal.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Valued image on Wikimedia Commons&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	tfa = {&lt;br /&gt;
		image = &amp;quot;Wikipedia-logo.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Today&#039;s Featured Article&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	tfl = {&lt;br /&gt;
		image = &amp;quot;Wikipedia-logo.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Today&#039;s Featured List&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	itn = {&lt;br /&gt;
		image = &amp;quot;Globe current.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;In The News&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	otd = {&lt;br /&gt;
		image = &amp;quot;Nuvola apps date.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;On This Day&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	wikiproject = {&lt;br /&gt;
		image = &amp;quot;People icon.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;WikiProject&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	goce = {&lt;br /&gt;
		image = &amp;quot;Writing Magnifying.PNG&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Guild of Copy Editors&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	wikipedia = {&lt;br /&gt;
		image = &amp;quot;Wikipedia-logo.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Wikipedia page&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	commons = {&lt;br /&gt;
		image = &amp;quot;Commons-logo.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Commons page&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	wikiquote = {&lt;br /&gt;
		image = &amp;quot;Wikiquote-logo.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Wikiquote page&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	wikiversity = {&lt;br /&gt;
		image = &amp;quot;Wikiversity logo 2017.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Wikiversity page&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	wikibooks = {&lt;br /&gt;
		image = &amp;quot;Wikibooks-logo.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Wikibooks page&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	wikisource = {&lt;br /&gt;
		image = &amp;quot;Wikisource-logo.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Wikisource page&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	wiktionary = {&lt;br /&gt;
		image = &amp;quot;Wiktionary-logo.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Wiktionary page&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	wikinews = {&lt;br /&gt;
		image = &amp;quot;Wikinews-logo.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Wikinews page&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	wikispecies = {&lt;br /&gt;
		image = &amp;quot;Wikispecies-logo.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Wikispecies page&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	wikidata = {&lt;br /&gt;
		image = &amp;quot;Wikidata-logo.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Wikidata page&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	wikivoyage = {&lt;br /&gt;
		image = &amp;quot;Wikivoyage-logo.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Wikivoyage page&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	meta = {&lt;br /&gt;
		image = &amp;quot;Wikimedia Community Logo.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Meta-wiki page&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	four = {&lt;br /&gt;
		image = &amp;quot;Four Award.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Four Award&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	million = {&lt;br /&gt;
		image = &amp;quot;Million award logo.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Million Award&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
	module = {&lt;br /&gt;
		image = &amp;quot;Lua-logo-nolabel.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Module&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	vital = {&lt;br /&gt;
		image = &amp;quot;Círculos_Concéntricos.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Vital article&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	},&lt;br /&gt;
	potd  = {&lt;br /&gt;
		image = &amp;quot;Wikipedia-logo.svg&amp;quot;,&lt;br /&gt;
		tooltip = &amp;quot;Picture of the Day&amp;quot;,&lt;br /&gt;
		link = true,&lt;br /&gt;
	},&lt;br /&gt;
    _DEFAULT = {&lt;br /&gt;
		image = &amp;quot;Symbol question.svg&amp;quot;,&lt;br /&gt;
		link = false,&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- End icon data&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- Make aliases work the same as normal keys, and remove the &amp;quot;aliases&amp;quot; subtables.&lt;br /&gt;
local ret= {}&lt;br /&gt;
for code, iconData in pairs(data) do&lt;br /&gt;
	iconData.canonicalCode = code&lt;br /&gt;
	if iconData.aliases then&lt;br /&gt;
		for _, alias in ipairs(iconData.aliases) do&lt;br /&gt;
			ret[alias] = iconData&lt;br /&gt;
		end&lt;br /&gt;
		iconData.aliases = nil&lt;br /&gt;
	end&lt;br /&gt;
	ret[code] = iconData&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return ret&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Modul:Icon&amp;diff=1533</id>
		<title>Modul:Icon</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Modul:Icon&amp;diff=1533"/>
		<updated>2022-08-12T16:59:12Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module implements [[Template:Icon]].&lt;br /&gt;
&lt;br /&gt;
require(&amp;quot;Module:No globals&amp;quot;)&lt;br /&gt;
local yesNo = require(&amp;quot;Module:Yesno&amp;quot;)&lt;br /&gt;
local getArgs = require(&amp;quot;Module:Arguments&amp;quot;).getArgs&lt;br /&gt;
local getPlain = nil&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
-- Determine whether we&#039;re being called from a sandbox&lt;br /&gt;
local sandbox = mw.getCurrentFrame():getTitle():find(&#039;sandbox&#039;, 1, true) and &#039;/sandbox&#039; or &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
-- Implements [[Template:Icon]]&lt;br /&gt;
-- Returns the icon image corresponding to a string (like &#039;B&#039;)&lt;br /&gt;
function p._main(args, data)&lt;br /&gt;
	local data_module = &#039;Module:Icon/data&#039;..sandbox&lt;br /&gt;
	data = data or mw.loadData(data_module)&lt;br /&gt;
	local code = args.class or args[1]&lt;br /&gt;
	local iconData&lt;br /&gt;
	if code then&lt;br /&gt;
		code = code:match(&#039;^%s*(.-)%s*$&#039;):lower() -- trim whitespace and put in lower case&lt;br /&gt;
		iconData = data[code]&lt;br /&gt;
	end&lt;br /&gt;
	if not iconData then&lt;br /&gt;
		iconData = data._DEFAULT&lt;br /&gt;
	end&lt;br /&gt;
	return string.format(&lt;br /&gt;
		&#039;[[File:%s%s%s|%s|class=noviewer|alt=%s]]&#039;,&lt;br /&gt;
		iconData.image,&lt;br /&gt;
		iconData.tooltip and &#039;|&#039; .. iconData.tooltip or &#039;&#039;,&lt;br /&gt;
		iconData.link == false and &#039;|link=&#039; or &#039;&#039;,&lt;br /&gt;
		args.size or &#039;16x16px&#039;,&lt;br /&gt;
		iconData.alt or &#039;&#039;&lt;br /&gt;
	)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Implements [[Template:Icon link]], a superset of [[Template:Icon]]&lt;br /&gt;
-- Returns an icon, plus a suitably formatted wikilink&lt;br /&gt;
function p._link(args, data)&lt;br /&gt;
	args.size = args.size or args.iconsize&lt;br /&gt;
	local icon = p._main(args, data)&lt;br /&gt;
	-- If no link given in args[2], default back to [[Template:Icon]]&lt;br /&gt;
	if not args[2] then&lt;br /&gt;
		return icon&lt;br /&gt;
	end&lt;br /&gt;
	-- Strip wiki markup out of link&lt;br /&gt;
	getPlain = getPlain or require(&amp;quot;Module:Text&amp;quot;).Text().getPlain&lt;br /&gt;
	local link = getPlain(args[2])&lt;br /&gt;
	local display = args[3] or args[2]&lt;br /&gt;
	-- italicize display string, if requested&lt;br /&gt;
	if yesNo(args.i) or yesNo(args.italic) or yesNo(args.italics) then&lt;br /&gt;
		display = &#039;&amp;lt;i&amp;gt;&#039;..display..&#039;&amp;lt;/i&amp;gt;&#039;&lt;br /&gt;
	end&lt;br /&gt;
	-- if display is link, just use standard wlink&lt;br /&gt;
	if link == display then&lt;br /&gt;
		return icon..&#039;&amp;amp;nbsp;[[&#039;..link..&#039;]]&#039;&lt;br /&gt;
	end&lt;br /&gt;
	return icon..&#039;&amp;amp;nbsp;[[&#039;..link..&#039;|&#039;..display..&#039;]]&#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.main(frame)&lt;br /&gt;
	local args = getArgs(frame,{parentFirst=true})&lt;br /&gt;
	return p._main(args)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.link(frame)&lt;br /&gt;
	local args = getArgs(frame,{parentFirst=true})&lt;br /&gt;
	return p._link(args)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Modul:Citation/CS1/styles.css&amp;diff=1531</id>
		<title>Modul:Citation/CS1/styles.css</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Modul:Citation/CS1/styles.css&amp;diff=1531"/>
		<updated>2022-08-12T16:59:12Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Modul:Citation/CS1/Whitelist&amp;diff=1529</id>
		<title>Modul:Citation/CS1/Whitelist</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Modul:Citation/CS1/Whitelist&amp;diff=1529"/>
		<updated>2022-08-12T16:59:11Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--[[--------------------------&amp;lt; S U P P O R T E D   P A R A M E T E R S &amp;gt;--------------------------------------&lt;br /&gt;
&lt;br /&gt;
Because a steady-state signal conveys no useful information, whitelist.basic_arguments[] list items can have three values:&lt;br /&gt;
	true - these parameters are valid and supported parameters&lt;br /&gt;
	false - these parameters are deprecated but still supported&lt;br /&gt;
	tracked - these parameters are valid and supported parameters tracked in an eponymous properties category&lt;br /&gt;
	nil - these parameters are no longer supported. remove entirely&lt;br /&gt;
	&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local basic_arguments = {&lt;br /&gt;
	[&#039;accessdate&#039;] = true,&lt;br /&gt;
	[&#039;access-date&#039;] = true,&lt;br /&gt;
	[&#039;agency&#039;] = true,&lt;br /&gt;
	[&#039;archivedate&#039;] = true,&lt;br /&gt;
	[&#039;archive-date&#039;] = true,&lt;br /&gt;
	[&#039;archive-format&#039;] = true,&lt;br /&gt;
	[&#039;archiveurl&#039;] = true,&lt;br /&gt;
	[&#039;archive-url&#039;] = true,&lt;br /&gt;
	[&#039;article&#039;] = true,&lt;br /&gt;
	[&#039;article-format&#039;] = true,&lt;br /&gt;
	[&#039;article-url&#039;] = true,&lt;br /&gt;
	[&#039;article-url-access&#039;] = true,&lt;br /&gt;
	[&#039;arxiv&#039;] = true,															-- cite arxiv; here because allowed in cite ... as identifier&lt;br /&gt;
	[&#039;asin&#039;] = true,&lt;br /&gt;
	[&#039;ASIN&#039;] = true,&lt;br /&gt;
	[&#039;asin-tld&#039;] = true,&lt;br /&gt;
	[&#039;at&#039;] = true,&lt;br /&gt;
	[&#039;author&#039;] = true,&lt;br /&gt;
	[&#039;author-first&#039;] = true,&lt;br /&gt;
	[&#039;author-given&#039;] = true,&lt;br /&gt;
	[&#039;author-last&#039;] = true,&lt;br /&gt;
	[&#039;author-surname&#039;] = true,&lt;br /&gt;
	[&#039;authorlink&#039;] = true,&lt;br /&gt;
	[&#039;author-link&#039;] = true,&lt;br /&gt;
	[&#039;author-mask&#039;] = true,&lt;br /&gt;
	[&#039;authors&#039;] = true,&lt;br /&gt;
	[&#039;bibcode&#039;] = true,&lt;br /&gt;
	[&#039;bibcode-access&#039;] = true,&lt;br /&gt;
	[&#039;biorxiv&#039;] = true,															-- cite biorxiv; here because allowed in cite ... as identifier&lt;br /&gt;
	[&#039;chapter&#039;] = true,&lt;br /&gt;
	[&#039;chapter-format&#039;] = true,&lt;br /&gt;
	[&#039;chapter-url&#039;] = true,&lt;br /&gt;
	[&#039;chapter-url-access&#039;] = true,&lt;br /&gt;
	[&#039;citeseerx&#039;] = true,														-- cite citeseerx; here because allowed in cite ... as identifier&lt;br /&gt;
	[&#039;collaboration&#039;] = true,&lt;br /&gt;
	[&#039;contribution&#039;] = true,&lt;br /&gt;
	[&#039;contribution-format&#039;] = true,&lt;br /&gt;
	[&#039;contribution-url&#039;] = true,&lt;br /&gt;
	[&#039;contribution-url-access&#039;] = true,&lt;br /&gt;
	[&#039;contributor&#039;] = true,&lt;br /&gt;
	[&#039;contributor-first&#039;] = true,&lt;br /&gt;
	[&#039;contributor-given&#039;] = true,&lt;br /&gt;
	[&#039;contributor-last&#039;] = true,&lt;br /&gt;
	[&#039;contributor-surname&#039;] = true,&lt;br /&gt;
	[&#039;contributor-link&#039;] = true,&lt;br /&gt;
	[&#039;contributor-mask&#039;] = true,&lt;br /&gt;
	[&#039;date&#039;] = true,&lt;br /&gt;
	[&#039;department&#039;] = true,&lt;br /&gt;
	[&#039;df&#039;] = true,&lt;br /&gt;
	[&#039;dictionary&#039;] = true,&lt;br /&gt;
	[&#039;display-authors&#039;] = true,&lt;br /&gt;
	[&#039;display-contributors&#039;] = true,&lt;br /&gt;
	[&#039;display-editors&#039;] = true,&lt;br /&gt;
	[&#039;display-interviewers&#039;] = true,&lt;br /&gt;
	[&#039;display-subjects&#039;] = true,&lt;br /&gt;
	[&#039;display-translators&#039;] = true,&lt;br /&gt;
	[&#039;doi&#039;] = true,&lt;br /&gt;
	[&#039;DOI&#039;] = true,&lt;br /&gt;
	[&#039;doi-access&#039;] = true,&lt;br /&gt;
	[&#039;doi-broken-date&#039;] = true,&lt;br /&gt;
	[&#039;edition&#039;] = true,&lt;br /&gt;
	[&#039;editor&#039;] = true,&lt;br /&gt;
	[&#039;editor-first&#039;] = true,&lt;br /&gt;
	[&#039;editor-given&#039;] = true,&lt;br /&gt;
	[&#039;editor-last&#039;] = true,&lt;br /&gt;
	[&#039;editor-surname&#039;] = true,&lt;br /&gt;
	[&#039;editor-link&#039;] = true,&lt;br /&gt;
	[&#039;editor-mask&#039;] = true,&lt;br /&gt;
	[&#039;eissn&#039;] = true,&lt;br /&gt;
	[&#039;EISSN&#039;] = true,&lt;br /&gt;
	[&#039;encyclopaedia&#039;] = true,&lt;br /&gt;
	[&#039;encyclopedia&#039;] = true,&lt;br /&gt;
	[&#039;entry&#039;] = true,&lt;br /&gt;
	[&#039;entry-format&#039;] = true,&lt;br /&gt;
	[&#039;entry-url&#039;] = true,&lt;br /&gt;
	[&#039;entry-url-access&#039;] = true,&lt;br /&gt;
	[&#039;eprint&#039;] = true,															-- cite arxiv; here because allowed in cite ... as identifier&lt;br /&gt;
	[&#039;first&#039;] = true,&lt;br /&gt;
	[&#039;format&#039;] = true,&lt;br /&gt;
	[&#039;given&#039;] = true,&lt;br /&gt;
	[&#039;hdl&#039;] = true,&lt;br /&gt;
	[&#039;HDL&#039;] = true,&lt;br /&gt;
	[&#039;hdl-access&#039;] = true,&lt;br /&gt;
	[&#039;host&#039;] = true,															-- unique to certain templates?&lt;br /&gt;
	[&#039;id&#039;] = true,&lt;br /&gt;
	[&#039;ID&#039;] = true,&lt;br /&gt;
	[&#039;institution&#039;] = true,														-- constrain to cite thesis?&lt;br /&gt;
	[&#039;interviewer&#039;] = true,&lt;br /&gt;
	[&#039;interviewer-first&#039;] = true,&lt;br /&gt;
	[&#039;interviewer-given&#039;] = true,&lt;br /&gt;
	[&#039;interviewer-last&#039;] = true,&lt;br /&gt;
	[&#039;interviewer-surname&#039;] = true,&lt;br /&gt;
	[&#039;interviewer-link&#039;] = true,&lt;br /&gt;
	[&#039;interviewer-mask&#039;] = true,&lt;br /&gt;
	[&#039;isbn&#039;] = true,&lt;br /&gt;
	[&#039;ISBN&#039;] = true,&lt;br /&gt;
	[&#039;ismn&#039;] = true,&lt;br /&gt;
	[&#039;ISMN&#039;] = true,&lt;br /&gt;
	[&#039;issn&#039;] = true,&lt;br /&gt;
	[&#039;ISSN&#039;] = true,&lt;br /&gt;
	[&#039;issue&#039;] = true,&lt;br /&gt;
	[&#039;jfm&#039;] = true,&lt;br /&gt;
	[&#039;JFM&#039;] = true,&lt;br /&gt;
	[&#039;journal&#039;] = true,&lt;br /&gt;
	[&#039;jstor&#039;] = true,&lt;br /&gt;
	[&#039;JSTOR&#039;] = true,&lt;br /&gt;
	[&#039;jstor-access&#039;] = true,&lt;br /&gt;
	[&#039;lang&#039;] = true,&lt;br /&gt;
	[&#039;language&#039;] = true,&lt;br /&gt;
	[&#039;last&#039;] = true,&lt;br /&gt;
	[&#039;lay-date&#039;] = false,&lt;br /&gt;
	[&#039;lay-format&#039;] = false,&lt;br /&gt;
	[&#039;lay-source&#039;] = false,&lt;br /&gt;
	[&#039;lay-url&#039;] = false,&lt;br /&gt;
	[&#039;lccn&#039;] = true,&lt;br /&gt;
	[&#039;LCCN&#039;] = true,&lt;br /&gt;
	[&#039;location&#039;] = true,&lt;br /&gt;
	[&#039;magazine&#039;] = true,&lt;br /&gt;
	[&#039;medium&#039;] = true,&lt;br /&gt;
	[&#039;minutes&#039;] = true,															-- constrain to cite AV media and podcast?&lt;br /&gt;
	[&#039;mode&#039;] = true,&lt;br /&gt;
	[&#039;mr&#039;] = true,&lt;br /&gt;
	[&#039;MR&#039;] = true,&lt;br /&gt;
	[&#039;name-list-style&#039;] = true,&lt;br /&gt;
	[&#039;newspaper&#039;] = true,&lt;br /&gt;
	[&#039;no-pp&#039;] = true,&lt;br /&gt;
	[&#039;no-tracking&#039;] = true,&lt;br /&gt;
	[&#039;number&#039;] = true,&lt;br /&gt;
	[&#039;oclc&#039;] = true,&lt;br /&gt;
	[&#039;OCLC&#039;] = true,&lt;br /&gt;
	[&#039;ol&#039;] = true,&lt;br /&gt;
	[&#039;OL&#039;] = true,&lt;br /&gt;
	[&#039;ol-access&#039;] = true,&lt;br /&gt;
	[&#039;orig-date&#039;] = true,&lt;br /&gt;
	[&#039;origyear&#039;] = true,&lt;br /&gt;
	[&#039;orig-year&#039;] = true,&lt;br /&gt;
	[&#039;osti&#039;] = true,&lt;br /&gt;
	[&#039;OSTI&#039;] = true,&lt;br /&gt;
	[&#039;osti-access&#039;] = true,&lt;br /&gt;
	[&#039;others&#039;] = true,&lt;br /&gt;
	[&#039;p&#039;] = true,&lt;br /&gt;
	[&#039;page&#039;] = true,&lt;br /&gt;
	[&#039;pages&#039;] = true,&lt;br /&gt;
	[&#039;people&#039;] = true,&lt;br /&gt;
	[&#039;periodical&#039;] = true,&lt;br /&gt;
	[&#039;place&#039;] = true,&lt;br /&gt;
	[&#039;pmc&#039;] = true,&lt;br /&gt;
	[&#039;PMC&#039;] = true,&lt;br /&gt;
	[&#039;pmc-embargo-date&#039;] = true,&lt;br /&gt;
	[&#039;pmid&#039;] = true,&lt;br /&gt;
	[&#039;PMID&#039;] = true,&lt;br /&gt;
	[&#039;postscript&#039;] = true,&lt;br /&gt;
	[&#039;pp&#039;] = true,&lt;br /&gt;
	[&#039;publication-date&#039;] = true,&lt;br /&gt;
	[&#039;publication-place&#039;] = true,&lt;br /&gt;
	[&#039;publisher&#039;] = true,&lt;br /&gt;
	[&#039;quotation&#039;] = true,&lt;br /&gt;
	[&#039;quote&#039;] = true,&lt;br /&gt;
	[&#039;quote-page&#039;] = true,&lt;br /&gt;
	[&#039;quote-pages&#039;] = true,&lt;br /&gt;
	[&#039;ref&#039;] = true,&lt;br /&gt;
	[&#039;rfc&#039;] = true,&lt;br /&gt;
	[&#039;RFC&#039;] = true,&lt;br /&gt;
	[&#039;sbn&#039;] = true,&lt;br /&gt;
	[&#039;SBN&#039;] = true,&lt;br /&gt;
	[&#039;scale&#039;] = true,&lt;br /&gt;
	[&#039;script-article&#039;] = true,&lt;br /&gt;
	[&#039;script-chapter&#039;] = true,&lt;br /&gt;
	[&#039;script-contribution&#039;] = true,&lt;br /&gt;
	[&#039;script-entry&#039;] = true,&lt;br /&gt;
	[&#039;script-journal&#039;] = true,&lt;br /&gt;
	[&#039;script-magazine&#039;] = true,&lt;br /&gt;
	[&#039;script-newspaper&#039;] = true,&lt;br /&gt;
	[&#039;script-periodical&#039;] = true,&lt;br /&gt;
	[&#039;script-quote&#039;] = true,&lt;br /&gt;
	[&#039;script-section&#039;] = true,&lt;br /&gt;
	[&#039;script-title&#039;] = true,&lt;br /&gt;
	[&#039;script-website&#039;] = true,&lt;br /&gt;
	[&#039;script-work&#039;] = true,&lt;br /&gt;
	[&#039;section&#039;] = true,&lt;br /&gt;
	[&#039;section-format&#039;] = true,&lt;br /&gt;
	[&#039;section-url&#039;] = true,&lt;br /&gt;
	[&#039;section-url-access&#039;] = true,&lt;br /&gt;
	[&#039;series&#039;] = true,&lt;br /&gt;
	[&#039;ssrn&#039;] = true,															-- cite ssrn; these three here because allowed in cite ... as identifier&lt;br /&gt;
	[&#039;SSRN&#039;] = true,&lt;br /&gt;
	[&#039;ssrn-access&#039;] = true,&lt;br /&gt;
	[&#039;subject&#039;] = true,&lt;br /&gt;
	[&#039;subject-link&#039;] = true,&lt;br /&gt;
	[&#039;subject-mask&#039;] = true,&lt;br /&gt;
	[&#039;surname&#039;] = true,&lt;br /&gt;
	[&#039;s2cid&#039;] = true,&lt;br /&gt;
	[&#039;S2CID&#039;] = true,&lt;br /&gt;
	[&#039;s2cid-access&#039;] = true,&lt;br /&gt;
	[&#039;template-doc-demo&#039;] = true,&lt;br /&gt;
	[&#039;time&#039;] = true,															-- constrain to cite av media and podcast?&lt;br /&gt;
	[&#039;time-caption&#039;] = true,													-- constrain to cite av media and podcast?&lt;br /&gt;
	[&#039;title&#039;] = true,&lt;br /&gt;
	[&#039;title-link&#039;] = true,&lt;br /&gt;
	[&#039;translator&#039;] = true,&lt;br /&gt;
	[&#039;translator-first&#039;] = true,&lt;br /&gt;
	[&#039;translator-given&#039;] = true,&lt;br /&gt;
	[&#039;translator-last&#039;] = true,	&lt;br /&gt;
	[&#039;translator-surname&#039;] = true,&lt;br /&gt;
	[&#039;translator-link&#039;] = true,&lt;br /&gt;
	[&#039;translator-mask&#039;] = true,&lt;br /&gt;
	[&#039;trans-article&#039;] = true,&lt;br /&gt;
	[&#039;trans-chapter&#039;] = true,&lt;br /&gt;
	[&#039;trans-contribution&#039;] = true,&lt;br /&gt;
	[&#039;trans-entry&#039;] = true,&lt;br /&gt;
	[&#039;trans-journal&#039;] = true,&lt;br /&gt;
	[&#039;trans-magazine&#039;] = true,&lt;br /&gt;
	[&#039;trans-newspaper&#039;] = true,&lt;br /&gt;
	[&#039;trans-periodical&#039;] = true,&lt;br /&gt;
	[&#039;trans-quote&#039;] = true,&lt;br /&gt;
	[&#039;trans-section&#039;] = true,&lt;br /&gt;
	[&#039;trans-title&#039;] = true,&lt;br /&gt;
	[&#039;trans-website&#039;] = true,&lt;br /&gt;
	[&#039;trans-work&#039;] = true,&lt;br /&gt;
	[&#039;type&#039;] = true,&lt;br /&gt;
	[&#039;url&#039;] = true,&lt;br /&gt;
	[&#039;URL&#039;] = true,&lt;br /&gt;
	[&#039;url-access&#039;] = true,&lt;br /&gt;
	[&#039;url-status&#039;] = true,&lt;br /&gt;
	[&#039;vauthors&#039;] = true,&lt;br /&gt;
	[&#039;veditors&#039;] = true,&lt;br /&gt;
	[&#039;version&#039;] = true,&lt;br /&gt;
	[&#039;via&#039;] = true,&lt;br /&gt;
	[&#039;volume&#039;] = true,&lt;br /&gt;
	[&#039;website&#039;] = true,&lt;br /&gt;
	[&#039;work&#039;] = true,&lt;br /&gt;
	[&#039;year&#039;] = true,&lt;br /&gt;
	[&#039;zbl&#039;] = true,&lt;br /&gt;
	[&#039;ZBL&#039;] = true,&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
local numbered_arguments = {&lt;br /&gt;
	[&#039;author#&#039;] = true,&lt;br /&gt;
	[&#039;author-first#&#039;] = true,&lt;br /&gt;
	[&#039;author#-first&#039;] = true,&lt;br /&gt;
	[&#039;author-given#&#039;] = true,&lt;br /&gt;
	[&#039;author#-given&#039;] = true,&lt;br /&gt;
	[&#039;author-last#&#039;] = true,&lt;br /&gt;
	[&#039;author#-last&#039;] = true,&lt;br /&gt;
	[&#039;author-surname#&#039;] = true,&lt;br /&gt;
	[&#039;author#-surname&#039;] = true,&lt;br /&gt;
	[&#039;author-link#&#039;] = true,&lt;br /&gt;
	[&#039;author#-link&#039;] = true,&lt;br /&gt;
	[&#039;authorlink#&#039;] = true,&lt;br /&gt;
	[&#039;author#link&#039;] = true,&lt;br /&gt;
	[&#039;author-mask#&#039;] = true,&lt;br /&gt;
	[&#039;author#-mask&#039;] = true,&lt;br /&gt;
	[&#039;contributor#&#039;] = true,&lt;br /&gt;
	[&#039;contributor-first#&#039;] = true,&lt;br /&gt;
	[&#039;contributor#-first&#039;] = true,&lt;br /&gt;
	[&#039;contributor-given#&#039;] = true,&lt;br /&gt;
	[&#039;contributor#-given&#039;] = true,&lt;br /&gt;
	[&#039;contributor-last#&#039;] = true,&lt;br /&gt;
	[&#039;contributor#-last&#039;] = true,&lt;br /&gt;
	[&#039;contributor-surname#&#039;] = true,&lt;br /&gt;
	[&#039;contributor#-surname&#039;] = true,&lt;br /&gt;
	[&#039;contributor-link#&#039;] = true,&lt;br /&gt;
	[&#039;contributor#-link&#039;] = true,&lt;br /&gt;
	[&#039;contributor-mask#&#039;] = true,&lt;br /&gt;
	[&#039;contributor#-mask&#039;] = true,&lt;br /&gt;
	[&#039;editor#&#039;] = true,&lt;br /&gt;
	[&#039;editor-first#&#039;] = true,&lt;br /&gt;
	[&#039;editor#-first&#039;] = true,&lt;br /&gt;
	[&#039;editor-given#&#039;] = true,&lt;br /&gt;
	[&#039;editor#-given&#039;] = true,&lt;br /&gt;
	[&#039;editor-last#&#039;] = true,&lt;br /&gt;
	[&#039;editor#-last&#039;] = true,&lt;br /&gt;
	[&#039;editor-surname#&#039;] = true,&lt;br /&gt;
	[&#039;editor#-surname&#039;] = true,&lt;br /&gt;
	[&#039;editor-link#&#039;] = true,&lt;br /&gt;
	[&#039;editor#-link&#039;] = true,&lt;br /&gt;
	[&#039;editor-mask#&#039;] = true,&lt;br /&gt;
	[&#039;editor#-mask&#039;] = true,&lt;br /&gt;
	[&#039;first#&#039;] = true,&lt;br /&gt;
	[&#039;given#&#039;] = true,&lt;br /&gt;
	[&#039;host#&#039;] = true,&lt;br /&gt;
	[&#039;interviewer#&#039;] = true,&lt;br /&gt;
	[&#039;interviewer-first#&#039;] = true,&lt;br /&gt;
	[&#039;interviewer#-first&#039;] = true,&lt;br /&gt;
	[&#039;interviewer-given#&#039;] = true,&lt;br /&gt;
	[&#039;interviewer#-given&#039;] = true,&lt;br /&gt;
	[&#039;interviewer-last#&#039;] = true,&lt;br /&gt;
	[&#039;interviewer#-last&#039;] = true,&lt;br /&gt;
	[&#039;interviewer-surname#&#039;] = true,&lt;br /&gt;
	[&#039;interviewer#-surname&#039;] = true,&lt;br /&gt;
	[&#039;interviewer-link#&#039;] = true,&lt;br /&gt;
	[&#039;interviewer#-link&#039;] = true,&lt;br /&gt;
	[&#039;interviewer-mask#&#039;] = true,&lt;br /&gt;
	[&#039;interviewer#-mask&#039;] = true,&lt;br /&gt;
	[&#039;last#&#039;] = true,&lt;br /&gt;
	[&#039;subject#&#039;] = true,&lt;br /&gt;
	[&#039;subject-link#&#039;] = true,&lt;br /&gt;
	[&#039;subject#-link&#039;] = true,&lt;br /&gt;
	[&#039;subject-mask#&#039;] = true,&lt;br /&gt;
	[&#039;subject#-mask&#039;] = true,&lt;br /&gt;
	[&#039;surname#&#039;] = true,&lt;br /&gt;
	[&#039;translator#&#039;] = true,&lt;br /&gt;
	[&#039;translator-first#&#039;] = true,&lt;br /&gt;
	[&#039;translator#-first&#039;] = true,&lt;br /&gt;
	[&#039;translator-given#&#039;] = true,&lt;br /&gt;
	[&#039;translator#-given&#039;] = true,&lt;br /&gt;
	[&#039;translator-last#&#039;] = true,&lt;br /&gt;
	[&#039;translator#-last&#039;] = true,&lt;br /&gt;
	[&#039;translator-surname#&#039;] = true,&lt;br /&gt;
	[&#039;translator#-surname&#039;] = true,&lt;br /&gt;
	[&#039;translator-link#&#039;] = true,&lt;br /&gt;
	[&#039;translator#-link&#039;] = true,&lt;br /&gt;
	[&#039;translator-mask#&#039;] = true,&lt;br /&gt;
	[&#039;translator#-mask&#039;] = true,&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; P R E P R I N T   S U P P O R T E D   P A R A M E T E R S &amp;gt;--------------------&lt;br /&gt;
&lt;br /&gt;
Cite arXiv, cite biorxiv, cite citeseerx, and cite ssrn are preprint templates that use the limited set of parameters&lt;br /&gt;
defined in the limited_basic_arguments and limited_numbered_arguments tables.  Those lists are supplemented with a&lt;br /&gt;
template-specific list of parameters that are required by the particular template and may be exclusive to one of the&lt;br /&gt;
preprint templates.  Some of these parameters may also be available to the general cs1|2 templates.&lt;br /&gt;
&lt;br /&gt;
Same conventions for true/false/tracked/nil as above.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local preprint_arguments = {&lt;br /&gt;
	arxiv = {&lt;br /&gt;
		[&#039;arxiv&#039;] = true,														-- cite arxiv and arxiv identifiers&lt;br /&gt;
		[&#039;class&#039;] = true,&lt;br /&gt;
		[&#039;eprint&#039;] = true,														-- cite arxiv and arxiv identifiers&lt;br /&gt;
		},&lt;br /&gt;
	biorxiv = {&lt;br /&gt;
		[&#039;biorxiv&#039;] = true,&lt;br /&gt;
		},&lt;br /&gt;
	citeseerx = {&lt;br /&gt;
		[&#039;citeseerx&#039;] = true,&lt;br /&gt;
		},&lt;br /&gt;
	ssrn = {&lt;br /&gt;
		[&#039;ssrn&#039;] = true,&lt;br /&gt;
		[&#039;SSRN&#039;] = true,&lt;br /&gt;
		[&#039;ssrn-access&#039;] = true,&lt;br /&gt;
		},&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; L I M I T E D   S U P P O R T E D   P A R A M E T E R S &amp;gt;----------------------&lt;br /&gt;
&lt;br /&gt;
cite arxiv, cite biorxiv, cite citeseerx, and cite ssrn templates are preprint templates so are allowed only a&lt;br /&gt;
limited subset of parameters allowed to all other cs1|2 templates.  The limited subset is defined here.&lt;br /&gt;
&lt;br /&gt;
Same conventions for true/false/tracked/nil as above.&lt;br /&gt;
	&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local limited_basic_arguments = {&lt;br /&gt;
	[&#039;at&#039;] = true,&lt;br /&gt;
	[&#039;author&#039;] = true,&lt;br /&gt;
	[&#039;author-first&#039;] = true,&lt;br /&gt;
	[&#039;author-given&#039;] = true,&lt;br /&gt;
	[&#039;author-last&#039;] = true,&lt;br /&gt;
	[&#039;author-surname&#039;] = true,&lt;br /&gt;
	[&#039;author-link&#039;] = true,&lt;br /&gt;
	[&#039;authorlink&#039;] = true,&lt;br /&gt;
	[&#039;author-mask&#039;] = true,&lt;br /&gt;
	[&#039;authors&#039;] = true,&lt;br /&gt;
	[&#039;collaboration&#039;] = true,&lt;br /&gt;
	[&#039;date&#039;] = true,&lt;br /&gt;
	[&#039;df&#039;] = true,&lt;br /&gt;
	[&#039;display-authors&#039;] = true,&lt;br /&gt;
	[&#039;first&#039;] = true,&lt;br /&gt;
	[&#039;given&#039;] = true,&lt;br /&gt;
	[&#039;language&#039;] = true,&lt;br /&gt;
	[&#039;last&#039;] = true,&lt;br /&gt;
	[&#039;mode&#039;] = true,&lt;br /&gt;
	[&#039;name-list-style&#039;] = true,&lt;br /&gt;
	[&#039;no-tracking&#039;] = true,&lt;br /&gt;
	[&#039;p&#039;] = true,&lt;br /&gt;
	[&#039;page&#039;] = true,&lt;br /&gt;
	[&#039;pages&#039;] = true,&lt;br /&gt;
	[&#039;postscript&#039;] = true,&lt;br /&gt;
	[&#039;pp&#039;] = true,&lt;br /&gt;
	[&#039;quotation&#039;] = true,&lt;br /&gt;
	[&#039;quote&#039;] = true,&lt;br /&gt;
	[&#039;ref&#039;] = true,&lt;br /&gt;
	[&#039;surname&#039;] = true,&lt;br /&gt;
	[&#039;template-doc-demo&#039;] = true,&lt;br /&gt;
	[&#039;title&#039;] = true,&lt;br /&gt;
	[&#039;trans-title&#039;] = true,&lt;br /&gt;
	[&#039;vauthors&#039;] = true,&lt;br /&gt;
	[&#039;year&#039;] = true,&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
local limited_numbered_arguments = {&lt;br /&gt;
	[&#039;author#&#039;] = true,&lt;br /&gt;
	[&#039;author-first#&#039;] = true,&lt;br /&gt;
	[&#039;author#-first&#039;] = true,&lt;br /&gt;
	[&#039;author-given#&#039;] = true,&lt;br /&gt;
	[&#039;author#-given&#039;] = true,&lt;br /&gt;
	[&#039;author-last#&#039;] = true,&lt;br /&gt;
	[&#039;author#-last&#039;] = true,&lt;br /&gt;
	[&#039;author-surname#&#039;] = true,&lt;br /&gt;
	[&#039;author#-surname&#039;] = true,&lt;br /&gt;
	[&#039;author-link#&#039;] = true,&lt;br /&gt;
	[&#039;author#-link&#039;] = true,&lt;br /&gt;
	[&#039;authorlink#&#039;] = true,&lt;br /&gt;
	[&#039;author#link&#039;] = true,&lt;br /&gt;
	[&#039;author-mask#&#039;] = true,&lt;br /&gt;
	[&#039;author#-mask&#039;] = true,&lt;br /&gt;
	[&#039;first#&#039;] = true,&lt;br /&gt;
	[&#039;given#&#039;] = true,&lt;br /&gt;
	[&#039;last#&#039;] = true,&lt;br /&gt;
	[&#039;surname#&#039;] = true,&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; U N I Q U E _ A R G U M E N T S &amp;gt;----------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Some templates have unique parameters.  Those templates and their unique parameters are listed here. Keys in this&lt;br /&gt;
table are the template&#039;s CitationClass parameter value&lt;br /&gt;
&lt;br /&gt;
Same conventions for true/false/tracked/nil as above.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local unique_arguments = {&lt;br /&gt;
	[&#039;audio-visual&#039;] = {&lt;br /&gt;
		[&#039;transcript&#039;] = true,&lt;br /&gt;
		[&#039;transcript-format&#039;] = true,&lt;br /&gt;
		[&#039;transcript-url&#039;] = true,&lt;br /&gt;
		},&lt;br /&gt;
	conference = {&lt;br /&gt;
		[&#039;book-title&#039;] = true,&lt;br /&gt;
		[&#039;conference&#039;] = true,&lt;br /&gt;
		[&#039;conference-format&#039;] = true,&lt;br /&gt;
		[&#039;conference-url&#039;] = true,&lt;br /&gt;
		[&#039;event&#039;] = true,&lt;br /&gt;
		},&lt;br /&gt;
	episode = {&lt;br /&gt;
		[&#039;airdate&#039;] = true,&lt;br /&gt;
		[&#039;air-date&#039;] = true,&lt;br /&gt;
		[&#039;credits&#039;] = true,&lt;br /&gt;
		[&#039;episode-link&#039;] = true,												-- alias of |title-link=&lt;br /&gt;
		[&#039;network&#039;] = true,&lt;br /&gt;
		[&#039;season&#039;] = true,&lt;br /&gt;
		[&#039;series-link&#039;] = true,&lt;br /&gt;
		[&#039;series-no&#039;] = true,&lt;br /&gt;
		[&#039;series-number&#039;] = true,&lt;br /&gt;
		[&#039;station&#039;] = true,&lt;br /&gt;
		[&#039;transcript&#039;] = true,&lt;br /&gt;
		[&#039;transcript-format&#039;] = true,&lt;br /&gt;
		[&#039;transcripturl&#039;] = false,&lt;br /&gt;
		[&#039;transcript-url&#039;] = true,&lt;br /&gt;
		},&lt;br /&gt;
	mailinglist = {&lt;br /&gt;
		[&#039;mailing-list&#039;] = true,&lt;br /&gt;
		},&lt;br /&gt;
	map = {&lt;br /&gt;
		[&#039;cartography&#039;] = true,&lt;br /&gt;
		[&#039;inset&#039;] = true,&lt;br /&gt;
		[&#039;map&#039;] = true,&lt;br /&gt;
		[&#039;map-format&#039;] = true,&lt;br /&gt;
		[&#039;map-url&#039;] = true,&lt;br /&gt;
		[&#039;map-url-access&#039;] = true,&lt;br /&gt;
		[&#039;script-map&#039;] = true,&lt;br /&gt;
		[&#039;sections&#039;] = true,&lt;br /&gt;
		[&#039;sheet&#039;] = true,&lt;br /&gt;
		[&#039;sheets&#039;] = true,&lt;br /&gt;
		[&#039;trans-map&#039;] = true,&lt;br /&gt;
		},&lt;br /&gt;
	newsgroup = {&lt;br /&gt;
		[&#039;message-id&#039;] = true,&lt;br /&gt;
		[&#039;newsgroup&#039;] = true,&lt;br /&gt;
		},&lt;br /&gt;
	report = {&lt;br /&gt;
		[&#039;docket&#039;] = true,&lt;br /&gt;
		},&lt;br /&gt;
	serial = {&lt;br /&gt;
		[&#039;airdate&#039;] = true,&lt;br /&gt;
		[&#039;air-date&#039;] = true,&lt;br /&gt;
		[&#039;credits&#039;] = true,&lt;br /&gt;
		[&#039;episode&#039;] = true,														-- cite serial only TODO: make available to cite episode?&lt;br /&gt;
		[&#039;episode-link&#039;] = true,												-- alias of |title-link=&lt;br /&gt;
		[&#039;network&#039;] = true,&lt;br /&gt;
		[&#039;series-link&#039;] = true,&lt;br /&gt;
		[&#039;station&#039;] = true,&lt;br /&gt;
		},&lt;br /&gt;
	speech = {&lt;br /&gt;
		[&#039;conference&#039;] = true,&lt;br /&gt;
		[&#039;conference-format&#039;] = true,&lt;br /&gt;
		[&#039;conference-url&#039;] = true,&lt;br /&gt;
		[&#039;event&#039;] = true,&lt;br /&gt;
		},&lt;br /&gt;
	thesis = {&lt;br /&gt;
		[&#039;degree&#039;] = true,&lt;br /&gt;
		[&#039;docket&#039;] = true,&lt;br /&gt;
		},&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; T E M P L A T E _ L I S T _ G E T &amp;gt;--------------------------------------------&lt;br /&gt;
&lt;br /&gt;
gets a list of the templates from table t&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function template_list_get (t)&lt;br /&gt;
	local out = {};																-- a table for output&lt;br /&gt;
	for k, _ in pairs (t) do													-- spin through the table and collect the keys&lt;br /&gt;
		table.insert (out, k)													-- add each key to the output table&lt;br /&gt;
	end&lt;br /&gt;
	return out;																	-- and done&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; E X P O R T E D   T A B L E S &amp;gt;------------------------------------------------&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
return {&lt;br /&gt;
	basic_arguments = basic_arguments,&lt;br /&gt;
	numbered_arguments = numbered_arguments,&lt;br /&gt;
	limited_basic_arguments = limited_basic_arguments,&lt;br /&gt;
	limited_numbered_arguments = limited_numbered_arguments,&lt;br /&gt;
&lt;br /&gt;
	preprint_arguments = preprint_arguments,&lt;br /&gt;
	preprint_template_list = template_list_get (preprint_arguments),			-- make a template list from preprint_arguments{} table&lt;br /&gt;
	unique_arguments = unique_arguments,&lt;br /&gt;
	unique_param_template_list = template_list_get (unique_arguments),			-- make a template list from unique_arguments{} table&lt;br /&gt;
	};&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Modul:Citation/CS1/Utilities&amp;diff=1527</id>
		<title>Modul:Citation/CS1/Utilities</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Modul:Citation/CS1/Utilities&amp;diff=1527"/>
		<updated>2022-08-12T16:59:11Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;local z = {&lt;br /&gt;
	error_cats_t = {};															-- for categorizing citations that contain errors&lt;br /&gt;
	error_ids_t = {};															-- list of error identifiers; used to prevent duplication of certain errors; local to this module&lt;br /&gt;
	error_msgs_t = {};															-- sequence table of error messages&lt;br /&gt;
	maint_cats_t = {};															-- for categorizing citations that aren&#039;t erroneous per se, but could use a little work&lt;br /&gt;
	prop_cats_t = {};															-- for categorizing citations based on certain properties, language of source for instance&lt;br /&gt;
	prop_keys_t = {};															-- for adding classes to the citation&#039;s &amp;lt;cite&amp;gt; tag&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; F O R W A R D   D E C L A R A T I O N S &amp;gt;--------------------------------------&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local cfg;																		-- table of tables imported from selected Module:Citation/CS1/Configuration&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; I S _ S E T &amp;gt;------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Returns true if argument is set; false otherwise. Argument is &#039;set&#039; when it exists (not nil) or when it is not an empty string.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function is_set (var)&lt;br /&gt;
	return not (var == nil or var == &#039;&#039;);&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; I N _ A R R A Y &amp;gt;--------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Whether needle is in haystack&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function in_array (needle, haystack)&lt;br /&gt;
	if needle == nil then&lt;br /&gt;
		return false;&lt;br /&gt;
	end&lt;br /&gt;
	for n, v in ipairs (haystack) do&lt;br /&gt;
		if v == needle then&lt;br /&gt;
			return n;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return false;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; H A S _ A C C E P T _ A S _ W R I T T E N &amp;gt;------------------------------------&lt;br /&gt;
&lt;br /&gt;
When &amp;lt;str&amp;gt; is wholly wrapped in accept-as-written markup, return &amp;lt;str&amp;gt; without markup and true; return &amp;lt;str&amp;gt; and false else&lt;br /&gt;
&lt;br /&gt;
with allow_empty = false, &amp;lt;str&amp;gt; must have at least one character inside the markup&lt;br /&gt;
with allow_empty = true, &amp;lt;str&amp;gt; the markup frame can be empty like (()) to distinguish an empty template parameter from the specific condition &amp;quot;has no applicable value&amp;quot; in citation-context.&lt;br /&gt;
&lt;br /&gt;
After further evaluation the two cases might be merged at a later stage, but should be kept separated for now.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function has_accept_as_written (str, allow_empty)&lt;br /&gt;
	if not is_set (str) then&lt;br /&gt;
		return str, false;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local count;&lt;br /&gt;
&lt;br /&gt;
	if true == allow_empty then&lt;br /&gt;
		str, count = str:gsub (&#039;^%(%((.*)%)%)$&#039;, &#039;%1&#039;); 						-- allows (()) to be an empty set&lt;br /&gt;
	else&lt;br /&gt;
		str, count = str:gsub (&#039;^%(%((.+)%)%)$&#039;, &#039;%1&#039;);&lt;br /&gt;
	end&lt;br /&gt;
	return str, 0 ~= count;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S U B S T I T U T E &amp;gt;----------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Populates numbered arguments in a message string using an argument table. &amp;lt;args&amp;gt; may be a single string or a&lt;br /&gt;
sequence table of multiple strings.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function substitute (msg, args)&lt;br /&gt;
	return args and mw.message.newRawMessage (msg, args):plain() or msg;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; E R R O R _ C O M M E N T &amp;gt;----------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Wraps error messages with CSS markup according to the state of hidden. &amp;lt;content&amp;gt; may be a single string or a&lt;br /&gt;
sequence table of multiple strings.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function error_comment (content, hidden)&lt;br /&gt;
	return substitute (hidden and cfg.presentation[&#039;hidden-error&#039;] or cfg.presentation[&#039;visible-error&#039;], content);&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; H Y P H E N _ T O _ D A S H &amp;gt;--------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Converts a hyphen to a dash under certain conditions.  The hyphen must separate&lt;br /&gt;
like items; unlike items are returned unmodified.  These forms are modified:&lt;br /&gt;
	letter - letter (A - B)&lt;br /&gt;
	digit - digit (4-5)&lt;br /&gt;
	digit separator digit - digit separator digit (4.1-4.5 or 4-1-4-5)&lt;br /&gt;
	letterdigit - letterdigit (A1-A5) (an optional separator between letter and&lt;br /&gt;
		digit is supported – a.1-a.5 or a-1-a-5)&lt;br /&gt;
	digitletter - digitletter (5a - 5d) (an optional separator between letter and&lt;br /&gt;
		digit is supported – 5.a-5.d or 5-a-5-d)&lt;br /&gt;
&lt;br /&gt;
any other forms are returned unmodified.&lt;br /&gt;
&lt;br /&gt;
str may be a comma- or semicolon-separated list&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function hyphen_to_dash (str)&lt;br /&gt;
	if not is_set (str) then&lt;br /&gt;
		return str;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local accept;																-- boolean&lt;br /&gt;
&lt;br /&gt;
	str = str:gsub (&amp;quot;(%(%(.-%)%))&amp;quot;, function(m) return m:gsub(&amp;quot;,&amp;quot;, &amp;quot;，&amp;quot;):gsub(&amp;quot;;&amp;quot;, &amp;quot;；&amp;quot;) end) -- replace commas and semicolons in accept-as-written markup with similar unicode characters so they&#039;ll be ignored during the split	&lt;br /&gt;
	str = str:gsub (&#039;&amp;amp;[nm]dash;&#039;, {[&#039;&amp;amp;ndash;&#039;] = &#039;–&#039;, [&#039;&amp;amp;mdash;&#039;] = &#039;—&#039;});		-- replace &amp;amp;mdash; and &amp;amp;ndash; entities with their characters; semicolon mucks up the text.split&lt;br /&gt;
	str = str:gsub (&#039;&amp;amp;#45;&#039;, &#039;-&#039;); -- replace HTML numeric entity with hyphen character&lt;br /&gt;
	str = str:gsub (&#039;&amp;amp;nbsp;&#039;, &#039; &#039;); -- replace &amp;amp;nbsp; entity with generic keyboard space character&lt;br /&gt;
	&lt;br /&gt;
	local out = {};&lt;br /&gt;
	local list = mw.text.split (str, &#039;%s*[,;]%s*&#039;);								-- split str at comma or semicolon separators if there are any&lt;br /&gt;
&lt;br /&gt;
	for _, item in ipairs (list) do												-- for each item in the list&lt;br /&gt;
		item, accept = has_accept_as_written (item);							-- remove accept-this-as-written markup when it wraps all of item&lt;br /&gt;
		if not accept and mw.ustring.match (item, &#039;^%w*[%.%-]?%w+%s*[%-–—]%s*%w*[%.%-]?%w+$&#039;) then	-- if a hyphenated range or has endash or emdash separators&lt;br /&gt;
			if item:match (&#039;^%a+[%.%-]?%d+%s*%-%s*%a+[%.%-]?%d+$&#039;) or			-- letterdigit hyphen letterdigit (optional separator between letter and digit)&lt;br /&gt;
				item:match (&#039;^%d+[%.%-]?%a+%s*%-%s*%d+[%.%-]?%a+$&#039;) or			-- digitletter hyphen digitletter (optional separator between digit and letter)&lt;br /&gt;
				item:match (&#039;^%d+[%.%-]%d+%s*%-%s*%d+[%.%-]%d+$&#039;) or			-- digit separator digit hyphen digit separator digit&lt;br /&gt;
				item:match (&#039;^%d+%s*%-%s*%d+$&#039;) or								-- digit hyphen digit&lt;br /&gt;
				item:match (&#039;^%a+%s*%-%s*%a+$&#039;) then							-- letter hyphen letter&lt;br /&gt;
					item = item:gsub (&#039;(%w*[%.%-]?%w+)%s*%-%s*(%w*[%.%-]?%w+)&#039;, &#039;%1–%2&#039;);	-- replace hyphen, remove extraneous space characters&lt;br /&gt;
			else&lt;br /&gt;
				item = mw.ustring.gsub (item, &#039;%s*[–—]%s*&#039;, &#039;–&#039;);				-- for endash or emdash separated ranges, replace em with en, remove extraneous whitespace&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		table.insert (out, item);												-- add the (possibly modified) item to the output table&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local temp_str = &#039;&#039;;														-- concatenate the output table into a comma separated string&lt;br /&gt;
	temp_str, accept = has_accept_as_written (table.concat (out, &#039;, &#039;));		-- remove accept-this-as-written markup when it wraps all of concatenated out&lt;br /&gt;
	if accept then&lt;br /&gt;
		temp_str = has_accept_as_written (str);									-- when global markup removed, return original str; do it this way to suppress boolean second return value&lt;br /&gt;
		return temp_str:gsub(&amp;quot;，&amp;quot;, &amp;quot;,&amp;quot;):gsub(&amp;quot;；&amp;quot;, &amp;quot;;&amp;quot;);&lt;br /&gt;
	else&lt;br /&gt;
		return temp_str:gsub(&amp;quot;，&amp;quot;, &amp;quot;,&amp;quot;):gsub(&amp;quot;；&amp;quot;, &amp;quot;;&amp;quot;);						-- else, return assembled temp_str&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[=[-------------------------&amp;lt; M A K E _ W I K I L I N K &amp;gt;----------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Makes a wikilink; when both link and display text is provided, returns a wikilink in the form [[L|D]]; if only&lt;br /&gt;
link is provided (or link and display are the same), returns a wikilink in the form [[L]]; if neither are&lt;br /&gt;
provided or link is omitted, returns an empty string.&lt;br /&gt;
&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local function make_wikilink (link, display)&lt;br /&gt;
	if not is_set (link) then return &#039;&#039; end&lt;br /&gt;
&lt;br /&gt;
	if is_set (display) and link ~= display then			&lt;br /&gt;
		return table.concat ({&#039;[[&#039;, link, &#039;|&#039;, display, &#039;]]&#039;});			&lt;br /&gt;
	else&lt;br /&gt;
		return table.concat ({&#039;[[&#039;, link, &#039;]]&#039;});&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S E T _ M E S S A G E &amp;gt;----------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Sets an error message using the ~/Configuration error_conditions{} table along with arguments supplied in the function&lt;br /&gt;
call, inserts the resulting message in z.error_msgs_t{} sequence table, and returns the error message.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;error_id&amp;gt; – key value for appropriate error handler in ~/Configuration error_conditions{} table &lt;br /&gt;
&amp;lt;arguments&amp;gt; – may be a single string or a sequence table of multiple strings to be subsititued into error_conditions[error_id].message&lt;br /&gt;
&amp;lt;raw&amp;gt; – boolean&lt;br /&gt;
	true –	causes this function to return the error message not wrapped in visible-error, hidden-error span tag;&lt;br /&gt;
			returns error_conditions[error_id].hidden as a second return value&lt;br /&gt;
			does not add message to z.error_msgs_t sequence table&lt;br /&gt;
	false, nil – adds message wrapped in visible-error, hidden-error span tag to z.error_msgs_t&lt;br /&gt;
			returns the error message wrapped in visible-error, hidden-error span tag; there is no second return value&lt;br /&gt;
&amp;lt;prefix&amp;gt; – string to be prepended to &amp;lt;message&amp;gt;									-- TODO: remove support for these unused(?) arguments?&lt;br /&gt;
&amp;lt;suffix&amp;gt; – string to be appended to &amp;lt;message&amp;gt;&lt;br /&gt;
&lt;br /&gt;
TODO: change z.error_cats_t and z.maint_cats_t to have the form cat_name = true?  this to avoid dups without having to have an extra table&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local added_maint_cats = {}														-- list of maintenance categories that have been added to z.maint_cats_t; TODO: figure out how to delete this table&lt;br /&gt;
&lt;br /&gt;
local function set_message (error_id, arguments, raw, prefix, suffix)&lt;br /&gt;
	local error_state = cfg.error_conditions[error_id];&lt;br /&gt;
	&lt;br /&gt;
	prefix = prefix or &#039;&#039;;&lt;br /&gt;
	suffix = suffix or &#039;&#039;;&lt;br /&gt;
	&lt;br /&gt;
	if error_state == nil then&lt;br /&gt;
		error (cfg.messages[&#039;undefined_error&#039;] .. &#039;: &#039; .. error_id);			-- because missing error handler in Module:Citation/CS1/Configuration&lt;br /&gt;
&lt;br /&gt;
	elseif is_set (error_state.category) then&lt;br /&gt;
		if error_state.message then												-- when error_state.message defined, this is an error message&lt;br /&gt;
			table.insert (z.error_cats_t, error_state.category);&lt;br /&gt;
		else&lt;br /&gt;
			if not added_maint_cats[error_id] then&lt;br /&gt;
				added_maint_cats[error_id] = true;								-- note that we&#039;ve added this category&lt;br /&gt;
				table.insert (z.maint_cats_t, substitute (error_state.category, arguments));	-- make cat name then add to table&lt;br /&gt;
			end&lt;br /&gt;
			return;																-- because no message, nothing more to do&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local message = substitute (error_state.message, arguments);&lt;br /&gt;
&lt;br /&gt;
	message = table.concat (&lt;br /&gt;
		{&lt;br /&gt;
		message,&lt;br /&gt;
		&#039; (&#039;,&lt;br /&gt;
		make_wikilink (&lt;br /&gt;
			table.concat (&lt;br /&gt;
				{&lt;br /&gt;
				cfg.messages[&#039;help page link&#039;],&lt;br /&gt;
				&#039;#&#039;,&lt;br /&gt;
				error_state.anchor&lt;br /&gt;
				}),&lt;br /&gt;
			cfg.messages[&#039;help page label&#039;]),&lt;br /&gt;
		&#039;)&#039;&lt;br /&gt;
		});&lt;br /&gt;
&lt;br /&gt;
	z.error_ids_t[error_id] = true;&lt;br /&gt;
	if z.error_ids_t[&#039;err_citation_missing_title&#039;] and							-- if missing-title error already noted&lt;br /&gt;
		in_array (error_id, {&#039;err_bare_url_missing_title&#039;, &#039;err_trans_missing_title&#039;}) then		-- and this error is one of these&lt;br /&gt;
			return &#039;&#039;, false;													-- don&#039;t bother because one flavor of missing title is sufficient&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	message = table.concat ({prefix, message, suffix});&lt;br /&gt;
&lt;br /&gt;
	if true == raw then&lt;br /&gt;
		return message, error_state.hidden;										-- return message not wrapped in visible-error, hidden-error span tag&lt;br /&gt;
	end		&lt;br /&gt;
&lt;br /&gt;
	message = error_comment (message, error_state.hidden);						-- wrap message in visible-error, hidden-error span tag&lt;br /&gt;
	table.insert (z.error_msgs_t, message);										-- add it to the messages sequence table&lt;br /&gt;
	return message;																-- and done; return value generally not used but is used as a flag in various functions of ~/Identifiers&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[-------------------------&amp;lt; I S _ A L I A S _ U S E D &amp;gt;-----------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
This function is used by select_one() to determine if one of a list of alias parameters is in the argument list&lt;br /&gt;
provided by the template.&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
	args – pointer to the arguments table from calling template&lt;br /&gt;
	alias – one of the list of possible aliases in the aliases lists from Module:Citation/CS1/Configuration&lt;br /&gt;
	index – for enumerated parameters, identifies which one&lt;br /&gt;
	enumerated – true/false flag used to choose how enumerated aliases are examined&lt;br /&gt;
	value – value associated with an alias that has previously been selected; nil if not yet selected&lt;br /&gt;
	selected – the alias that has previously been selected; nil if not yet selected&lt;br /&gt;
	error_list – list of aliases that are duplicates of the alias already selected&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
	value – value associated with alias we selected or that was previously selected or nil if an alias not yet selected&lt;br /&gt;
	selected – the alias we selected or the alias that was previously selected or nil if an alias not yet selected&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function is_alias_used (args, alias, index, enumerated, value, selected, error_list)&lt;br /&gt;
	if enumerated then															-- is this a test for an enumerated parameters?&lt;br /&gt;
		alias = alias:gsub (&#039;#&#039;, index);										-- replace &#039;#&#039; with the value in index&lt;br /&gt;
	else&lt;br /&gt;
		alias = alias:gsub (&#039;#&#039;, &#039;&#039;);											-- remove &#039;#&#039; if it exists&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if is_set (args[alias]) then												-- alias is in the template&#039;s argument list&lt;br /&gt;
		if value ~= nil and selected ~= alias then								-- if we have already selected one of the aliases&lt;br /&gt;
			local skip;&lt;br /&gt;
			for _, v in ipairs (error_list) do									-- spin through the error list to see if we&#039;ve added this alias&lt;br /&gt;
				if v == alias then&lt;br /&gt;
					skip = true;&lt;br /&gt;
					break;														-- has been added so stop looking &lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			if not skip then													-- has not been added so&lt;br /&gt;
				table.insert (error_list, alias);								-- add error alias to the error list&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			value = args[alias];												-- not yet selected an alias, so select this one&lt;br /&gt;
			selected = alias;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return value, selected;														-- return newly selected alias, or previously selected alias&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; A D D _ M A I N T _ C A T &amp;gt;------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Adds a category to z.maint_cats_t using names from the configuration file with additional text if any.&lt;br /&gt;
To prevent duplication, the added_maint_cats table lists the categories by key that have been added to z.maint_cats_t.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function add_maint_cat (key, arguments)&lt;br /&gt;
	if not added_maint_cats [key] then&lt;br /&gt;
		added_maint_cats [key] = true;											-- note that we&#039;ve added this category&lt;br /&gt;
		table.insert (z.maint_cats_t, substitute (cfg.maint_cats [key], arguments));	-- make name then add to table&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; A D D _ P R O P _ C A T &amp;gt;--------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Adds a category to z.prop_cats_t using names from the configuration file with additional text if any.&lt;br /&gt;
&lt;br /&gt;
foreign_lang_source and foreign_lang_source_2 keys have a language code appended to them so that multiple languages&lt;br /&gt;
may be categorized but multiples of the same language are not categorized.&lt;br /&gt;
&lt;br /&gt;
added_prop_cats is a table declared in page scope variables above&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local added_prop_cats = {};														-- list of property categories that have been added to z.prop_cats_t&lt;br /&gt;
&lt;br /&gt;
local function add_prop_cat (key, arguments, key_modifier)&lt;br /&gt;
	local key_modified = key .. ((key_modifier and key_modifier) or &#039;&#039;);		-- modify &amp;lt;key&amp;gt; with &amp;lt;key_modifier&amp;gt; if present and not nil&lt;br /&gt;
	&lt;br /&gt;
	if not added_prop_cats [key_modified] then&lt;br /&gt;
		added_prop_cats [key_modified] = true;									-- note that we&#039;ve added this category&lt;br /&gt;
		table.insert (z.prop_cats_t, substitute (cfg.prop_cats [key], arguments));	-- make name then add to table&lt;br /&gt;
		table.insert (z.prop_keys_t, &#039;cs1-prop-&#039; .. key);						-- convert key to class for use in the citation&#039;s &amp;lt;cite&amp;gt; tag&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S A F E _ F O R _ I T A L I C S &amp;gt;----------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Protects a string that will be wrapped in wiki italic markup &#039;&#039; ... &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Note: We cannot use &amp;lt;i&amp;gt; for italics, as the expected behavior for italics specified by &#039;&#039;...&#039;&#039; in the title is that&lt;br /&gt;
they will be inverted (i.e. unitalicized) in the resulting references.  In addition, &amp;lt;i&amp;gt; and &#039;&#039; tend to interact&lt;br /&gt;
poorly under Mediawiki&#039;s HTML tidy.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function safe_for_italics (str)&lt;br /&gt;
	if not is_set (str) then return str end&lt;br /&gt;
&lt;br /&gt;
	if str:sub (1, 1) == &amp;quot;&#039;&amp;quot; then str = &amp;quot;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot; .. str; end&lt;br /&gt;
	if str:sub (-1, -1) == &amp;quot;&#039;&amp;quot; then str = str .. &amp;quot;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;; end&lt;br /&gt;
	&lt;br /&gt;
	return str:gsub (&#039;\n&#039;, &#039; &#039;);												-- Remove newlines as they break italics.&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; W R A P _ S T Y L E &amp;gt;----------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Applies styling to various parameters.  Supplied string is wrapped using a message_list configuration taking one&lt;br /&gt;
argument; protects italic styled parameters.  Additional text taken from citation_config.presentation - the reason&lt;br /&gt;
this function is similar to but separate from wrap_msg().&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function wrap_style (key, str)&lt;br /&gt;
	if not is_set (str) then&lt;br /&gt;
		return &amp;quot;&amp;quot;;&lt;br /&gt;
	elseif in_array (key, {&#039;italic-title&#039;, &#039;trans-italic-title&#039;}) then&lt;br /&gt;
		str = safe_for_italics (str);&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return substitute (cfg.presentation[key], {str});&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; M A K E _ S E P _ L I S T &amp;gt;------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
make a separated list of items using provided separators.&lt;br /&gt;
	&amp;lt;sep_list&amp;gt; - typically &#039;&amp;lt;comma&amp;gt;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
	&amp;lt;sep_list_pair&amp;gt; - typically &#039;&amp;lt;space&amp;gt;and&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
	&amp;lt;sep_list_end&amp;gt; - typically &#039;&amp;lt;comma&amp;gt;&amp;lt;space&amp;gt;and&amp;lt;space&amp;gt;&#039; or &#039;&amp;lt;comma&amp;gt;&amp;lt;space&amp;gt;&amp;amp;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
&lt;br /&gt;
defaults to cfg.presentation[&#039;sep_list&#039;], cfg.presentation[&#039;sep_list_pair&#039;], and cfg.presentation[&#039;sep_list_end&#039;]&lt;br /&gt;
if &amp;lt;sep_list_end&amp;gt; is specified, &amp;lt;sep_list&amp;gt; and &amp;lt;sep_list_pair&amp;gt; must also be supplied&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function make_sep_list (count, list_seq, sep_list, sep_list_pair, sep_list_end)&lt;br /&gt;
	local list = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
	if not sep_list then														-- set the defaults&lt;br /&gt;
		sep_list = cfg.presentation[&#039;sep_list&#039;];&lt;br /&gt;
		sep_list_pair = cfg.presentation[&#039;sep_list_pair&#039;];&lt;br /&gt;
		sep_list_end = cfg.presentation[&#039;sep_list_end&#039;];&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if 2 &amp;gt;= count then&lt;br /&gt;
		list = table.concat (list_seq, sep_list_pair);							-- insert separator between two items; returns list_seq[1] then only one item&lt;br /&gt;
	elseif 2 &amp;lt; count then&lt;br /&gt;
		list = table.concat (list_seq, sep_list, 1, count - 1);					-- concatenate all but last item with plain list separator&lt;br /&gt;
		list = table.concat ({list, list_seq[count]}, sep_list_end);			-- concatenate last item onto end of &amp;lt;list&amp;gt; with final separator&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return list;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S E L E C T _ O N E &amp;gt;----------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Chooses one matching parameter from a list of parameters to consider.  The list of parameters to consider is just&lt;br /&gt;
names.  For parameters that may be enumerated, the position of the numerator in the parameter name is identified&lt;br /&gt;
by the &#039;#&#039; so |author-last1= and |author1-last= are represented as &#039;author-last#&#039; and &#039;author#-last&#039;.&lt;br /&gt;
&lt;br /&gt;
Because enumerated parameter |&amp;lt;param&amp;gt;1= is an alias of |&amp;lt;param&amp;gt;= we must test for both possibilities.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Generates an error if more than one match is present.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function select_one (args, aliases_list, error_condition, index)&lt;br /&gt;
	local value = nil;															-- the value assigned to the selected parameter&lt;br /&gt;
	local selected = &#039;&#039;;														-- the name of the parameter we have chosen&lt;br /&gt;
	local error_list = {};&lt;br /&gt;
&lt;br /&gt;
	if index ~= nil then index = tostring(index); end&lt;br /&gt;
&lt;br /&gt;
	for _, alias in ipairs (aliases_list) do									-- for each alias in the aliases list&lt;br /&gt;
		if alias:match (&#039;#&#039;) then												-- if this alias can be enumerated&lt;br /&gt;
			if &#039;1&#039; == index then												-- when index is 1 test for enumerated and non-enumerated aliases&lt;br /&gt;
				value, selected = is_alias_used (args, alias, index, false, value, selected, error_list);	-- first test for non-enumerated alias&lt;br /&gt;
			end&lt;br /&gt;
			value, selected = is_alias_used (args, alias, index, true, value, selected, error_list);	-- test for enumerated alias&lt;br /&gt;
		else&lt;br /&gt;
			value, selected = is_alias_used (args, alias, index, false, value, selected, error_list);	-- test for non-enumerated alias&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if #error_list &amp;gt; 0 and &#039;none&#039; ~= error_condition then						-- for cases where this code is used outside of extract_names()&lt;br /&gt;
		for i, v in ipairs (error_list) do&lt;br /&gt;
			error_list[i] = wrap_style (&#039;parameter&#039;, v);&lt;br /&gt;
		end&lt;br /&gt;
		table.insert (error_list, wrap_style (&#039;parameter&#039;, selected));&lt;br /&gt;
		set_message (error_condition, {make_sep_list (#error_list, error_list)});&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return value, selected;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[=[-------------------------&amp;lt; R E M O V E _ W I K I _ L I N K &amp;gt;----------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Gets the display text from a wikilink like [[A|B]] or [[B]] gives B&lt;br /&gt;
&lt;br /&gt;
The str:gsub() returns either A|B froma [[A|B]] or B from [[B]] or B from B (no wikilink markup).&lt;br /&gt;
&lt;br /&gt;
In l(), l:gsub() removes the link and pipe (if they exist); the second :gsub() trims whitespace from the label&lt;br /&gt;
if str was wrapped in wikilink markup.  Presumably, this is because without wikimarkup in str, there is no match&lt;br /&gt;
in the initial gsub, the replacement function l() doesn&#039;t get called.&lt;br /&gt;
&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local function remove_wiki_link (str)&lt;br /&gt;
	return (str:gsub (&amp;quot;%[%[([^%[%]]*)%]%]&amp;quot;, function(l)&lt;br /&gt;
		return l:gsub (&amp;quot;^[^|]*|(.*)$&amp;quot;, &amp;quot;%1&amp;quot; ):gsub (&amp;quot;^%s*(.-)%s*$&amp;quot;, &amp;quot;%1&amp;quot;);&lt;br /&gt;
	end));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[=[-------------------------&amp;lt; I S _ W I K I L I N K &amp;gt;--------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Determines if str is a wikilink, extracts, and returns the wikilink type, link text, and display text parts.&lt;br /&gt;
If str is a complex wikilink ([[L|D]]):&lt;br /&gt;
	returns wl_type 2 and D and L from [[L|D]];&lt;br /&gt;
if str is a simple wikilink ([[D]])&lt;br /&gt;
	returns wl_type 1 and D from [[D]] and L as empty string;&lt;br /&gt;
if not a wikilink:&lt;br /&gt;
	returns wl_type 0, str as D, and L as empty string.&lt;br /&gt;
&lt;br /&gt;
trims leading and trailing whitespace and pipes from L and D ([[L|]] and [[|D]] are accepted by MediaWiki and&lt;br /&gt;
treated like [[D]]; while [[|D|]] is not accepted by MediaWiki, here, we accept it and return D without the pipes).&lt;br /&gt;
&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local function is_wikilink (str)&lt;br /&gt;
	local D, L&lt;br /&gt;
	local wl_type = 2;															-- assume that str is a complex wikilink [[L|D]]&lt;br /&gt;
&lt;br /&gt;
	if not str:match (&#039;^%[%[[^%]]+%]%]$&#039;) then									-- is str some sort of a wikilink (must have some sort of content)&lt;br /&gt;
		return 0, str, &#039;&#039;;														-- not a wikilink; return wl_type as 0, str as D, and empty string as L&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	L, D = str:match (&#039;^%[%[([^|]+)|([^%]]+)%]%]$&#039;);							-- get L and D from [[L|D]] &lt;br /&gt;
&lt;br /&gt;
	if not is_set (D) then														-- if no separate display&lt;br /&gt;
		D = str:match (&#039;^%[%[([^%]]*)|*%]%]$&#039;);									-- get D from [[D]] or [[D|]]&lt;br /&gt;
		wl_type = 1; &lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	D = mw.text.trim (D, &#039;%s|&#039;);												-- trim white space and pipe characters &lt;br /&gt;
	return wl_type, D, L or &#039;&#039;;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S T R I P _ A P O S T R O P H E _ M A R K U P &amp;gt;--------------------------------&lt;br /&gt;
&lt;br /&gt;
Strip wiki italic and bold markup from argument so that it doesn&#039;t contaminate COinS metadata.&lt;br /&gt;
This function strips common patterns of apostrophe markup.  We presume that editors who have taken the time to&lt;br /&gt;
markup a title have, as a result, provided valid markup. When they don&#039;t, some single apostrophes are left behind.&lt;br /&gt;
&lt;br /&gt;
Returns the argument without wiki markup and a number; the number is more-or-less meaningless except as a flag&lt;br /&gt;
to indicate that markup was replaced; do not rely on it as an indicator of how many of any kind of markup was&lt;br /&gt;
removed; returns the argument and nil when no markup removed&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function strip_apostrophe_markup (argument)&lt;br /&gt;
	if not is_set (argument) then&lt;br /&gt;
		return argument, nil;													-- no argument, nothing to do&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if nil == argument:find ( &amp;quot;&#039;&#039;&amp;quot;, 1, true ) then								-- Is there at least one double apostrophe?  If not, exit.&lt;br /&gt;
		return argument, nil;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local flag;&lt;br /&gt;
	while true do&lt;br /&gt;
		if argument:find (&amp;quot;&#039;&#039;&#039;&#039;&#039;&amp;quot;, 1, true) then								-- bold italic (5)&lt;br /&gt;
			argument, flag = argument:gsub (&amp;quot;%&#039;%&#039;%&#039;%&#039;%&#039;&amp;quot;, &amp;quot;&amp;quot;);					-- remove all instances of it&lt;br /&gt;
		elseif argument:find (&amp;quot;&#039;&#039;&#039;&#039;&amp;quot;, 1, true) then								-- italic start and end without content (4)&lt;br /&gt;
			argument, flag=argument:gsub (&amp;quot;%&#039;%&#039;%&#039;%&#039;&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
		elseif argument:find (&amp;quot;&#039;&#039;&#039;&amp;quot;, 1, true) then								-- bold (3)&lt;br /&gt;
			argument, flag=argument:gsub (&amp;quot;%&#039;%&#039;%&#039;&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
		elseif argument:find (&amp;quot;&#039;&#039;&amp;quot;, 1, true) then								-- italic (2)&lt;br /&gt;
			argument, flag = argument:gsub (&amp;quot;%&#039;%&#039;&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
		else&lt;br /&gt;
			break;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return argument, flag;														-- done&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S E T _ S E L E C T E D _ M O D U L E S &amp;gt;--------------------------------------&lt;br /&gt;
&lt;br /&gt;
Sets local cfg table to same (live or sandbox) as that used by the other modules.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function set_selected_modules (cfg_table_ptr)&lt;br /&gt;
	cfg = cfg_table_ptr;&lt;br /&gt;
	&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; E X P O R T S &amp;gt;----------------------------------------------------------------&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
return {&lt;br /&gt;
	add_maint_cat = add_maint_cat,												-- exported functions&lt;br /&gt;
	add_prop_cat = add_prop_cat,&lt;br /&gt;
	error_comment = error_comment,&lt;br /&gt;
	has_accept_as_written = has_accept_as_written,&lt;br /&gt;
	hyphen_to_dash = hyphen_to_dash,&lt;br /&gt;
	in_array = in_array,&lt;br /&gt;
	is_set = is_set,&lt;br /&gt;
	is_wikilink = is_wikilink,&lt;br /&gt;
	make_sep_list = make_sep_list,&lt;br /&gt;
	make_wikilink = make_wikilink,&lt;br /&gt;
	remove_wiki_link = remove_wiki_link,&lt;br /&gt;
	safe_for_italics = safe_for_italics,&lt;br /&gt;
	select_one = select_one,&lt;br /&gt;
	set_message = set_message,&lt;br /&gt;
	set_selected_modules = set_selected_modules,&lt;br /&gt;
	strip_apostrophe_markup = strip_apostrophe_markup,&lt;br /&gt;
	substitute = substitute,&lt;br /&gt;
	wrap_style = wrap_style,&lt;br /&gt;
&lt;br /&gt;
	z = z,																		-- exported table&lt;br /&gt;
	}&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Modul:Citation/CS1/Identifiers&amp;diff=1525</id>
		<title>Modul:Citation/CS1/Identifiers</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Modul:Citation/CS1/Identifiers&amp;diff=1525"/>
		<updated>2022-08-12T16:59:11Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--[[--------------------------&amp;lt; F O R W A R D   D E C L A R A T I O N S &amp;gt;--------------------------------------&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local has_accept_as_written, is_set, in_array, set_message, select_one,			-- functions in Module:Citation/CS1/Utilities&lt;br /&gt;
		substitute, make_wikilink;&lt;br /&gt;
&lt;br /&gt;
local z;																		-- table of tables defined in Module:Citation/CS1/Utilities&lt;br /&gt;
&lt;br /&gt;
local cfg;																		-- table of configuration tables that are defined in Module:Citation/CS1/Configuration&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; P A G E   S C O P E   V A R I A B L E S &amp;gt;--------------------------------------&lt;br /&gt;
&lt;br /&gt;
declare variables here that have page-wide scope that are not brought in from other modules; that are created here and used here&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local auto_link_urls = {};														-- holds identifier URLs for those identifiers that can auto-link |title=&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--============================&amp;lt;&amp;lt; H E L P E R   F U N C T I O N S &amp;gt;&amp;gt;============================================&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; W I K I D A T A _ A R T I C L E _ N A M E _ G E T &amp;gt;----------------------------&lt;br /&gt;
&lt;br /&gt;
as an aid to internationalizing identifier-label wikilinks, gets identifier article names from Wikidata.&lt;br /&gt;
&lt;br /&gt;
returns :&amp;lt;lang code&amp;gt;:&amp;lt;article title&amp;gt; when &amp;lt;q&amp;gt; has an &amp;lt;article title&amp;gt; for &amp;lt;lang code&amp;gt;; nil else&lt;br /&gt;
&lt;br /&gt;
for identifiers that do not have q, returns nil&lt;br /&gt;
&lt;br /&gt;
for wikis that do not have mw.wikibase installed, returns nil&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function wikidata_article_name_get (q)&lt;br /&gt;
	if not is_set (q) or (q and not mw.wikibase) then							-- when no q number or when a q number but mw.wikibase not installed on this wiki&lt;br /&gt;
		return nil;																-- abandon&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local wd_article;&lt;br /&gt;
	local this_wiki_code = cfg.this_wiki_code;									-- Wikipedia subdomain; &#039;en&#039; for en.wikipedia.org&lt;br /&gt;
&lt;br /&gt;
	wd_article = mw.wikibase.getSitelink (q, this_wiki_code .. &#039;wiki&#039;);			-- fetch article title from WD; nil when no title available at this wiki&lt;br /&gt;
&lt;br /&gt;
	if wd_article then&lt;br /&gt;
		wd_article = table.concat ({&#039;:&#039;, this_wiki_code, &#039;:&#039;, wd_article});		-- interwiki-style link without brackets if taken from WD; leading colon required&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return wd_article;															-- article title from WD; nil else&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; L I N K _ L A B E L _ M A K E &amp;gt;------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
common function to create identifier link label from handler table or from Wikidata&lt;br /&gt;
&lt;br /&gt;
returns the first available of&lt;br /&gt;
	1. redirect from local wiki&#039;s handler table (if enabled)&lt;br /&gt;
	2. Wikidata (if there is a Wikidata entry for this identifier in the local wiki&#039;s language)&lt;br /&gt;
	3. label specified in the local wiki&#039;s handler table&lt;br /&gt;
	&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function link_label_make (handler)&lt;br /&gt;
	local wd_article;&lt;br /&gt;
	&lt;br /&gt;
	if not (cfg.use_identifier_redirects and is_set (handler.redirect)) then	-- redirect has priority so if enabled and available don&#039;t fetch from Wikidata because expensive&lt;br /&gt;
		wd_article = wikidata_article_name_get (handler.q);						-- if Wikidata has an article title for this wiki, get it;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return (cfg.use_identifier_redirects and is_set (handler.redirect) and handler.redirect) or wd_article or handler.link;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; E X T E R N A L _ L I N K _ I D &amp;gt;----------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Formats a wiki-style external link&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function external_link_id (options)&lt;br /&gt;
	local url_string = options.id;&lt;br /&gt;
	local ext_link;&lt;br /&gt;
	local this_wiki_code = cfg.this_wiki_code;									-- Wikipedia subdomain; &#039;en&#039; for en.wikipedia.org&lt;br /&gt;
	local wd_article;															-- article title from Wikidata&lt;br /&gt;
	&lt;br /&gt;
	if options.encode == true or options.encode == nil then&lt;br /&gt;
		url_string = mw.uri.encode (url_string, &#039;PATH&#039;);&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if options.auto_link and is_set (options.access) then&lt;br /&gt;
		auto_link_urls[options.auto_link] = table.concat ({options.prefix, url_string, options.suffix});&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	ext_link = mw.ustring.format (&#039;[%s%s%s %s]&#039;, options.prefix, url_string, options.suffix or &amp;quot;&amp;quot;, mw.text.nowiki (options.id));&lt;br /&gt;
	if is_set (options.access) then&lt;br /&gt;
		ext_link = substitute (cfg.presentation[&#039;ext-link-access-signal&#039;], {cfg.presentation[options.access].class, cfg.presentation[options.access].title, ext_link});	-- add the free-to-read / paywall lock&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return table.concat	({&lt;br /&gt;
		make_wikilink (link_label_make (options), options.label),				-- redirect, Wikidata link, or locally specified link (in that order)&lt;br /&gt;
		options.separator or &#039;&amp;amp;nbsp;&#039;,&lt;br /&gt;
		ext_link&lt;br /&gt;
		});&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; I N T E R N A L _ L I N K _ I D &amp;gt;----------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Formats a wiki-style internal link&lt;br /&gt;
&lt;br /&gt;
TODO: Does not currently need to support options.access, options.encode, auto-linking and COinS (as in external_link_id),&lt;br /&gt;
but may be needed in the future for :m:Interwiki_map custom-prefixes like :arxiv:, :bibcode:, :DOI:, :hdl:, :ISSN:,&lt;br /&gt;
:JSTOR:, :Openlibrary:, :PMID:, :RFC:.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function internal_link_id (options)&lt;br /&gt;
	local id = mw.ustring.gsub (options.id, &#039;%d&#039;, cfg.date_names.local_digits);	-- translate &#039;local&#039; digits to Western 0-9&lt;br /&gt;
&lt;br /&gt;
	return table.concat (&lt;br /&gt;
		{&lt;br /&gt;
		make_wikilink (link_label_make (options), options.label),				-- wiki-link the identifier label&lt;br /&gt;
		options.separator or &#039;&amp;amp;nbsp;&#039;,											-- add the separator&lt;br /&gt;
		make_wikilink (&lt;br /&gt;
			table.concat (&lt;br /&gt;
				{&lt;br /&gt;
				options.prefix,&lt;br /&gt;
				id,																-- translated to Western digits&lt;br /&gt;
				options.suffix or &#039;&#039;&lt;br /&gt;
				}),&lt;br /&gt;
			substitute (cfg.presentation[&#039;bdi&#039;], {&#039;&#039;, mw.text.nowiki (options.id)})	-- bdi tags to prevent Latin script identifiers from being reversed at RTL language wikis&lt;br /&gt;
			);																	-- nowiki because MediaWiki still has magic links for ISBN and the like; TODO: is it really required?&lt;br /&gt;
		});&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; I S _ E M B A R G O E D &amp;gt;------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Determines if a PMC identifier&#039;s online version is embargoed. Compares the date in |pmc-embargo-date= against&lt;br /&gt;
today&#039;s date.  If embargo date is in the future, returns the content of |pmc-embargo-date=; otherwise, returns&lt;br /&gt;
an empty string because the embargo has expired or because |pmc-embargo-date= was not set in this cite.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function is_embargoed (embargo)&lt;br /&gt;
	if is_set (embargo) then&lt;br /&gt;
		local lang = mw.getContentLanguage();&lt;br /&gt;
		local good1, embargo_date, todays_date;&lt;br /&gt;
		good1, embargo_date = pcall (lang.formatDate, lang, &#039;U&#039;, embargo);&lt;br /&gt;
		todays_date = lang:formatDate (&#039;U&#039;);&lt;br /&gt;
	&lt;br /&gt;
		if good1 then															-- if embargo date is a good date&lt;br /&gt;
			if tonumber (embargo_date) &amp;gt;= tonumber (todays_date) then			-- is embargo date is in the future?&lt;br /&gt;
				return embargo;													-- still embargoed&lt;br /&gt;
			else&lt;br /&gt;
				set_message (&#039;maint_pmc_embargo&#039;);								-- embargo has expired; add main cat&lt;br /&gt;
				return &#039;&#039;;														-- unset because embargo has expired&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;&#039;;																	-- |pmc-embargo-date= not set return empty string&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[=[-------------------------&amp;lt; I S _ V A L I D _ B I O R X I V _ D A T E &amp;gt;------------------------------------&lt;br /&gt;
&lt;br /&gt;
returns true if:&lt;br /&gt;
	2019-12-11T00:00Z &amp;lt;= biorxiv_date &amp;lt; today + 2 days&lt;br /&gt;
	&lt;br /&gt;
The dated form of biorxiv identifier has a start date of 2019-12-11.  The Unix timestamp for that date is {{#time:U|2019-12-11}} = 1576022400&lt;br /&gt;
&lt;br /&gt;
biorxiv_date is the date provided in those |biorxiv= parameter values that are dated at time 00:00:00 UTC&lt;br /&gt;
today is the current date at time 00:00:00 UTC plus 48 hours&lt;br /&gt;
	if today is 2015-01-01T00:00:00 then&lt;br /&gt;
		adding 24 hours gives 2015-01-02T00:00:00 – one second more than today&lt;br /&gt;
		adding 24 hours gives 2015-01-03T00:00:00 – one second more than tomorrow&lt;br /&gt;
&lt;br /&gt;
This function does not work if it is fed month names for languages other than English.  Wikimedia #time: parser&lt;br /&gt;
apparently doesn&#039;t understand non-English date month names. This function will always return false when the date&lt;br /&gt;
contains a non-English month name because good1 is false after the call to lang_object.formatDate().  To get&lt;br /&gt;
around that call this function with date parts and create a YYYY-MM-DD format date.&lt;br /&gt;
&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local function is_valid_biorxiv_date (y, m, d)&lt;br /&gt;
	local biorxiv_date = table.concat ({y, m, d}, &#039;-&#039;);							-- make ymd date&lt;br /&gt;
	local good1, good2;&lt;br /&gt;
	local biorxiv_ts, tomorrow_ts;												-- to hold Unix timestamps representing the dates&lt;br /&gt;
	local lang_object = mw.getContentLanguage();&lt;br /&gt;
&lt;br /&gt;
	good1, biorxiv_ts = pcall (lang_object.formatDate, lang_object, &#039;U&#039;, biorxiv_date);		-- convert biorxiv_date value to Unix timestamp &lt;br /&gt;
	good2, tomorrow_ts = pcall (lang_object.formatDate, lang_object, &#039;U&#039;, &#039;today + 2 days&#039; );	-- today midnight + 2 days is one second more than all day tomorrow&lt;br /&gt;
	&lt;br /&gt;
	if good1 and good2 then														-- lang.formatDate() returns a timestamp in the local script which tonumber() may not understand&lt;br /&gt;
		biorxiv_ts = tonumber (biorxiv_ts) or lang_object:parseFormattedNumber (biorxiv_ts);	-- convert to numbers for the comparison;&lt;br /&gt;
		tomorrow_ts = tonumber (tomorrow_ts) or lang_object:parseFormattedNumber (tomorrow_ts);&lt;br /&gt;
	else&lt;br /&gt;
		return false;															-- one or both failed to convert to Unix timestamp&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return ((1576022400 &amp;lt;= biorxiv_ts) and (biorxiv_ts &amp;lt; tomorrow_ts))			-- 2012-12-11T00:00Z &amp;lt;= biorxiv_date &amp;lt; tomorrow&#039;s date&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; IS _ V A L I D _ I S X N &amp;gt;-----------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
ISBN-10 and ISSN validator code calculates checksum across all ISBN/ISSN digits including the check digit.&lt;br /&gt;
ISBN-13 is checked in isbn().&lt;br /&gt;
&lt;br /&gt;
If the number is valid the result will be 0. Before calling this function, ISBN/ISSN must be checked for length&lt;br /&gt;
and stripped of dashes, spaces and other non-ISxN characters.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function is_valid_isxn (isxn_str, len)&lt;br /&gt;
	local temp = 0;&lt;br /&gt;
	isxn_str = { isxn_str:byte(1, len) };										-- make a table of byte values &#039;0&#039; → 0x30 .. &#039;9&#039; → 0x39, &#039;X&#039; → 0x58&lt;br /&gt;
	len = len + 1;																-- adjust to be a loop counter&lt;br /&gt;
	for i, v in ipairs (isxn_str) do											-- loop through all of the bytes and calculate the checksum&lt;br /&gt;
		if v == string.byte (&amp;quot;X&amp;quot; ) then											-- if checkdigit is X (compares the byte value of &#039;X&#039; which is 0x58)&lt;br /&gt;
			temp = temp + 10 * (len - i);										-- it represents 10 decimal&lt;br /&gt;
		else&lt;br /&gt;
			temp = temp + tonumber (string.char (v) )*(len-i);&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return temp % 11 == 0;														-- returns true if calculation result is zero&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; IS _ V A L I D _ I S X N _ 1 3 &amp;gt;-----------------------------------------------&lt;br /&gt;
&lt;br /&gt;
ISBN-13 and ISMN validator code calculates checksum across all 13 ISBN/ISMN digits including the check digit.&lt;br /&gt;
If the number is valid, the result will be 0. Before calling this function, ISBN-13/ISMN must be checked for length&lt;br /&gt;
and stripped of dashes, spaces and other non-ISxN-13 characters.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function is_valid_isxn_13 (isxn_str)&lt;br /&gt;
	local temp=0;&lt;br /&gt;
	&lt;br /&gt;
	isxn_str = { isxn_str:byte(1, 13) };										-- make a table of byte values &#039;0&#039; → 0x30 .. &#039;9&#039; → 0x39&lt;br /&gt;
	for i, v in ipairs (isxn_str) do&lt;br /&gt;
		temp = temp + (3 - 2*(i % 2)) * tonumber (string.char (v) );			-- multiply odd index digits by 1, even index digits by 3 and sum; includes check digit&lt;br /&gt;
	end&lt;br /&gt;
	return temp % 10 == 0;														-- sum modulo 10 is zero when ISBN-13/ISMN is correct&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; N O R M A L I Z E _ L C C N &amp;gt;--------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
LCCN normalization (http://www.loc.gov/marc/lccn-namespace.html#normalization)&lt;br /&gt;
1. Remove all blanks.&lt;br /&gt;
2. If there is a forward slash (/) in the string, remove it, and remove all characters to the right of the forward slash.&lt;br /&gt;
3. If there is a hyphen in the string:&lt;br /&gt;
	a. Remove it.&lt;br /&gt;
	b. Inspect the substring following (to the right of) the (removed) hyphen. Then (and assuming that steps 1 and 2 have been carried out):&lt;br /&gt;
		1. All these characters should be digits, and there should be six or less. (not done in this function)&lt;br /&gt;
		2. If the length of the substring is less than 6, left-fill the substring with zeroes until the length is six.&lt;br /&gt;
&lt;br /&gt;
Returns a normalized LCCN for lccn() to validate.  There is no error checking (step 3.b.1) performed in this function.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function normalize_lccn (lccn)&lt;br /&gt;
	lccn = lccn:gsub (&amp;quot;%s&amp;quot;, &amp;quot;&amp;quot;);												-- 1. strip whitespace&lt;br /&gt;
&lt;br /&gt;
	if nil ~= string.find (lccn, &#039;/&#039;) then&lt;br /&gt;
		lccn = lccn:match (&amp;quot;(.-)/&amp;quot;);											-- 2. remove forward slash and all character to the right of it&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local prefix&lt;br /&gt;
	local suffix&lt;br /&gt;
	prefix, suffix = lccn:match (&amp;quot;(.+)%-(.+)&amp;quot;);									-- 3.a remove hyphen by splitting the string into prefix and suffix&lt;br /&gt;
&lt;br /&gt;
	if nil ~= suffix then														-- if there was a hyphen&lt;br /&gt;
		suffix = string.rep(&amp;quot;0&amp;quot;, 6-string.len (suffix)) .. suffix;				-- 3.b.2 left fill the suffix with 0s if suffix length less than 6&lt;br /&gt;
		lccn = prefix..suffix;													-- reassemble the LCCN&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return lccn;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--============================&amp;lt;&amp;lt; I D E N T I F I E R   F U N C T I O N S &amp;gt;&amp;gt;====================================&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; A R X I V &amp;gt;--------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
See: http://arxiv.org/help/arxiv_identifier&lt;br /&gt;
&lt;br /&gt;
format and error check arXiv identifier.  There are three valid forms of the identifier:&lt;br /&gt;
the first form, valid only between date codes 9107 and 0703, is:&lt;br /&gt;
	arXiv:&amp;lt;archive&amp;gt;.&amp;lt;class&amp;gt;/&amp;lt;date code&amp;gt;&amp;lt;number&amp;gt;&amp;lt;version&amp;gt;&lt;br /&gt;
where:&lt;br /&gt;
	&amp;lt;archive&amp;gt; is a string of alpha characters - may be hyphenated; no other punctuation&lt;br /&gt;
	&amp;lt;class&amp;gt; is a string of alpha characters - may be hyphenated; no other punctuation; not the same as |class= parameter which is not supported in this form&lt;br /&gt;
	&amp;lt;date code&amp;gt; is four digits in the form YYMM where YY is the last two digits of the four-digit year and MM is the month number January = 01&lt;br /&gt;
		first digit of YY for this form can only 9 and 0&lt;br /&gt;
	&amp;lt;number&amp;gt; is a three-digit number&lt;br /&gt;
	&amp;lt;version&amp;gt; is a 1 or more digit number preceded with a lowercase v; no spaces (undocumented)&lt;br /&gt;
	&lt;br /&gt;
the second form, valid from April 2007 through December 2014 is:&lt;br /&gt;
	arXiv:&amp;lt;date code&amp;gt;.&amp;lt;number&amp;gt;&amp;lt;version&amp;gt;&lt;br /&gt;
where:&lt;br /&gt;
	&amp;lt;date code&amp;gt; is four digits in the form YYMM where YY is the last two digits of the four-digit year and MM is the month number January = 01&lt;br /&gt;
	&amp;lt;number&amp;gt; is a four-digit number&lt;br /&gt;
	&amp;lt;version&amp;gt; is a 1 or more digit number preceded with a lowercase v; no spaces&lt;br /&gt;
&lt;br /&gt;
the third form, valid from January 2015 is:&lt;br /&gt;
	arXiv:&amp;lt;date code&amp;gt;.&amp;lt;number&amp;gt;&amp;lt;version&amp;gt;&lt;br /&gt;
where:&lt;br /&gt;
	&amp;lt;date code&amp;gt; and &amp;lt;version&amp;gt; are as defined for 0704-1412&lt;br /&gt;
	&amp;lt;number&amp;gt; is a five-digit number&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function arxiv (options)&lt;br /&gt;
	local id = options.id;&lt;br /&gt;
	local class = options.Class;												-- TODO: lowercase?&lt;br /&gt;
	local handler = options.handler;&lt;br /&gt;
	local year, month, version;&lt;br /&gt;
	local err_msg = false;														-- assume no error message&lt;br /&gt;
	local text;																	-- output text&lt;br /&gt;
	&lt;br /&gt;
	if id:match(&amp;quot;^%a[%a%.%-]+/[90]%d[01]%d%d%d%d$&amp;quot;) or id:match(&amp;quot;^%a[%a%.%-]+/[90]%d[01]%d%d%d%dv%d+$&amp;quot;) then	-- test for the 9107-0703 format with or without version&lt;br /&gt;
		year, month = id:match(&amp;quot;^%a[%a%.%-]+/([90]%d)([01]%d)%d%d%d[v%d]*$&amp;quot;);&lt;br /&gt;
		year = tonumber (year);&lt;br /&gt;
		month = tonumber (month);&lt;br /&gt;
		if ((not (90 &amp;lt; year or 8 &amp;gt; year)) or (1 &amp;gt; month or 12 &amp;lt; month)) or		-- if invalid year or invalid month&lt;br /&gt;
			((91 == year and 7 &amp;gt; month) or (7 == year and 3 &amp;lt; month)) then		-- if years ok, are starting and ending months ok?&lt;br /&gt;
				err_msg = true;													-- flag for error message&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
	elseif id:match(&amp;quot;^%d%d[01]%d%.%d%d%d%d$&amp;quot;) or id:match(&amp;quot;^%d%d[01]%d%.%d%d%d%dv%d+$&amp;quot;) then	-- test for the 0704-1412 with or without version&lt;br /&gt;
		year, month = id:match(&amp;quot;^(%d%d)([01]%d)%.%d%d%d%d[v%d]*$&amp;quot;);&lt;br /&gt;
		year = tonumber (year);&lt;br /&gt;
		month = tonumber (month);&lt;br /&gt;
		if ((7 &amp;gt; year) or (14 &amp;lt; year) or (1 &amp;gt; month or 12 &amp;lt; month)) or			-- is year invalid or is month invalid? (doesn&#039;t test for future years)&lt;br /&gt;
			((7 == year) and (4 &amp;gt; month)) then									-- when year is 07, is month invalid (before April)?&lt;br /&gt;
				err_msg = true;													-- flag for error message&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
	elseif id:match(&amp;quot;^%d%d[01]%d%.%d%d%d%d%d$&amp;quot;) or id:match(&amp;quot;^%d%d[01]%d%.%d%d%d%d%dv%d+$&amp;quot;) then	-- test for the 1501- format with or without version&lt;br /&gt;
		year, month = id:match(&amp;quot;^(%d%d)([01]%d)%.%d%d%d%d%d[v%d]*$&amp;quot;);&lt;br /&gt;
		year = tonumber (year);&lt;br /&gt;
		month = tonumber (month);&lt;br /&gt;
		if ((15 &amp;gt; year) or (1 &amp;gt; month or 12 &amp;lt; month)) then						-- is year invalid or is month invalid? (doesn&#039;t test for future years)&lt;br /&gt;
			err_msg = true;														-- flag for error message&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
	else&lt;br /&gt;
		err_msg = true;															-- not a recognized format; flag for error message&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if err_msg then&lt;br /&gt;
		options.coins_list_t[&#039;ARXIV&#039;] = nil;									-- when error, unset so not included in COinS&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local err_msg_t = {};&lt;br /&gt;
	if err_msg then&lt;br /&gt;
		set_message (&#039;err_bad_arxiv&#039;);&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,&lt;br /&gt;
			prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = handler.access});&lt;br /&gt;
&lt;br /&gt;
	if is_set (class) then&lt;br /&gt;
		if id:match (&#039;^%d+&#039;) then&lt;br /&gt;
			text = table.concat ({text, &#039; [[//arxiv.org/archive/&#039;, class, &#039; &#039;, class, &#039;]]&#039;});	-- external link within square brackets, not wikilink&lt;br /&gt;
		else&lt;br /&gt;
			set_message (&#039;err_class_ignored&#039;);&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return text;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; B I B C O D E &amp;gt;--------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Validates (sort of) and formats a bibcode ID.&lt;br /&gt;
&lt;br /&gt;
Format for bibcodes is specified here: http://adsabs.harvard.edu/abs_doc/help_pages/data.html#bibcodes&lt;br /&gt;
&lt;br /&gt;
But, this: 2015arXiv151206696F is apparently valid so apparently, the only things that really matter are length, 19 characters&lt;br /&gt;
and first four digits must be a year.  This function makes these tests:&lt;br /&gt;
	length must be 19 characters&lt;br /&gt;
	characters in position&lt;br /&gt;
		1–4 must be digits and must represent a year in the range of 1000 – next year&lt;br /&gt;
		5 must be a letter&lt;br /&gt;
		6–8 must be letter, digit, ampersand, or dot (ampersand cannot directly precede a dot; &amp;amp;. )&lt;br /&gt;
		9–18 must be letter, digit, or dot&lt;br /&gt;
		19 must be a letter or dot&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function bibcode (options)&lt;br /&gt;
	local id = options.id;&lt;br /&gt;
	local access = options.access;&lt;br /&gt;
	local handler = options.handler;&lt;br /&gt;
	local err_type;&lt;br /&gt;
	local err_msg = &#039;&#039;;&lt;br /&gt;
	local year;&lt;br /&gt;
&lt;br /&gt;
	local text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,&lt;br /&gt;
		prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode,&lt;br /&gt;
		access = access});&lt;br /&gt;
	&lt;br /&gt;
	if 19 ~= id:len() then&lt;br /&gt;
		err_type = cfg.err_msg_supl.length;&lt;br /&gt;
	else&lt;br /&gt;
		year = id:match (&amp;quot;^(%d%d%d%d)[%a][%w&amp;amp;%.][%w&amp;amp;%.][%w&amp;amp;%.][%w.]+[%a%.]$&amp;quot;);&lt;br /&gt;
		if not year then														-- if nil then no pattern match&lt;br /&gt;
			err_type = cfg.err_msg_supl.value;									-- so value error&lt;br /&gt;
		else&lt;br /&gt;
			local next_year = tonumber (os.date (&#039;%Y&#039;)) + 1;					-- get the current year as a number and add one for next year&lt;br /&gt;
			year = tonumber (year);												-- convert year portion of bibcode to a number&lt;br /&gt;
			if (1000 &amp;gt; year) or (year &amp;gt; next_year) then&lt;br /&gt;
				err_type = cfg.err_msg_supl.year;								-- year out of bounds&lt;br /&gt;
			end&lt;br /&gt;
			if id:find(&#039;&amp;amp;%.&#039;) then&lt;br /&gt;
				err_type = cfg.err_msg_supl.journal;							-- journal abbreviation must not have &#039;&amp;amp;.&#039; (if it does it&#039;s missing a letter)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if is_set (err_type) then													-- if there was an error detected&lt;br /&gt;
		set_message (&#039;err_bad_bibcode&#039;, {err_type});&lt;br /&gt;
		options.coins_list_t[&#039;BIBCODE&#039;] = nil;									-- when error, unset so not included in COinS&lt;br /&gt;
&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return text;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; B I O R X I V &amp;gt;-----------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Format bioRxiv ID and do simple error checking.  Before 2019-12-11, biorXiv IDs were 10.1101/ followed by exactly&lt;br /&gt;
6 digits.  After 2019-12-11, biorXiv IDs retained the six-digit identifier but prefixed that with a yyyy.mm.dd. &lt;br /&gt;
date and suffixed with an optional version identifier.&lt;br /&gt;
&lt;br /&gt;
The bioRxiv ID is the string of characters:&lt;br /&gt;
	https://doi.org/10.1101/078733 -&amp;gt; 10.1101/078733&lt;br /&gt;
or a date followed by a six-digit number followed by an optional version indicator &#039;v&#039; and one or more digits:&lt;br /&gt;
	https://www.biorxiv.org/content/10.1101/2019.12.11.123456v2 -&amp;gt; 10.1101/2019.12.11.123456v2&lt;br /&gt;
	&lt;br /&gt;
see https://www.biorxiv.org/about-biorxiv&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function biorxiv (options)&lt;br /&gt;
	local id = options.id;&lt;br /&gt;
	local handler = options.handler;&lt;br /&gt;
	local err_msg = true;														-- flag; assume that there will be an error&lt;br /&gt;
	&lt;br /&gt;
	local patterns = {&lt;br /&gt;
		&#039;^10.1101/%d%d%d%d%d%d$&#039;,												-- simple 6-digit identifier (before 2019-12-11)&lt;br /&gt;
		&#039;^10.1101/(20[1-9]%d)%.([01]%d)%.([0-3]%d)%.%d%d%d%d%d%dv%d+$&#039;,			-- y.m.d. date + 6-digit identifier + version (after 2019-12-11)&lt;br /&gt;
		&#039;^10.1101/(20[1-9]%d)%.([01]%d)%.([0-3]%d)%.%d%d%d%d%d%d$&#039;,				-- y.m.d. date + 6-digit identifier (after 2019-12-11)&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	for _, pattern in ipairs (patterns) do										-- spin through the patterns looking for a match&lt;br /&gt;
		if id:match (pattern) then&lt;br /&gt;
			local y, m, d = id:match (pattern);									-- found a match, attempt to get year, month and date from the identifier&lt;br /&gt;
&lt;br /&gt;
			if m then															-- m is nil when id is the six-digit form&lt;br /&gt;
				if not is_valid_biorxiv_date (y, m, d) then						-- validate the encoded date; TODO: don&#039;t ignore leap-year and actual month lengths ({{#time:}} is a poor date validator)&lt;br /&gt;
					break;														-- date fail; break out early so we don&#039;t unset the error message&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			err_msg = nil;														-- we found a match so unset the error message&lt;br /&gt;
			break;																-- and done&lt;br /&gt;
		end&lt;br /&gt;
	end																			-- err_cat remains set here when no match&lt;br /&gt;
&lt;br /&gt;
	if err_msg then&lt;br /&gt;
		options.coins_list_t[&#039;BIORXIV&#039;] = nil;									-- when error, unset so not included in COinS&lt;br /&gt;
		set_message (&#039;err_bad_biorxiv&#039;);										-- and set the error message&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,&lt;br /&gt;
			prefix = handler.prefix, id = id, separator = handler.separator,&lt;br /&gt;
			encode = handler.encode, access = handler.access});&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; C I T E S E E R X &amp;gt;------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
CiteSeerX use their own notion of &amp;quot;doi&amp;quot; (not to be confused with the identifiers resolved via doi.org).&lt;br /&gt;
&lt;br /&gt;
The description of the structure of this identifier can be found at Help_talk:Citation_Style_1/Archive_26#CiteSeerX_id_structure&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function citeseerx (options)&lt;br /&gt;
	local id = options.id;&lt;br /&gt;
	local handler = options.handler;&lt;br /&gt;
	local matched;&lt;br /&gt;
&lt;br /&gt;
	local text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,&lt;br /&gt;
		prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode,&lt;br /&gt;
		access = handler.access});&lt;br /&gt;
	&lt;br /&gt;
	matched = id:match (&amp;quot;^10%.1%.1%.[1-9]%d?%d?%d?%.[1-9]%d?%d?%d?$&amp;quot;);&lt;br /&gt;
	if not matched then&lt;br /&gt;
		set_message (&#039;err_bad_citeseerx&#039; );&lt;br /&gt;
		options.coins_list_t[&#039;CITESEERX&#039;] = nil;								-- when error, unset so not included in COinS&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return text;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; D O I &amp;gt;------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Formats a DOI and checks for DOI errors.&lt;br /&gt;
&lt;br /&gt;
DOI names contain two parts: prefix and suffix separated by a forward slash.&lt;br /&gt;
	Prefix: directory indicator &#039;10.&#039; followed by a registrant code&lt;br /&gt;
	Suffix: character string of any length chosen by the registrant&lt;br /&gt;
&lt;br /&gt;
This function checks a DOI name for: prefix/suffix.  If the DOI name contains spaces or endashes, or, if it ends&lt;br /&gt;
with a period or a comma, this function will emit a bad_doi error message.&lt;br /&gt;
&lt;br /&gt;
DOI names are case-insensitive and can incorporate any printable Unicode characters so the test for spaces, endash,&lt;br /&gt;
and terminal punctuation may not be technically correct but it appears, that in practice these characters are rarely&lt;br /&gt;
if ever used in DOI names.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function doi (options)&lt;br /&gt;
	local id = options.id;&lt;br /&gt;
	local inactive = options.DoiBroken&lt;br /&gt;
	local access = options.access;&lt;br /&gt;
	local ignore_invalid = options.accept;&lt;br /&gt;
	local handler = options.handler;&lt;br /&gt;
	local err_flag;&lt;br /&gt;
&lt;br /&gt;
	local text;&lt;br /&gt;
	if is_set (inactive) then&lt;br /&gt;
		local inactive_year = inactive:match(&amp;quot;%d%d%d%d&amp;quot;) or &#039;&#039;;					-- try to get the year portion from the inactive date&lt;br /&gt;
		local inactive_month, good;&lt;br /&gt;
&lt;br /&gt;
		if is_set (inactive_year) then&lt;br /&gt;
			if 4 &amp;lt; inactive:len() then											-- inactive date has more than just a year (could be anything)&lt;br /&gt;
				local lang_obj = mw.getContentLanguage();						-- get a language object for this wiki&lt;br /&gt;
				good, inactive_month = pcall (lang_obj.formatDate, lang_obj, &#039;F&#039;, inactive);	-- try to get the month name from the inactive date&lt;br /&gt;
				if not good then&lt;br /&gt;
					inactive_month = nil;										-- something went wrong so make sure this is unset&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			inactive_year = nil;												-- |doi-broken-date= has something but it isn&#039;t a date&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		if is_set (inactive_year) and is_set (inactive_month) then&lt;br /&gt;
			set_message (&#039;maint_doi_inactive_dated&#039;, {inactive_year, inactive_month, &#039; &#039;});&lt;br /&gt;
		elseif is_set (inactive_year) then&lt;br /&gt;
			set_message (&#039;maint_doi_inactive_dated&#039;, {inactive_year, &#039;&#039;, &#039;&#039;});&lt;br /&gt;
		else&lt;br /&gt;
			set_message (&#039;maint_doi_inactive&#039;);&lt;br /&gt;
		end&lt;br /&gt;
		inactive = &amp;quot; (&amp;quot; .. cfg.messages[&#039;inactive&#039;] .. &#039; &#039; .. inactive .. &#039;)&#039;;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local registrant = mw.ustring.match (id, &#039;^10%.([^/]+)/[^%s–]-[^%.,]$&#039;);	-- registrant set when DOI has the proper basic form&lt;br /&gt;
&lt;br /&gt;
	local registrant_err_patterns = {											-- these patterns are for code ranges that are not supported &lt;br /&gt;
		&#039;^[^1-3]%d%d%d%d%.%d%d*$&#039;,												-- 5 digits with subcode (0xxxx, 40000+); accepts: 10000–39999&lt;br /&gt;
		&#039;^[^1-5]%d%d%d%d$&#039;,														-- 5 digits without subcode (0xxxx, 60000+); accepts: 10000–59999&lt;br /&gt;
		&#039;^[^1-9]%d%d%d%.%d%d*$&#039;,												-- 4 digits with subcode (0xxx); accepts: 1000–9999&lt;br /&gt;
		&#039;^[^1-9]%d%d%d$&#039;,														-- 4 digits without subcode (0xxx); accepts: 1000–9999&lt;br /&gt;
		&#039;^%d%d%d%d%d%d+&#039;,														-- 6 or more digits&lt;br /&gt;
		&#039;^%d%d?%d?$&#039;,															-- less than 4 digits without subcode (with subcode is legitimate)&lt;br /&gt;
		&#039;^5555$&#039;,																-- test registrant will never resolve&lt;br /&gt;
		&#039;[^%d%.]&#039;,																-- any character that isn&#039;t a digit or a dot&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
	if not ignore_invalid then&lt;br /&gt;
		if registrant then														-- when DOI has proper form&lt;br /&gt;
			for i, pattern in ipairs (registrant_err_patterns) do				-- spin through error patterns&lt;br /&gt;
				if registrant:match (pattern) then								-- to validate registrant codes&lt;br /&gt;
					err_flag = set_message (&#039;err_bad_doi&#039;);						-- when found, mark this DOI as bad&lt;br /&gt;
					break;														-- and done&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			err_flag = set_message (&#039;err_bad_doi&#039;);								-- invalid directory or malformed&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		set_message (&#039;maint_doi_ignore&#039;);&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if err_flag then&lt;br /&gt;
		options.coins_list_t[&#039;DOI&#039;] = nil;										-- when error, unset so not included in COinS&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,&lt;br /&gt;
		prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = access,&lt;br /&gt;
		auto_link = not (err_flag or is_set (inactive) or ignore_invalid) and &#039;doi&#039; or nil -- do not auto-link when |doi-broken-date= has a value or when there is a DOI error or (to play it safe, after all, auto-linking is not essential) when invalid DOIs are ignored&lt;br /&gt;
		}) .. (inactive or &#039;&#039;);&lt;br /&gt;
&lt;br /&gt;
	return text;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; H D L &amp;gt;------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Formats an HDL with minor error checking.&lt;br /&gt;
&lt;br /&gt;
HDL names contain two parts: prefix and suffix separated by a forward slash.&lt;br /&gt;
	Prefix: character string using any character in the UCS-2 character set except &#039;/&#039;&lt;br /&gt;
	Suffix: character string of any length using any character in the UCS-2 character set chosen by the registrant&lt;br /&gt;
&lt;br /&gt;
This function checks a HDL name for: prefix/suffix.  If the HDL name contains spaces, endashes, or, if it ends&lt;br /&gt;
with a period or a comma, this function will emit a bad_hdl error message.&lt;br /&gt;
&lt;br /&gt;
HDL names are case-insensitive and can incorporate any printable Unicode characters so the test for endashes and&lt;br /&gt;
terminal punctuation may not be technically correct but it appears, that in practice these characters are rarely&lt;br /&gt;
if ever used in HDLs.&lt;br /&gt;
&lt;br /&gt;
Query string parameters are named here: http://www.handle.net/proxy_servlet.html.  query strings are not displayed&lt;br /&gt;
but since &#039;?&#039; is an allowed character in an HDL, &#039;?&#039; followed by one of the query parameters is the only way we&lt;br /&gt;
have to detect the query string so that it isn&#039;t URL-encoded with the rest of the identifier.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function hdl (options)&lt;br /&gt;
	local id = options.id;&lt;br /&gt;
	local access = options.access;&lt;br /&gt;
	local handler = options.handler;&lt;br /&gt;
	local query_params = {														-- list of known query parameters from http://www.handle.net/proxy_servlet.html&lt;br /&gt;
		&#039;noredirect&#039;,&lt;br /&gt;
		&#039;ignore_aliases&#039;,&lt;br /&gt;
		&#039;auth&#039;,&lt;br /&gt;
		&#039;cert&#039;,&lt;br /&gt;
		&#039;index&#039;,&lt;br /&gt;
		&#039;type&#039;,&lt;br /&gt;
		&#039;urlappend&#039;,&lt;br /&gt;
		&#039;locatt&#039;,&lt;br /&gt;
		&#039;action&#039;,&lt;br /&gt;
		}&lt;br /&gt;
	&lt;br /&gt;
	local hdl, suffix, param = id:match (&#039;(.-)(%?(%a+).+)$&#039;);					-- look for query string&lt;br /&gt;
	local found;&lt;br /&gt;
&lt;br /&gt;
	if hdl then																	-- when there are query strings, this is the handle identifier portion&lt;br /&gt;
		for _, q in ipairs (query_params) do									-- spin through the list of query parameters&lt;br /&gt;
			if param:match (&#039;^&#039; .. q) then										-- if the query string begins with one of the parameters&lt;br /&gt;
				found = true;													-- announce a find&lt;br /&gt;
				break;															-- and stop looking&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if found then&lt;br /&gt;
		id = hdl;																-- found so replace id with the handle portion; this will be URL-encoded, suffix will not&lt;br /&gt;
	else&lt;br /&gt;
		suffix = &#039;&#039;;															-- make sure suffix is empty string for concatenation else&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,&lt;br /&gt;
			prefix = handler.prefix, id = id, suffix = suffix, separator = handler.separator, encode = handler.encode, access = access})&lt;br /&gt;
&lt;br /&gt;
	if nil == id:match(&amp;quot;^[^%s–]-/[^%s–]-[^%.,]$&amp;quot;) then							-- HDL must contain a forward slash, must not contain spaces, endashes, and must not end with period or comma&lt;br /&gt;
		set_message (&#039;err_bad_hdl&#039; );&lt;br /&gt;
		options.coins_list_t[&#039;HDL&#039;] = nil;										-- when error, unset so not included in COinS&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return text;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; I S B N &amp;gt;----------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Determines whether an ISBN string is valid&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function isbn (options)&lt;br /&gt;
	local isbn_str = options.id;&lt;br /&gt;
	local ignore_invalid = options.accept;&lt;br /&gt;
	local handler = options.handler;&lt;br /&gt;
&lt;br /&gt;
	local function return_result (check, err_type)								-- local function to handle the various returns&lt;br /&gt;
		local ISBN = internal_link_id ({link = handler.link, label = handler.label, redirect = handler.redirect,&lt;br /&gt;
						prefix = handler.prefix, id = isbn_str, separator = handler.separator});&lt;br /&gt;
		if ignore_invalid then													-- if ignoring ISBN errors&lt;br /&gt;
			set_message (&#039;maint_isbn_ignore&#039;);									-- add a maint category even when there is no error&lt;br /&gt;
		else																	-- here when not ignoring&lt;br /&gt;
			if not check then													-- and there is an error&lt;br /&gt;
				options.coins_list_t[&#039;ISBN&#039;] = nil;								-- when error, unset so not included in COinS&lt;br /&gt;
				set_message (&#039;err_bad_isbn&#039;, err_type);							-- set an error message&lt;br /&gt;
				return ISBN;										 			-- return id text&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		return ISBN;															-- return id text&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if nil ~= isbn_str:match (&#039;[^%s-0-9X]&#039;) then&lt;br /&gt;
		return return_result (false, cfg.err_msg_supl.char);					-- fail if isbn_str contains anything but digits, hyphens, or the uppercase X&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local id = isbn_str:gsub (&#039;[%s-]&#039;, &#039;&#039;);										-- remove hyphens and whitespace&lt;br /&gt;
&lt;br /&gt;
	local len = id:len();&lt;br /&gt;
 &lt;br /&gt;
	if len ~= 10 and len ~= 13 then&lt;br /&gt;
		return return_result (false, cfg.err_msg_supl.length);					-- fail if incorrect length&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if len == 10 then&lt;br /&gt;
		if id:match (&#039;^%d*X?$&#039;) == nil then										-- fail if isbn_str has &#039;X&#039; anywhere but last position&lt;br /&gt;
			return return_result (false, cfg.err_msg_supl.form);									&lt;br /&gt;
		end&lt;br /&gt;
		if not is_valid_isxn (id, 10) then										-- test isbn-10 for numerical validity&lt;br /&gt;
			return return_result (false, cfg.err_msg_supl.check);				-- fail if isbn-10 is not numerically valid&lt;br /&gt;
		end&lt;br /&gt;
		if id:find (&#039;^63[01]&#039;) then												-- 630xxxxxxx and 631xxxxxxx are (apparently) not valid isbn group ids but are used by amazon as numeric identifiers (asin)&lt;br /&gt;
			return return_result (false, cfg.err_msg_supl.group);				-- fail if isbn-10 begins with 630/1&lt;br /&gt;
		end&lt;br /&gt;
		return return_result (true, cfg.err_msg_supl.check);					-- pass if isbn-10 is numerically valid&lt;br /&gt;
	else&lt;br /&gt;
		if id:match (&#039;^%d+$&#039;) == nil then&lt;br /&gt;
			return return_result (false, cfg.err_msg_supl.char);				-- fail if ISBN-13 is not all digits&lt;br /&gt;
		end&lt;br /&gt;
		if id:match (&#039;^97[89]%d*$&#039;) == nil then&lt;br /&gt;
			return return_result (false, cfg.err_msg_supl.prefix);				-- fail when ISBN-13 does not begin with 978 or 979&lt;br /&gt;
		end&lt;br /&gt;
		if id:match (&#039;^9790&#039;) then&lt;br /&gt;
			return return_result (false, cfg.err_msg_supl.group);				-- group identifier &#039;0&#039; is reserved to ISMN&lt;br /&gt;
		end&lt;br /&gt;
		return return_result (is_valid_isxn_13 (id), cfg.err_msg_supl.check);&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; A S I N &amp;gt;----------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Formats a link to Amazon.  Do simple error checking: ASIN must be mix of 10 numeric or uppercase alpha&lt;br /&gt;
characters.  If a mix, first character must be uppercase alpha; if all numeric, ASINs must be 10-digit&lt;br /&gt;
ISBN. If 10-digit ISBN, add a maintenance category so a bot or AWB script can replace |asin= with |isbn=.&lt;br /&gt;
Error message if not 10 characters, if not ISBN-10, if mixed and first character is a digit.&lt;br /&gt;
&lt;br /&gt;
|asin=630....... and |asin=631....... are (apparently) not a legitimate ISBN though it checksums as one; these&lt;br /&gt;
do not cause this function to emit the maint_asin message&lt;br /&gt;
&lt;br /&gt;
This function is positioned here because it calls isbn()&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function asin (options)&lt;br /&gt;
	local id = options.id;&lt;br /&gt;
	local domain = options.ASINTLD;&lt;br /&gt;
	&lt;br /&gt;
	local err_flag;&lt;br /&gt;
&lt;br /&gt;
	if not id:match(&amp;quot;^[%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u]$&amp;quot;) then&lt;br /&gt;
		err_flag = set_message (&#039;err_bad_asin&#039;);								-- ASIN is not a mix of 10 uppercase alpha and numeric characters&lt;br /&gt;
	else&lt;br /&gt;
		if id:match(&amp;quot;^%d%d%d%d%d%d%d%d%d[%dX]$&amp;quot;) then							-- if 10-digit numeric (or 9 digits with terminal X)&lt;br /&gt;
			if is_valid_isxn (id, 10) then										-- see if ASIN value is or validates as ISBN-10&lt;br /&gt;
				if not id:find (&#039;^63[01]&#039;) then									-- 630xxxxxxx and 631xxxxxxx are (apparently) not a valid isbn prefixes but are used by amazon as a numeric identifier&lt;br /&gt;
					err_flag = set_message (&#039;err_bad_asin&#039;);					-- ASIN has ISBN-10 form but begins with something other than 630/1 so probably an isbn &lt;br /&gt;
				end&lt;br /&gt;
			elseif not is_set (err_flag) then&lt;br /&gt;
				err_flag = set_message (&#039;err_bad_asin&#039;);						-- ASIN is not ISBN-10&lt;br /&gt;
			end&lt;br /&gt;
		elseif not id:match(&amp;quot;^%u[%d%u]+$&amp;quot;) then&lt;br /&gt;
			err_flag = set_message (&#039;err_bad_asin&#039;);							-- asin doesn&#039;t begin with uppercase alpha&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if (not is_set (domain)) or in_array (domain, {&#039;us&#039;}) then					-- default: United States&lt;br /&gt;
		domain = &amp;quot;com&amp;quot;;&lt;br /&gt;
	elseif in_array (domain, {&#039;jp&#039;, &#039;uk&#039;}) then									-- Japan, United Kingdom&lt;br /&gt;
		domain = &amp;quot;co.&amp;quot; .. domain;&lt;br /&gt;
	elseif in_array (domain, {&#039;z.cn&#039;}) then 									-- China&lt;br /&gt;
		domain = &amp;quot;cn&amp;quot;;&lt;br /&gt;
	elseif in_array (domain, {&#039;au&#039;, &#039;br&#039;, &#039;mx&#039;, &#039;sg&#039;, &#039;tr&#039;}) then				-- Australia, Brazil, Mexico, Singapore, Turkey&lt;br /&gt;
		domain = &amp;quot;com.&amp;quot; .. domain;&lt;br /&gt;
	elseif not in_array (domain, {&#039;ae&#039;, &#039;ca&#039;, &#039;cn&#039;, &#039;de&#039;, &#039;es&#039;, &#039;fr&#039;, &#039;in&#039;, &#039;it&#039;, &#039;nl&#039;, &#039;pl&#039;, &#039;sa&#039;, &#039;se&#039;, &#039;co.jp&#039;, &#039;co.uk&#039;, &#039;com&#039;, &#039;com.au&#039;, &#039;com.br&#039;, &#039;com.mx&#039;, &#039;com.sg&#039;, &#039;com.tr&#039;}) then -- Arabic Emirates, Canada, China, Germany, Spain, France, Indonesia, Italy, Netherlands, Poland, Saudi Arabia, Sweden (as of 2021-03 Austria (.at), Liechtenstein (.li) and Switzerland (.ch) still redirect to the German site (.de) with special settings, so don&#039;t maintain local ASINs for them)&lt;br /&gt;
		err_flag = set_message (&#039;err_bad_asin_tld&#039;);							-- unsupported asin-tld value&lt;br /&gt;
	end&lt;br /&gt;
	local handler = options.handler;&lt;br /&gt;
&lt;br /&gt;
	if not is_set (err_flag) then&lt;br /&gt;
		options.coins_list_t[&#039;ASIN&#039;] = handler.prefix .. domain .. &amp;quot;/dp/&amp;quot; .. id;	-- asin for coins&lt;br /&gt;
	else&lt;br /&gt;
		options.coins_list_t[&#039;ASIN&#039;] = nil;										-- when error, unset so not included in COinS&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,&lt;br /&gt;
		prefix = handler.prefix .. domain .. &amp;quot;/dp/&amp;quot;,&lt;br /&gt;
		id = id, encode = handler.encode, separator = handler.separator})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; I S M N &amp;gt;----------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Determines whether an ISMN string is valid.  Similar to ISBN-13, ISMN is 13 digits beginning 979-0-... and uses the&lt;br /&gt;
same check digit calculations.  See http://www.ismn-international.org/download/Web_ISMN_Users_Manual_2008-6.pdf&lt;br /&gt;
section 2, pages 9–12.&lt;br /&gt;
&lt;br /&gt;
ismn value not made part of COinS metadata because we don&#039;t have a url or isn&#039;t a COinS-defined identifier (rft.xxx)&lt;br /&gt;
or an identifier registered at info-uri.info (info:)&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function ismn (options)&lt;br /&gt;
	local id = options.id;&lt;br /&gt;
	local handler = options.handler;&lt;br /&gt;
	local text;&lt;br /&gt;
	local valid_ismn = true;&lt;br /&gt;
	local id_copy;&lt;br /&gt;
&lt;br /&gt;
	id_copy = id;																-- save a copy because this testing is destructive&lt;br /&gt;
	id = id:gsub (&#039;[%s-]&#039;, &#039;&#039;);													-- remove hyphens and white space&lt;br /&gt;
&lt;br /&gt;
	if 13 ~= id:len() or id:match (&amp;quot;^9790%d*$&amp;quot; ) == nil then					-- ISMN must be 13 digits and begin with 9790&lt;br /&gt;
		valid_ismn = false;&lt;br /&gt;
	else&lt;br /&gt;
		valid_ismn=is_valid_isxn_13 (id);										-- validate ISMN&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	--	text = internal_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,		-- use this (or external version) when there is some place to link to&lt;br /&gt;
	--		prefix = handler.prefix, id = id_copy, separator = handler.separator, encode = handler.encode})&lt;br /&gt;
&lt;br /&gt;
	text = table.concat (														-- because no place to link to yet&lt;br /&gt;
		{&lt;br /&gt;
		make_wikilink (link_label_make (handler), handler.label),&lt;br /&gt;
		handler.separator,&lt;br /&gt;
		id_copy&lt;br /&gt;
		});&lt;br /&gt;
&lt;br /&gt;
	if false == valid_ismn then&lt;br /&gt;
		options.coins_list_t[&#039;ISMN&#039;] = nil;										-- when error, unset so not included in COinS; not really necessary here because ismn not made part of COinS&lt;br /&gt;
		set_message (&#039;err_bad_ismn&#039;);											-- create an error message if the ISMN is invalid&lt;br /&gt;
	end &lt;br /&gt;
	&lt;br /&gt;
	return text;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; I S S N &amp;gt;----------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Validate and format an ISSN.  This code fixes the case where an editor has included an ISSN in the citation but&lt;br /&gt;
has separated the two groups of four digits with a space.  When that condition occurred, the resulting link looked&lt;br /&gt;
like this:&lt;br /&gt;
&lt;br /&gt;
	|issn=0819 4327 gives: [http://www.worldcat.org/issn/0819 4327 0819 4327]	-- can&#039;t have spaces in an external link&lt;br /&gt;
	&lt;br /&gt;
This code now prevents that by inserting a hyphen at the ISSN midpoint.  It also validates the ISSN for length&lt;br /&gt;
and makes sure that the checkdigit agrees with the calculated value.  Incorrect length (8 digits), characters&lt;br /&gt;
other than 0-9 and X, or checkdigit / calculated value mismatch will all cause a check ISSN error message.  The&lt;br /&gt;
ISSN is always displayed with a hyphen, even if the ISSN was given as a single group of 8 digits.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function issn (options)&lt;br /&gt;
	local id = options.id;&lt;br /&gt;
	local handler = options.handler;&lt;br /&gt;
	local ignore_invalid = options.accept;&lt;br /&gt;
&lt;br /&gt;
	local issn_copy = id;														-- save a copy of unadulterated ISSN; use this version for display if ISSN does not validate&lt;br /&gt;
	local text;&lt;br /&gt;
	local valid_issn = true;&lt;br /&gt;
&lt;br /&gt;
	id = id:gsub (&#039;[%s-]&#039;, &#039;&#039;);													-- remove hyphens and whitespace&lt;br /&gt;
&lt;br /&gt;
	if 8 ~= id:len() or nil == id:match (&amp;quot;^%d*X?$&amp;quot; ) then						-- validate the ISSN: 8 digits long, containing only 0-9 or X in the last position&lt;br /&gt;
		valid_issn = false;														-- wrong length or improper character&lt;br /&gt;
	else&lt;br /&gt;
		valid_issn = is_valid_isxn (id, 8);										-- validate ISSN&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if true == valid_issn then&lt;br /&gt;
		id = string.sub (id, 1, 4 ) .. &amp;quot;-&amp;quot; .. string.sub (id, 5 );				-- if valid, display correctly formatted version&lt;br /&gt;
	else&lt;br /&gt;
		id = issn_copy;															-- if not valid, show the invalid ISSN with error message&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,&lt;br /&gt;
		prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode})&lt;br /&gt;
&lt;br /&gt;
	if ignore_invalid then&lt;br /&gt;
		set_message (&#039;maint_issn_ignore&#039;);&lt;br /&gt;
	else&lt;br /&gt;
		if false == valid_issn then&lt;br /&gt;
			options.coins_list_t[&#039;ISSN&#039;] = nil;									-- when error, unset so not included in COinS&lt;br /&gt;
			set_message (&#039;err_bad_issn&#039;, (options.hkey == &#039;EISSN&#039;) and &#039;e&#039; or &#039;&#039;);	-- create an error message if the ISSN is invalid&lt;br /&gt;
		end &lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return text;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; J F M &amp;gt;-----------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
A numerical identifier in the form nn.nnnn.nn&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function jfm (options)&lt;br /&gt;
	local id = options.id;&lt;br /&gt;
	local handler = options.handler;&lt;br /&gt;
	local id_num;&lt;br /&gt;
&lt;br /&gt;
	id_num = id:match (&#039;^[Jj][Ff][Mm](.*)$&#039;);									-- identifier with jfm prefix; extract identifier&lt;br /&gt;
&lt;br /&gt;
	if is_set (id_num) then&lt;br /&gt;
		set_message (&#039;maint_jfm_format&#039;);&lt;br /&gt;
	else																		-- plain number without JFM prefix&lt;br /&gt;
		id_num = id;															-- if here id does not have prefix&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if id_num and id_num:match(&#039;^%d%d%.%d%d%d%d%.%d%d$&#039;) then&lt;br /&gt;
		id = id_num;															-- jfm matches pattern&lt;br /&gt;
	else&lt;br /&gt;
		set_message (&#039;err_bad_jfm&#039; );											-- set an error message&lt;br /&gt;
		options.coins_list_t[&#039;JFM&#039;] = nil;										-- when error, unset so not included in COinS&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,&lt;br /&gt;
			prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode});&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; J S T O R &amp;gt;--------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Format a JSTOR with some error checking&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function jstor (options)&lt;br /&gt;
	local id = options.id;&lt;br /&gt;
	local access = options.access;&lt;br /&gt;
	local handler = options.handler;&lt;br /&gt;
&lt;br /&gt;
	if id:find (&#039;[Jj][Ss][Tt][Oo][Rr]&#039;) or id:find (&#039;^https?://&#039;) or id:find (&#039;%s&#039;) then&lt;br /&gt;
		set_message (&#039;err_bad_jstor&#039;);											-- set an error message&lt;br /&gt;
		options.coins_list_t[&#039;JSTOR&#039;] = nil;									-- when error, unset so not included in COinS&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,&lt;br /&gt;
		prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = access});&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; L C C N &amp;gt;----------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Format LCCN link and do simple error checking.  LCCN is a character string 8-12 characters long. The length of&lt;br /&gt;
the LCCN dictates the character type of the first 1-3 characters; the rightmost eight are always digits.&lt;br /&gt;
http://info-uri.info/registry/OAIHandler?verb=GetRecord&amp;amp;metadataPrefix=reg&amp;amp;identifier=info:lccn/&lt;br /&gt;
&lt;br /&gt;
length = 8 then all digits&lt;br /&gt;
length = 9 then lccn[1] is lowercase alpha&lt;br /&gt;
length = 10 then lccn[1] and lccn[2] are both lowercase alpha or both digits&lt;br /&gt;
length = 11 then lccn[1] is lower case alpha, lccn[2] and lccn[3] are both lowercase alpha or both digits&lt;br /&gt;
length = 12 then lccn[1] and lccn[2] are both lowercase alpha&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function lccn (options)&lt;br /&gt;
	local lccn = options.id;&lt;br /&gt;
	local handler = options.handler;&lt;br /&gt;
	local err_flag;																-- presume that LCCN is valid&lt;br /&gt;
	local id = lccn;															-- local copy of the LCCN&lt;br /&gt;
&lt;br /&gt;
	id = normalize_lccn (id);													-- get canonical form (no whitespace, hyphens, forward slashes)&lt;br /&gt;
	local len = id:len();														-- get the length of the LCCN&lt;br /&gt;
&lt;br /&gt;
	if 8 == len then&lt;br /&gt;
		if id:match(&amp;quot;[^%d]&amp;quot;) then												-- if LCCN has anything but digits (nil if only digits)&lt;br /&gt;
			err_flag = set_message (&#039;err_bad_lccn&#039;);							-- set an error message&lt;br /&gt;
		end&lt;br /&gt;
	elseif 9 == len then														-- LCCN should be adddddddd&lt;br /&gt;
		if nil == id:match(&amp;quot;%l%d%d%d%d%d%d%d%d&amp;quot;) then							-- does it match our pattern?&lt;br /&gt;
			err_flag = set_message (&#039;err_bad_lccn&#039;);							-- set an error message&lt;br /&gt;
		end&lt;br /&gt;
	elseif 10 == len then														-- LCCN should be aadddddddd or dddddddddd&lt;br /&gt;
		if id:match(&amp;quot;[^%d]&amp;quot;) then												-- if LCCN has anything but digits (nil if only digits) ...&lt;br /&gt;
			if nil == id:match(&amp;quot;^%l%l%d%d%d%d%d%d%d%d&amp;quot;) then					-- ... see if it matches our pattern&lt;br /&gt;
				err_flag = set_message (&#039;err_bad_lccn&#039;);						-- no match, set an error message&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	elseif 11 == len then														-- LCCN should be aaadddddddd or adddddddddd&lt;br /&gt;
		if not (id:match(&amp;quot;^%l%l%l%d%d%d%d%d%d%d%d&amp;quot;) or id:match(&amp;quot;^%l%d%d%d%d%d%d%d%d%d%d&amp;quot;)) then	-- see if it matches one of our patterns&lt;br /&gt;
			err_flag = set_message (&#039;err_bad_lccn&#039;);							-- no match, set an error message&lt;br /&gt;
		end&lt;br /&gt;
	elseif 12 == len then														-- LCCN should be aadddddddddd&lt;br /&gt;
		if not id:match(&amp;quot;^%l%l%d%d%d%d%d%d%d%d%d%d&amp;quot;) then						-- see if it matches our pattern&lt;br /&gt;
			err_flag = set_message (&#039;err_bad_lccn&#039;);							-- no match, set an error message&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		err_flag = set_message (&#039;err_bad_lccn&#039;);								-- wrong length, set an error message&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if not is_set (err_flag) and nil ~= lccn:find (&#039;%s&#039;) then&lt;br /&gt;
		err_flag = set_message (&#039;err_bad_lccn&#039;);								-- lccn contains a space, set an error message&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if is_set (err_flag) then&lt;br /&gt;
		options.coins_list_t[&#039;LCCN&#039;] = nil;										-- when error, unset so not included in COinS&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,&lt;br /&gt;
			prefix = handler.prefix, id = lccn, separator = handler.separator, encode = handler.encode});&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; M R &amp;gt;--------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
A seven digit number; if not seven digits, zero-fill leading digits to make seven digits.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function mr (options)&lt;br /&gt;
	local id = options.id;&lt;br /&gt;
	local handler = options.handler;&lt;br /&gt;
	local id_num;&lt;br /&gt;
	local id_len;&lt;br /&gt;
&lt;br /&gt;
	id_num = id:match (&#039;^[Mm][Rr](%d+)$&#039;);										-- identifier with mr prefix&lt;br /&gt;
&lt;br /&gt;
	if is_set (id_num) then&lt;br /&gt;
		set_message (&#039;maint_mr_format&#039;);										-- add maint cat&lt;br /&gt;
	else																		-- plain number without mr prefix&lt;br /&gt;
		id_num = id:match (&#039;^%d+$&#039;);											-- if here id is all digits&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	id_len = id_num and id_num:len() or 0;&lt;br /&gt;
	if (7 &amp;gt;= id_len) and (0 ~= id_len) then&lt;br /&gt;
		id = string.rep (&#039;0&#039;, 7-id_len) .. id_num;								-- zero-fill leading digits&lt;br /&gt;
	else&lt;br /&gt;
		set_message (&#039;err_bad_mr&#039;);												-- set an error message&lt;br /&gt;
		options.coins_list_t[&#039;MR&#039;] = nil;										-- when error, unset so not included in COinS&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,&lt;br /&gt;
			prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode});&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; O C L C &amp;gt;----------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Validate and format an OCLC ID.  https://www.oclc.org/batchload/controlnumber.en.html {{dead link}}&lt;br /&gt;
archived at: https://web.archive.org/web/20161228233804/https://www.oclc.org/batchload/controlnumber.en.html&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function oclc (options)&lt;br /&gt;
	local id = options.id;&lt;br /&gt;
	local handler = options.handler;&lt;br /&gt;
	local number;&lt;br /&gt;
&lt;br /&gt;
	if id:match(&#039;^ocm%d%d%d%d%d%d%d%d$&#039;) then									-- ocm prefix and 8 digits; 001 field (12 characters)&lt;br /&gt;
		number = id:match(&#039;ocm(%d+)&#039;);											-- get the number&lt;br /&gt;
	elseif id:match(&#039;^ocn%d%d%d%d%d%d%d%d%d$&#039;) then								-- ocn prefix and 9 digits; 001 field (12 characters)&lt;br /&gt;
		number = id:match(&#039;ocn(%d+)&#039;);											-- get the number&lt;br /&gt;
	elseif id:match(&#039;^on%d%d%d%d%d%d%d%d%d%d+$&#039;) then							-- on prefix and 10 or more digits; 001 field (12 characters)&lt;br /&gt;
		number = id:match(&#039;^on(%d%d%d%d%d%d%d%d%d%d+)$&#039;);						-- get the number&lt;br /&gt;
	elseif id:match(&#039;^%(OCoLC%)[1-9]%d*$&#039;) then									-- (OCoLC) prefix and variable number digits; no leading zeros; 035 field&lt;br /&gt;
		number = id:match(&#039;%(OCoLC%)([1-9]%d*)&#039;);								-- get the number&lt;br /&gt;
		if 9 &amp;lt; number:len() then&lt;br /&gt;
			number = nil;														-- constrain to 1 to 9 digits; change this when OCLC issues 10-digit numbers&lt;br /&gt;
		end&lt;br /&gt;
	elseif id:match(&#039;^%d+$&#039;) then												-- no prefix&lt;br /&gt;
		number = id;															-- get the number&lt;br /&gt;
		if 10 &amp;lt; number:len() then&lt;br /&gt;
			number = nil;														-- constrain to 1 to 10 digits; change this when OCLC issues 11-digit numbers&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if number then																-- proper format&lt;br /&gt;
		id = number;															-- exclude prefix, if any, from external link&lt;br /&gt;
	else&lt;br /&gt;
		set_message (&#039;err_bad_oclc&#039;)											-- add an error message if the id is malformed&lt;br /&gt;
		options.coins_list_t[&#039;OCLC&#039;] = nil;										-- when error, unset so not included in COinS&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,&lt;br /&gt;
		prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode});&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; O P E N L I B R A R Y &amp;gt;--------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Formats an OpenLibrary link, and checks for associated errors.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function openlibrary (options)&lt;br /&gt;
	local id = options.id;&lt;br /&gt;
	local access = options.access;&lt;br /&gt;
	local handler = options.handler;&lt;br /&gt;
	local ident, code = id:gsub(&#039;^OL&#039;, &#039;&#039;):match(&amp;quot;^(%d+([AMW]))$&amp;quot;);				-- strip optional OL prefix followed immediately by digits followed by &#039;A&#039;, &#039;M&#039;, or &#039;W&#039;;&lt;br /&gt;
	local err_flag;&lt;br /&gt;
	local prefix = {															-- these are appended to the handler.prefix according to code&lt;br /&gt;
		[&#039;A&#039;]=&#039;authors/OL&#039;,&lt;br /&gt;
		[&#039;M&#039;]=&#039;books/OL&#039;,&lt;br /&gt;
		[&#039;W&#039;]=&#039;works/OL&#039;,&lt;br /&gt;
		[&#039;X&#039;]=&#039;OL&#039;																-- not a code; spoof when &#039;code&#039; in id is invalid&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
	if not ident then&lt;br /&gt;
		code = &#039;X&#039;;																-- no code or id completely invalid&lt;br /&gt;
		ident = id;																-- copy id to ident so that we display the flawed identifier&lt;br /&gt;
		err_flag = set_message (&#039;err_bad_ol&#039;);&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if not is_set (err_flag) then&lt;br /&gt;
		options.coins_list_t[&#039;OL&#039;] = handler.prefix .. prefix[code] .. ident;	-- experiment for ol coins&lt;br /&gt;
	else&lt;br /&gt;
		options.coins_list_t[&#039;OL&#039;] = nil;										-- when error, unset so not included in COinS&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,&lt;br /&gt;
		prefix = handler.prefix .. prefix[code],&lt;br /&gt;
		id = ident, separator = handler.separator, encode = handler.encode,&lt;br /&gt;
		access = access});&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; O S T I &amp;gt;----------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Format OSTI and do simple error checking. OSTIs are sequential numbers beginning at 1 and counting up.  This&lt;br /&gt;
code checks the OSTI to see that it contains only digits and is less than test_limit specified in the configuration;&lt;br /&gt;
the value in test_limit will need to be updated periodically as more OSTIs are issued.&lt;br /&gt;
&lt;br /&gt;
NB. 1018 is the lowest OSTI number found in the wild (so far) and resolving OK on the OSTI site&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function osti (options)&lt;br /&gt;
	local id = options.id;&lt;br /&gt;
	local access = options.access;&lt;br /&gt;
	local handler = options.handler;&lt;br /&gt;
&lt;br /&gt;
	if id:match(&amp;quot;[^%d]&amp;quot;) then													-- if OSTI has anything but digits&lt;br /&gt;
		set_message (&#039;err_bad_osti&#039;);											-- set an error message&lt;br /&gt;
		options.coins_list_t[&#039;OSTI&#039;] = nil;										-- when error, unset so not included in COinS&lt;br /&gt;
	else																		-- OSTI is only digits&lt;br /&gt;
		local id_num = tonumber (id);											-- convert id to a number for range testing&lt;br /&gt;
		if 1018 &amp;gt; id_num or handler.id_limit &amp;lt; id_num then						-- if OSTI is outside test limit boundaries&lt;br /&gt;
			set_message (&#039;err_bad_osti&#039;);										-- set an error message&lt;br /&gt;
			options.coins_list_t[&#039;OSTI&#039;] = nil;									-- when error, unset so not included in COinS&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,&lt;br /&gt;
			prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = access});&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; P M C &amp;gt;------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Format a PMC, do simple error checking, and check for embargoed articles.&lt;br /&gt;
&lt;br /&gt;
The embargo parameter takes a date for a value. If the embargo date is in the future the PMC identifier will not&lt;br /&gt;
be linked to the article.  If the embargo date is today or in the past, or if it is empty or omitted, then the&lt;br /&gt;
PMC identifier is linked to the article through the link at cfg.id_handlers[&#039;PMC&#039;].prefix.&lt;br /&gt;
&lt;br /&gt;
PMC embargo date testing is done in function is_embargoed () which is called earlier because when the citation&lt;br /&gt;
has |pmc=&amp;lt;value&amp;gt; but does not have a |url= then |title= is linked with the PMC link.  Function is_embargoed ()&lt;br /&gt;
returns the embargo date if the PMC article is still embargoed, otherwise it returns an empty string.&lt;br /&gt;
&lt;br /&gt;
PMCs are sequential numbers beginning at 1 and counting up.  This code checks the PMC to see that it contains only digits and is less&lt;br /&gt;
than test_limit; the value in local variable test_limit will need to be updated periodically as more PMCs are issued.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function pmc (options)&lt;br /&gt;
	local id = options.id;&lt;br /&gt;
	local embargo = options.Embargo;											-- TODO: lowercase?&lt;br /&gt;
	local handler = options.handler;&lt;br /&gt;
	local err_flag;&lt;br /&gt;
	local id_num;&lt;br /&gt;
	local text;&lt;br /&gt;
&lt;br /&gt;
	id_num = id:match (&#039;^[Pp][Mm][Cc](%d+)$&#039;);									-- identifier with PMC prefix&lt;br /&gt;
&lt;br /&gt;
	if is_set (id_num) then&lt;br /&gt;
		set_message (&#039;maint_pmc_format&#039;);&lt;br /&gt;
	else																		-- plain number without PMC prefix&lt;br /&gt;
		id_num = id:match (&#039;^%d+$&#039;);											-- if here id is all digits&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if is_set (id_num) then														-- id_num has a value so test it&lt;br /&gt;
		id_num = tonumber (id_num);												-- convert id_num to a number for range testing&lt;br /&gt;
		if 1 &amp;gt; id_num or handler.id_limit &amp;lt; id_num then							-- if PMC is outside test limit boundaries&lt;br /&gt;
			err_flag = set_message (&#039;err_bad_pmc&#039;);								-- set an error message&lt;br /&gt;
		else&lt;br /&gt;
			id = tostring (id_num);												-- make sure id is a string&lt;br /&gt;
		end&lt;br /&gt;
	else																		-- when id format incorrect&lt;br /&gt;
		err_flag = set_message (&#039;err_bad_pmc&#039;);									-- set an error message&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if is_set (embargo) and is_set (is_embargoed (embargo)) then				-- is PMC is still embargoed?&lt;br /&gt;
		text = table.concat (													-- still embargoed so no external link&lt;br /&gt;
			{&lt;br /&gt;
			make_wikilink (link_label_make (handler), handler.label),&lt;br /&gt;
			handler.separator,&lt;br /&gt;
			id,&lt;br /&gt;
			});&lt;br /&gt;
	else&lt;br /&gt;
		text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,	-- no embargo date or embargo has expired, ok to link to article&lt;br /&gt;
			prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = handler.access,&lt;br /&gt;
			auto_link = not err_flag and &#039;pmc&#039; or nil							-- do not auto-link when PMC has error&lt;br /&gt;
			});&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if err_flag then&lt;br /&gt;
		options.coins_list_t[&#039;PMC&#039;] = nil;										-- when error, unset so not included in COinS&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return text;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; P M I D &amp;gt;----------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Format PMID and do simple error checking.  PMIDs are sequential numbers beginning at 1 and counting up.  This&lt;br /&gt;
code checks the PMID to see that it contains only digits and is less than test_limit; the value in local variable&lt;br /&gt;
test_limit will need to be updated periodically as more PMIDs are issued.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function pmid (options)&lt;br /&gt;
	local id = options.id;&lt;br /&gt;
	local handler = options.handler;&lt;br /&gt;
&lt;br /&gt;
	if id:match(&amp;quot;[^%d]&amp;quot;) then													-- if PMID has anything but digits&lt;br /&gt;
		set_message (&#039;err_bad_pmid&#039;);											-- set an error message&lt;br /&gt;
		options.coins_list_t[&#039;PMID&#039;] = nil;										-- when error, unset so not included in COinS&lt;br /&gt;
	else																		-- PMID is only digits&lt;br /&gt;
		local id_num = tonumber (id);											-- convert id to a number for range testing&lt;br /&gt;
		if 1 &amp;gt; id_num or handler.id_limit &amp;lt; id_num then							-- if PMID is outside test limit boundaries&lt;br /&gt;
			set_message (&#039;err_bad_pmid&#039;);										-- set an error message&lt;br /&gt;
			options.coins_list_t[&#039;PMID&#039;] = nil;									-- when error, unset so not included in COinS&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,&lt;br /&gt;
			prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode});&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; R F C &amp;gt;------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Format RFC and do simple error checking. RFCs are sequential numbers beginning at 1 and counting up.  This&lt;br /&gt;
code checks the RFC to see that it contains only digits and is less than test_limit specified in the configuration;&lt;br /&gt;
the value in test_limit will need to be updated periodically as more RFCs are issued.&lt;br /&gt;
&lt;br /&gt;
An index of all RFCs is here: https://tools.ietf.org/rfc/&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function rfc (options)&lt;br /&gt;
	local id = options.id;&lt;br /&gt;
	local handler = options.handler;&lt;br /&gt;
&lt;br /&gt;
	if id:match(&amp;quot;[^%d]&amp;quot;) then													-- if RFC has anything but digits&lt;br /&gt;
		set_message (&#039;err_bad_rfc&#039;);											-- set an error message&lt;br /&gt;
		options.coins_list_t[&#039;RFC&#039;] = nil;										-- when error, unset so not included in COinS&lt;br /&gt;
	else																		-- RFC is only digits&lt;br /&gt;
		local id_num = tonumber (id);											-- convert id to a number for range testing&lt;br /&gt;
		if 1 &amp;gt; id_num or handler.id_limit &amp;lt; id_num then							-- if RFC is outside test limit boundaries&lt;br /&gt;
			set_message (&#039;err_bad_rfc&#039;);										-- set an error message&lt;br /&gt;
			options.coins_list_t[&#039;RFC&#039;] = nil;									-- when error, unset so not included in COinS&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,&lt;br /&gt;
			prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = handler.access});&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S 2 C I D &amp;gt;--------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Format an S2CID, do simple error checking&lt;br /&gt;
&lt;br /&gt;
S2CIDs are sequential numbers beginning at 1 and counting up.  This code checks the S2CID to see that it is only&lt;br /&gt;
digits and is less than test_limit; the value in local variable test_limit will need to be updated periodically&lt;br /&gt;
as more S2CIDs are issued.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function s2cid (options)&lt;br /&gt;
	local id = options.id;&lt;br /&gt;
	local access = options.access;&lt;br /&gt;
	local handler = options.handler;&lt;br /&gt;
	local id_num;&lt;br /&gt;
	local text;&lt;br /&gt;
	&lt;br /&gt;
	id_num = id:match (&#039;^[1-9]%d*$&#039;);											-- id must be all digits; must not begin with 0; no open access flag&lt;br /&gt;
&lt;br /&gt;
 	if is_set (id_num) then														-- id_num has a value so test it&lt;br /&gt;
		id_num = tonumber (id_num);												-- convert id_num to a number for range testing&lt;br /&gt;
		if handler.id_limit &amp;lt; id_num then										-- if S2CID is outside test limit boundaries&lt;br /&gt;
			set_message (&#039;err_bad_s2cid&#039;);										-- set an error message&lt;br /&gt;
			options.coins_list_t[&#039;S2CID&#039;] = nil;								-- when error, unset so not included in COinS&lt;br /&gt;
		end&lt;br /&gt;
	else																		-- when id format incorrect&lt;br /&gt;
		set_message (&#039;err_bad_s2cid&#039;);											-- set an error message&lt;br /&gt;
		options.coins_list_t[&#039;S2CID&#039;] = nil;									-- when error, unset so not included in COinS&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,&lt;br /&gt;
		prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = access});&lt;br /&gt;
&lt;br /&gt;
	return text;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S B N &amp;gt;------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
9-digit form of ISBN-10; uses same check-digit validation when SBN is prefixed with an additional &#039;0&#039; to make 10 digits&lt;br /&gt;
&lt;br /&gt;
sbn value not made part of COinS metadata because we don&#039;t have a url or isn&#039;t a COinS-defined identifier (rft.xxx)&lt;br /&gt;
or an identifier registered at info-uri.info (info:)&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function sbn (options)&lt;br /&gt;
	local id = options.id;&lt;br /&gt;
	local ignore_invalid = options.accept;&lt;br /&gt;
	local handler = options.handler;&lt;br /&gt;
	local function return_result (check, err_type)								-- local function to handle the various returns&lt;br /&gt;
		local SBN = internal_link_id ({link = handler.link, label = handler.label, redirect = handler.redirect,&lt;br /&gt;
						prefix = handler.prefix, id = id, separator = handler.separator});&lt;br /&gt;
		if not ignore_invalid then												-- if not ignoring SBN errors&lt;br /&gt;
			if not check then&lt;br /&gt;
				options.coins_list_t[&#039;SBN&#039;] = nil;								-- when error, unset so not included in COinS; not really necessary here because sbn not made part of COinS&lt;br /&gt;
				set_message (&#039;err_bad_sbn&#039;, {err_type});						-- display an error message&lt;br /&gt;
				return SBN; &lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			set_message (&#039;maint_isbn_ignore&#039;);									-- add a maint category even when there is no error (ToDo: Possibly switch to separate message for SBNs only)&lt;br /&gt;
		end&lt;br /&gt;
		return SBN;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if id:match (&#039;[^%s-0-9X]&#039;) then&lt;br /&gt;
		return return_result (false, cfg.err_msg_supl.char);					-- fail if SBN contains anything but digits, hyphens, or the uppercase X&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local ident = id:gsub (&#039;[%s-]&#039;, &#039;&#039;);										-- remove hyphens and whitespace; they interfere with the rest of the tests&lt;br /&gt;
&lt;br /&gt;
	if  9 ~= ident:len() then&lt;br /&gt;
		return return_result (false, cfg.err_msg_supl.length);					-- fail if incorrect length&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if ident:match (&#039;^%d*X?$&#039;) == nil then&lt;br /&gt;
		return return_result (false, cfg.err_msg_supl.form);					-- fail if SBN has &#039;X&#039; anywhere but last position&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return return_result (is_valid_isxn (&#039;0&#039; .. ident, 10), cfg.err_msg_supl.check);&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S S R N &amp;gt;----------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Format an SSRN, do simple error checking&lt;br /&gt;
&lt;br /&gt;
SSRNs are sequential numbers beginning at 100? and counting up.  This code checks the SSRN to see that it is&lt;br /&gt;
only digits and is greater than 99 and less than test_limit; the value in local variable test_limit will need&lt;br /&gt;
to be updated periodically as more SSRNs are issued.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function ssrn (options)&lt;br /&gt;
	local id = options.id;&lt;br /&gt;
	local handler = options.handler;&lt;br /&gt;
	local id_num;&lt;br /&gt;
	local text;&lt;br /&gt;
	&lt;br /&gt;
	id_num = id:match (&#039;^%d+$&#039;);												-- id must be all digits&lt;br /&gt;
&lt;br /&gt;
	if is_set (id_num) then														-- id_num has a value so test it&lt;br /&gt;
		id_num = tonumber (id_num);												-- convert id_num to a number for range testing&lt;br /&gt;
		if 100 &amp;gt; id_num or handler.id_limit &amp;lt; id_num then						-- if SSRN is outside test limit boundaries&lt;br /&gt;
			set_message (&#039;err_bad_ssrn&#039;);										-- set an error message&lt;br /&gt;
			options.coins_list_t[&#039;SSRN&#039;] = nil;									-- when error, unset so not included in COinS&lt;br /&gt;
		end&lt;br /&gt;
	else																		-- when id format incorrect&lt;br /&gt;
		set_message (&#039;err_bad_ssrn&#039;);											-- set an error message&lt;br /&gt;
		options.coins_list_t[&#039;SSRN&#039;] = nil;										-- when error, unset so not included in COinS&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,&lt;br /&gt;
		prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode, access = options.access});&lt;br /&gt;
&lt;br /&gt;
	return text;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; U S E N E T _ I D &amp;gt;------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Validate and format a usenet message id.  Simple error checking, looks for &#039;id-left@id-right&#039; not enclosed in&lt;br /&gt;
&#039;&amp;lt;&#039; and/or &#039;&amp;gt;&#039; angle brackets.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function usenet_id (options)&lt;br /&gt;
	local id = options.id;&lt;br /&gt;
	local handler = options.handler;&lt;br /&gt;
&lt;br /&gt;
	local text = external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,&lt;br /&gt;
		prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode})&lt;br /&gt;
 &lt;br /&gt;
	if not id:match(&#039;^.+@.+$&#039;) or not id:match(&#039;^[^&amp;lt;].*[^&amp;gt;]$&#039;) then				-- doesn&#039;t have &#039;@&#039; or has one or first or last character is &#039;&amp;lt; or &#039;&amp;gt;&#039;&lt;br /&gt;
		set_message (&#039;err_bad_usenet_id&#039;)										-- add an error message if the message id is invalid&lt;br /&gt;
		options.coins_list_t[&#039;USENETID&#039;] = nil;									-- when error, unset so not included in COinS&lt;br /&gt;
	end &lt;br /&gt;
	&lt;br /&gt;
	return text;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; Z B L &amp;gt;-----------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
A numerical identifier in the form nnnn.nnnnn - leading zeros in the first quartet optional&lt;br /&gt;
&lt;br /&gt;
format described here: http://emis.mi.sanu.ac.rs/ZMATH/zmath/en/help/search/&lt;br /&gt;
&lt;br /&gt;
temporary format is apparently eight digits.  Anything else is an error&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function zbl (options)&lt;br /&gt;
	local id = options.id;&lt;br /&gt;
	local handler = options.handler;&lt;br /&gt;
&lt;br /&gt;
	if id:match(&#039;^%d%d%d%d%d%d%d%d$&#039;) then										-- is this identifier using temporary format?&lt;br /&gt;
		set_message (&#039;maint_zbl&#039;);												-- yes, add maint cat&lt;br /&gt;
	elseif not id:match(&#039;^%d?%d?%d?%d%.%d%d%d%d%d$&#039;) then						-- not temporary, is it normal format?&lt;br /&gt;
		set_message (&#039;err_bad_zbl&#039;);											-- no, set an error message&lt;br /&gt;
		options.coins_list_t[&#039;ZBL&#039;] = nil;										-- when error, unset so not included in COinS&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return external_link_id ({link = handler.link, label = handler.label, q = handler.q, redirect = handler.redirect,&lt;br /&gt;
			prefix = handler.prefix, id = id, separator = handler.separator, encode = handler.encode});&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--============================&amp;lt;&amp;lt; I N T E R F A C E   F U N C T I O N S &amp;gt;&amp;gt;==========================================&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; E X T R A C T _ I D S &amp;gt;------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Populates ID table from arguments using configuration settings. Loops through cfg.id_handlers and searches args for&lt;br /&gt;
any of the parameters listed in each cfg.id_handlers[&#039;...&#039;].parameters.  If found, adds the parameter and value to&lt;br /&gt;
the identifier list.  Emits redundant error message if more than one alias exists in args&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function extract_ids (args)&lt;br /&gt;
	local id_list = {};															-- list of identifiers found in args&lt;br /&gt;
	for k, v in pairs (cfg.id_handlers) do										-- k is uppercase identifier name as index to cfg.id_handlers; e.g. cfg.id_handlers[&#039;ISBN&#039;], v is a table&lt;br /&gt;
		v = select_one (args, v.parameters, &#039;err_redundant_parameters&#039; );		-- v.parameters is a table of aliases for k; here we pick one from args if present&lt;br /&gt;
		if is_set (v) then id_list[k] = v; end									-- if found in args, add identifier to our list&lt;br /&gt;
	end&lt;br /&gt;
	return id_list;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; E X T R A C T _ I D _ A C C E S S _ L E V E L S &amp;gt;--------------------------------------&lt;br /&gt;
&lt;br /&gt;
Fetches custom id access levels from arguments using configuration settings. Parameters which have a predefined access&lt;br /&gt;
level (e.g. arxiv) do not use this function as they are directly rendered as free without using an additional parameter.&lt;br /&gt;
&lt;br /&gt;
returns a table of k/v pairs where k is same as the identifier&#039;s key in cfg.id_handlers and v is the assigned (valid) keyword&lt;br /&gt;
&lt;br /&gt;
access-level values must match the case used in cfg.keywords_lists[&#039;id-access&#039;] (lowercase unless there is some special reason for something else)&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function extract_id_access_levels (args, id_list)&lt;br /&gt;
	local id_accesses_list = {};&lt;br /&gt;
	for k, v in pairs (cfg.id_handlers) do&lt;br /&gt;
		local access_param = v.custom_access;									-- name of identifier&#039;s access-level parameter&lt;br /&gt;
		if is_set (access_param) then&lt;br /&gt;
			local access_level = args[access_param];							-- get the assigned value if there is one&lt;br /&gt;
			if is_set (access_level) then&lt;br /&gt;
				if not in_array (access_level, cfg.keywords_lists[&#039;id-access&#039;]) then	-- exact match required&lt;br /&gt;
					set_message (&#039;err_invalid_param_val&#039;, {access_param, access_level});	&lt;br /&gt;
					access_level = nil;											-- invalid so unset&lt;br /&gt;
				end&lt;br /&gt;
				if not is_set (id_list[k]) then									-- identifier access-level must have a matching identifier&lt;br /&gt;
					set_message (&#039;err_param_access_requires_param&#039;, {k:lower()});	-- parameter name is uppercase in cfg.id_handlers (k); lowercase for error message&lt;br /&gt;
				end&lt;br /&gt;
				id_accesses_list[k] = cfg.keywords_xlate[access_level];			-- get translated keyword&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return id_accesses_list;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; B U I L D _ I D _ L I S T &amp;gt;----------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
render the identifiers into a sorted sequence table&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ID_list_coins_t&amp;gt; is a table of k/v pairs where k is same as key in cfg.id_handlers and v is the assigned value&lt;br /&gt;
&amp;lt;options_t&amp;gt; is a table of various k/v option pairs provided in the call to new_build_id_list();&lt;br /&gt;
	modified by	this function and passed to all identifier rendering functions&lt;br /&gt;
&amp;lt;access_levels_t&amp;gt; is a table of k/v pairs where k is same as key in cfg.id_handlers and v is the assigned value (if valid)&lt;br /&gt;
&lt;br /&gt;
returns a sequence table of sorted (by hkey - &#039;handler&#039; key) rendered identifier strings&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function build_id_list (ID_list_coins_t, options_t, access_levels_t)&lt;br /&gt;
	local ID_list_t = {};&lt;br /&gt;
	local accept;&lt;br /&gt;
	local func_map = {															--function map points to functions associated with hkey identifier&lt;br /&gt;
		[&#039;ARXIV&#039;] = arxiv,&lt;br /&gt;
		[&#039;ASIN&#039;] = asin,&lt;br /&gt;
		[&#039;BIBCODE&#039;] = bibcode,&lt;br /&gt;
		[&#039;BIORXIV&#039;] = biorxiv,&lt;br /&gt;
		[&#039;CITESEERX&#039;] = citeseerx,&lt;br /&gt;
		[&#039;DOI&#039;] = doi,&lt;br /&gt;
		[&#039;EISSN&#039;] = issn,&lt;br /&gt;
		[&#039;HDL&#039;] = hdl,&lt;br /&gt;
		[&#039;ISBN&#039;] = isbn,&lt;br /&gt;
		[&#039;ISMN&#039;] = ismn,&lt;br /&gt;
		[&#039;ISSN&#039;] = issn,&lt;br /&gt;
		[&#039;JFM&#039;] = jfm,&lt;br /&gt;
		[&#039;JSTOR&#039;] = jstor,&lt;br /&gt;
		[&#039;LCCN&#039;] = lccn,&lt;br /&gt;
		[&#039;MR&#039;] = mr,&lt;br /&gt;
		[&#039;OCLC&#039;] = oclc,&lt;br /&gt;
		[&#039;OL&#039;] = openlibrary,&lt;br /&gt;
		[&#039;OSTI&#039;] = osti,&lt;br /&gt;
		[&#039;PMC&#039;] = pmc,&lt;br /&gt;
		[&#039;PMID&#039;] = pmid,&lt;br /&gt;
		[&#039;RFC&#039;]  = rfc,&lt;br /&gt;
		[&#039;S2CID&#039;] = s2cid,&lt;br /&gt;
		[&#039;SBN&#039;] = sbn,&lt;br /&gt;
		[&#039;SSRN&#039;] = ssrn,&lt;br /&gt;
		[&#039;USENETID&#039;] = usenet_id,&lt;br /&gt;
		[&#039;ZBL&#039;] = zbl,&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
	for hkey, v in pairs (ID_list_coins_t) do&lt;br /&gt;
		v, accept = has_accept_as_written (v);									-- remove accept-as-written markup if present; accept is boolean true when markup removed; false else&lt;br /&gt;
																				-- every function gets the options table with value v and accept boolean&lt;br /&gt;
		options_t.hkey = hkey;													-- ~/Configuration handler key&lt;br /&gt;
		options_t.id = v;														-- add that identifier value to the options table&lt;br /&gt;
		options_t.accept = accept;												-- add the accept boolean flag&lt;br /&gt;
		options_t.access = access_levels_t[hkey];								-- add the access level for those that have an |&amp;lt;identifier-access= parameter&lt;br /&gt;
		options_t.handler = cfg.id_handlers[hkey];&lt;br /&gt;
		options_t.coins_list_t = ID_list_coins_t;								-- pointer to ID_list_coins_t; for |asin= and |ol=; also to keep erroneous values out of the citation&#039;s metadata&lt;br /&gt;
		options_t.coins_list_t[hkey] = v;										-- id value without accept-as-written markup for metadata&lt;br /&gt;
		&lt;br /&gt;
		if options_t.handler.access and not in_array (options_t.handler.access, cfg.keywords_lists[&#039;id-access&#039;]) then&lt;br /&gt;
			error (cfg.messages[&#039;unknown_ID_access&#039;] .. options_t.handler.access);	-- here when handler access key set to a value not listed in list of allowed id access keywords&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		if func_map[hkey] then&lt;br /&gt;
			local id_text = func_map[hkey] (options_t);							-- call the function to get identifier text and any error message&lt;br /&gt;
			table.insert (ID_list_t, {hkey, id_text});							-- add identifier text to the output sequence table&lt;br /&gt;
		else&lt;br /&gt;
			error (cfg.messages[&#039;unknown_ID_key&#039;] .. hkey);						-- here when func_map doesn&#039;t have a function for hkey&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local function comp (a, b)													-- used by following table.sort()&lt;br /&gt;
		return a[1]:lower() &amp;lt; b[1]:lower();										-- sort by hkey&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	table.sort (ID_list_t, comp);												-- sequence table of tables sort	&lt;br /&gt;
	for k, v in ipairs (ID_list_t) do											-- convert sequence table of tables to simple sequence table of strings&lt;br /&gt;
		ID_list_t[k] = v[2];													-- v[2] is the identifier rendering from the call to the various functions in func_map{}&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return ID_list_t;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; O P T I O N S _ C H E C K &amp;gt;----------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
check that certain option parameters have their associated identifier parameters with values&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ID_list_coins_t&amp;gt; is a table of k/v pairs where k is same as key in cfg.id_handlers and v is the assigned value&lt;br /&gt;
&amp;lt;ID_support_t&amp;gt; is a sequence table of tables created in citation0() where each subtable has four elements:&lt;br /&gt;
	[1] is the support parameter&#039;s assigned value; empty string if not set&lt;br /&gt;
	[2] is a text string same as key in cfg.id_handlers&lt;br /&gt;
	[3] is cfg.error_conditions key used to create error message&lt;br /&gt;
	[4] is original ID support parameter name used to create error message&lt;br /&gt;
	&lt;br /&gt;
returns nothing; on error emits an appropriate error message&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function options_check (ID_list_coins_t, ID_support_t)&lt;br /&gt;
	for _, v in ipairs (ID_support_t) do&lt;br /&gt;
		if is_set (v[1]) and not ID_list_coins_t[v[2]] then						-- when support parameter has a value but matching identifier parameter is missing or empty&lt;br /&gt;
			set_message (v[3], (v[4]));											-- emit the appropriate error message&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; I D E N T I F I E R _ L I S T S _ G E T &amp;gt;--------------------------------------&lt;br /&gt;
&lt;br /&gt;
Creates two identifier lists: a k/v table of identifiers and their values to be used locally and for use in the&lt;br /&gt;
COinS metadata, and a sequence table of the rendered identifier strings that will be included in the rendered&lt;br /&gt;
citation.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function identifier_lists_get (args_t, options_t, ID_support_t)&lt;br /&gt;
	local ID_list_coins_t = extract_ids (args_t);										-- get a table of identifiers and their values for use locally and for use in COinS&lt;br /&gt;
	options_check (ID_list_coins_t, ID_support_t);										-- ID support parameters must have matching identifier parameters &lt;br /&gt;
	local ID_access_levels_t = extract_id_access_levels (args_t, ID_list_coins_t);		-- get a table of identifier access levels&lt;br /&gt;
	local ID_list_t = build_id_list (ID_list_coins_t, options_t, ID_access_levels_t);	-- get a sequence table of rendered identifier strings&lt;br /&gt;
&lt;br /&gt;
	return ID_list_t, ID_list_coins_t;											-- return the tables&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S E T _ S E L E C T E D _ M O D U L E S &amp;gt;--------------------------------------&lt;br /&gt;
&lt;br /&gt;
Sets local cfg table and imported functions table to same (live or sandbox) as that used by the other modules.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function set_selected_modules (cfg_table_ptr, utilities_page_ptr)&lt;br /&gt;
	cfg = cfg_table_ptr;&lt;br /&gt;
&lt;br /&gt;
	has_accept_as_written = utilities_page_ptr.has_accept_as_written;			-- import functions from select Module:Citation/CS1/Utilities module&lt;br /&gt;
	is_set = utilities_page_ptr.is_set;								&lt;br /&gt;
	in_array = utilities_page_ptr.in_array;&lt;br /&gt;
	set_message = utilities_page_ptr.set_message;&lt;br /&gt;
	select_one = utilities_page_ptr.select_one;&lt;br /&gt;
	substitute = utilities_page_ptr.substitute;&lt;br /&gt;
	make_wikilink = utilities_page_ptr.make_wikilink;&lt;br /&gt;
&lt;br /&gt;
	z = utilities_page_ptr.z;													-- table of tables in Module:Citation/CS1/Utilities&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; E X P O R T E D   F U N C T I O N S &amp;gt;------------------------------------------&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
return {&lt;br /&gt;
	auto_link_urls = auto_link_urls,											-- table of identifier URLs to be used when auto-linking |title=&lt;br /&gt;
	&lt;br /&gt;
	identifier_lists_get = identifier_lists_get,								-- experiment to replace individual calls to build_id_list(), extract_ids, extract_id_access_levels&lt;br /&gt;
	is_embargoed = is_embargoed;&lt;br /&gt;
	set_selected_modules = set_selected_modules;&lt;br /&gt;
	}&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Modul:Citation/CS1/Date_validation&amp;diff=1523</id>
		<title>Modul:Citation/CS1/Date validation</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Modul:Citation/CS1/Date_validation&amp;diff=1523"/>
		<updated>2022-08-12T16:59:11Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--[[--------------------------&amp;lt; F O R W A R D   D E C L A R A T I O N S &amp;gt;--------------------------------------&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local add_prop_cat, is_set, in_array, set_message, substitute, wrap_style;		-- imported functions from selected Module:Citation/CS1/Utilities&lt;br /&gt;
local cfg;																		-- table of tables imported from selected Module:Citation/CS1/Configuration&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; F I L E - S C O P E   D E C L A R A T I O N S &amp;gt;--------------------------------&lt;br /&gt;
&lt;br /&gt;
File-scope variables are declared here&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local lang_object = mw.getContentLanguage();									-- used by is_valid_accessdate(), is_valid_year(), date_name_xlate(); TODO: move to ~/Configuration?&lt;br /&gt;
local year_limit;																-- used by is_valid_year()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[=[-------------------------&amp;lt; I S _ V A L I D _ A C C E S S D A T E &amp;gt;----------------------------------------&lt;br /&gt;
&lt;br /&gt;
returns true if:&lt;br /&gt;
	Wikipedia start date &amp;lt;= accessdate &amp;lt; today + 2 days&lt;br /&gt;
&lt;br /&gt;
Wikipedia start date is 2001-01-15T00:00:00 UTC which is 979516800 seconds after 1970-01-01T00:00:00 UTC (the start of Unix time)&lt;br /&gt;
accessdate is the date provided in |access-date= at time 00:00:00 UTC&lt;br /&gt;
today is the current date at time 00:00:00 UTC plus 48 hours&lt;br /&gt;
	if today is 2015-01-01T00:00:00 then&lt;br /&gt;
		adding 24 hours gives 2015-01-02T00:00:00 – one second more than today&lt;br /&gt;
		adding 24 hours gives 2015-01-03T00:00:00 – one second more than tomorrow&lt;br /&gt;
&lt;br /&gt;
This function does not work if it is fed month names for languages other than English.  Wikimedia #time: parser&lt;br /&gt;
apparently doesn&#039;t understand non-English date month names. This function will always return false when the date&lt;br /&gt;
contains a non-English month name because good1 is false after the call to lang.formatDate().  To get around that&lt;br /&gt;
call this function with YYYY-MM-DD format dates.&lt;br /&gt;
&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local function is_valid_accessdate (accessdate)&lt;br /&gt;
	local good1, good2;&lt;br /&gt;
	local access_ts, tomorrow_ts;												-- to hold Unix time stamps representing the dates&lt;br /&gt;
&lt;br /&gt;
	good1, access_ts = pcall (lang_object.formatDate, lang_object, &#039;U&#039;, accessdate );			-- convert accessdate value to Unix timestamp &lt;br /&gt;
	good2, tomorrow_ts = pcall (lang_object.formatDate, lang_object, &#039;U&#039;, &#039;today + 2 days&#039; );	-- today midnight + 2 days is one second more than all day tomorrow&lt;br /&gt;
	&lt;br /&gt;
	if good1 and good2 then														-- lang.formatDate() returns a timestamp in the local script which which tonumber() may not understand&lt;br /&gt;
		access_ts = tonumber (access_ts) or lang_object:parseFormattedNumber (access_ts);		-- convert to numbers for the comparison;&lt;br /&gt;
		tomorrow_ts = tonumber (tomorrow_ts) or lang_object:parseFormattedNumber (tomorrow_ts);&lt;br /&gt;
	else&lt;br /&gt;
		return false;															-- one or both failed to convert to Unix time stamp&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if 979516800 &amp;lt;= access_ts and access_ts &amp;lt; tomorrow_ts then					-- Wikipedia start date &amp;lt;= accessdate &amp;lt; tomorrow&#039;s date&lt;br /&gt;
		return true;&lt;br /&gt;
	else&lt;br /&gt;
		return false;															-- accessdate out of range&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; G E T _ M O N T H _ N U M B E R &amp;gt;----------------------------------------------&lt;br /&gt;
&lt;br /&gt;
returns a number according to the month in a date: 1 for January, etc.  Capitalization and spelling must be correct.&lt;br /&gt;
If not a valid month, returns 0&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function get_month_number (month)&lt;br /&gt;
	return cfg.date_names[&#039;local&#039;].long[month] or cfg.date_names[&#039;local&#039;].short[month] or	-- look for local names first&lt;br /&gt;
			cfg.date_names[&#039;en&#039;].long[month] or	cfg.date_names[&#039;en&#039;].short[month] or		-- failing that, look for English names&lt;br /&gt;
			0;																				-- not a recognized month name&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; G E T _ S E A S O N _ N U M B E R &amp;gt;--------------------------------------------&lt;br /&gt;
&lt;br /&gt;
returns a number according to the sequence of seasons in a year: 21 for Spring, etc.  Capitalization and spelling&lt;br /&gt;
must be correct. If not a valid season, returns 0.&lt;br /&gt;
	21-24 = Spring, Summer, Autumn, Winter, independent of “Hemisphere”&lt;br /&gt;
&lt;br /&gt;
returns 0 when &amp;lt;param&amp;gt; is not |date=&lt;br /&gt;
&lt;br /&gt;
Season numbering is defined by Extended Date/Time Format (EDTF) specification (https://www.loc.gov/standards/datetime/)&lt;br /&gt;
which became part of ISO 8601 in 2019.  See &#039;§Sub-year groupings&#039;.  The standard defines various divisions using&lt;br /&gt;
numbers 21-41.  cs1|2 only supports generic seasons.  EDTF does support the distinction between north and south&lt;br /&gt;
hemisphere seasons but cs1|2 has no way to make that distinction.&lt;br /&gt;
&lt;br /&gt;
These additional divisions not currently supported:&lt;br /&gt;
	25-28 = Spring - Northern Hemisphere, Summer- Northern Hemisphere, Autumn - Northern Hemisphere, Winter - Northern Hemisphere&lt;br /&gt;
	29-32 = Spring – Southern Hemisphere, Summer– Southern Hemisphere, Autumn – Southern Hemisphere, Winter - Southern Hemisphere&lt;br /&gt;
	33-36 = Quarter 1, Quarter 2, Quarter 3, Quarter 4 (3 months each)&lt;br /&gt;
	37-39 = Quadrimester 1, Quadrimester 2, Quadrimester 3 (4 months each)&lt;br /&gt;
	40-41 = Semestral 1, Semestral-2 (6 months each)&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function get_season_number (season, param)&lt;br /&gt;
	if &#039;date&#039; ~= param then&lt;br /&gt;
		return 0;																-- season dates only supported by |date=&lt;br /&gt;
	end&lt;br /&gt;
	return cfg.date_names[&#039;local&#039;].season[season] or							-- look for local names first&lt;br /&gt;
			cfg.date_names[&#039;en&#039;].season[season] or								-- failing that, look for English names&lt;br /&gt;
			0;																	-- not a recognized season name&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; G E T _ Q U A R T E R _ N U M B E R &amp;gt;------------------------------------------&lt;br /&gt;
&lt;br /&gt;
returns a number according to the sequence of quarters in a year: 33 for first quarter, etc.  Capitalization and spelling&lt;br /&gt;
must be correct. If not a valid quarter, returns 0.&lt;br /&gt;
	33-36 = Quarter 1, Quarter 2, Quarter 3, Quarter 4 (3 months each)&lt;br /&gt;
&lt;br /&gt;
returns 0 when &amp;lt;param&amp;gt; is not |date=&lt;br /&gt;
&lt;br /&gt;
Quarter numbering is defined by Extended Date/Time Format (EDTF) specification (https://www.loc.gov/standards/datetime/)&lt;br /&gt;
which became part of ISO 8601 in 2019.  See &#039;§Sub-year groupings&#039;.  The standard defines various divisions using&lt;br /&gt;
numbers 21-41.  cs1|2 only supports generic seasons and quarters.&lt;br /&gt;
&lt;br /&gt;
These additional divisions not currently supported:&lt;br /&gt;
	37-39 = Quadrimester 1, Quadrimester 2, Quadrimester 3 (4 months each)&lt;br /&gt;
	40-41 = Semestral 1, Semestral-2 (6 months each)&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function get_quarter_number (quarter, param)&lt;br /&gt;
	if &#039;date&#039; ~= param then&lt;br /&gt;
		return 0;																-- quarter dates only supported by |date=&lt;br /&gt;
	end&lt;br /&gt;
	quarter = mw.ustring.gsub (quarter, &#039; +&#039;, &#039; &#039;);								-- special case replace multiple space chars with a single space char&lt;br /&gt;
	return cfg.date_names[&#039;local&#039;].quarter[quarter] or							-- look for local names first&lt;br /&gt;
			cfg.date_names[&#039;en&#039;].quarter[quarter] or							-- failing that, look for English names&lt;br /&gt;
			0;																	-- not a recognized quarter name&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; G E T _ P R O P E R _ N A M E _ N U M B E R &amp;gt;----------------------------------&lt;br /&gt;
&lt;br /&gt;
returns a non-zero number if date contains a recognized proper-name.  Capitalization and spelling must be correct.&lt;br /&gt;
&lt;br /&gt;
returns 0 when &amp;lt;param&amp;gt; is not |date=&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function get_proper_name_number (name, param)&lt;br /&gt;
	if &#039;date&#039; ~= param then&lt;br /&gt;
		return 0;																-- proper-name dates only supported by |date=&lt;br /&gt;
	end&lt;br /&gt;
	return cfg.date_names[&#039;local&#039;].named[name] or								-- look for local names dates first&lt;br /&gt;
			cfg.date_names[&#039;en&#039;].named[name] or									-- failing that, look for English names&lt;br /&gt;
			0;																	-- not a recognized named date&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; G E T _ E L E M E N T _ N U M B E R &amp;lt;------------------------------------------&lt;br /&gt;
&lt;br /&gt;
returns true if month or season or quarter or proper name is valid (properly spelled, capitalized, abbreviated)&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function get_element_number (element, param)&lt;br /&gt;
	local num;&lt;br /&gt;
	&lt;br /&gt;
	local funcs = {get_month_number, get_season_number, get_quarter_number, get_proper_name_number};	-- list of functions to execute in order&lt;br /&gt;
	&lt;br /&gt;
	for _, func in ipairs (funcs) do											-- spin through the function list&lt;br /&gt;
		num = func (element, param);											-- call the function and get the returned number&lt;br /&gt;
		if 0 ~= num then														-- non-zero when valid month season quarter &lt;br /&gt;
			return num;															-- return that number&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return nil;																	-- not valid&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; I S _ V A L I D _ Y E A R &amp;gt;----------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Function gets current year from the server and compares it to year from a citation parameter.  Years more than one&lt;br /&gt;
year in the future are not acceptable.&lt;br /&gt;
&lt;br /&gt;
Special case for |pmc-embargo-date=: years more than two years in the future are not acceptable&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function is_valid_year (year, param)&lt;br /&gt;
	if not is_set (year_limit) then&lt;br /&gt;
		year_limit = tonumber(os.date(&amp;quot;%Y&amp;quot;))+1;									-- global variable so we only have to fetch it once&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	year = tonumber (year) or lang_object:parseFormattedNumber (year);			-- convert to number for the comparison;&lt;br /&gt;
	&lt;br /&gt;
	if &#039;pmc-embargo-date&#039; == param then											-- special case for |pmc-embargo-date=&lt;br /&gt;
		return year and (year &amp;lt;= tonumber(os.date(&amp;quot;%Y&amp;quot;))+2) or false;			-- years more than two years in the future are not accepted&lt;br /&gt;
	end	&lt;br /&gt;
	return year and (year &amp;lt;= year_limit) or false;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; I S _ V A L I D _ D A T E &amp;gt;----------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Returns true if day is less than or equal to the number of days in month and year is no farther into the future&lt;br /&gt;
than next year; else returns false.&lt;br /&gt;
&lt;br /&gt;
Assumes Julian calendar prior to year 1582 and Gregorian calendar thereafter. Accounts for Julian calendar leap&lt;br /&gt;
years before 1582 and Gregorian leap years after 1582. Where the two calendars overlap (1582 to approximately&lt;br /&gt;
1923) dates are assumed to be Gregorian.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function is_valid_date (year, month, day, param)&lt;br /&gt;
local days_in_month = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};&lt;br /&gt;
local month_length;&lt;br /&gt;
	if not is_valid_year (year, param) then										-- no farther into the future than next year except |pmc-embargo-date= no more than two years in the future&lt;br /&gt;
		return false;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	month = tonumber (month);													-- required for YYYY-MM-DD dates&lt;br /&gt;
	&lt;br /&gt;
	if (2 == month) then														-- if February&lt;br /&gt;
		month_length = 28;														-- then 28 days unless&lt;br /&gt;
		if 1582 &amp;gt; tonumber(year) then											-- Julian calendar&lt;br /&gt;
			if 0 == (year%4) then												-- is a leap year?&lt;br /&gt;
				month_length = 29;												-- if leap year then 29 days in February&lt;br /&gt;
			end&lt;br /&gt;
		else																	-- Gregorian calendar&lt;br /&gt;
			if (0 == (year%4) and (0 ~= (year%100) or 0 == (year%400))) then	-- is a leap year?&lt;br /&gt;
				month_length = 29;												-- if leap year then 29 days in February&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		month_length = days_in_month[month];&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if tonumber (day) &amp;gt; month_length then&lt;br /&gt;
		return false;&lt;br /&gt;
	end&lt;br /&gt;
	return true;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; I S _ V A L I D _ M O N T H _ R A N G E _ S T Y L E &amp;gt;--------------------------&lt;br /&gt;
&lt;br /&gt;
Months in a range are expected to have the same style: Jan–Mar or October–December but not February–Mar or Jul–August. &lt;br /&gt;
This function looks in cfg.date_names{} to see if both month names are listed in the long subtable or both are&lt;br /&gt;
listed in the short subtable.  When both have the same style (both are listed in the same table), returns true; false else&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function is_valid_month_range_style (month1, month2)&lt;br /&gt;
	if (cfg.date_names.en.long[month1] and cfg.date_names.en.long[month2]) or					-- are both English names listed in the long subtable?&lt;br /&gt;
		(cfg.date_names.en.short[month1] and cfg.date_names.en.short[month2]) or				-- are both English names listed in the short subtable?&lt;br /&gt;
		(cfg.date_names[&#039;local&#039;].long[month1] and cfg.date_names[&#039;local&#039;].long[month2]) or		-- are both local names listed in the long subtable?&lt;br /&gt;
		(cfg.date_names[&#039;local&#039;].short[month1] and cfg.date_names[&#039;local&#039;].short[month2]) then	-- are both local names listed in the short subtable?&lt;br /&gt;
			return true;&lt;br /&gt;
	end&lt;br /&gt;
	return false;																-- names are mixed&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; I S _ V A L I D _ M O N T H _ S E A S O N _ R A N G E &amp;gt;------------------------&lt;br /&gt;
&lt;br /&gt;
Check a pair of months or seasons to see if both are valid members of a month or season pair.&lt;br /&gt;
&lt;br /&gt;
Month pairs are expected to be left to right, earliest to latest in time.&lt;br /&gt;
&lt;br /&gt;
All season ranges are accepted as valid because there are publishers out there who have published a Summer–Spring YYYY issue, hence treat as ok&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function is_valid_month_season_range(range_start, range_end, param)&lt;br /&gt;
	local range_start_number = get_month_number (range_start);&lt;br /&gt;
	local range_end_number;&lt;br /&gt;
&lt;br /&gt;
	if 0 == range_start_number then												-- is this a month range?&lt;br /&gt;
		range_start_number = get_season_number (range_start, param);			-- not a month; is it a season? get start season number&lt;br /&gt;
		range_end_number = get_season_number (range_end, param);				-- get end season number&lt;br /&gt;
&lt;br /&gt;
		if (0 ~= range_start_number) and (0 ~= range_end_number) and (range_start_number ~= range_end_number) then&lt;br /&gt;
			return true;														-- any season pairing is accepted except when both are the same&lt;br /&gt;
		end&lt;br /&gt;
		return false;															-- range_start and/or range_end is not a season&lt;br /&gt;
	end&lt;br /&gt;
																				-- here when range_start is a month&lt;br /&gt;
	range_end_number = get_month_number (range_end);							-- get end month number&lt;br /&gt;
	if range_start_number &amp;lt; range_end_number and								-- range_start is a month; does range_start precede range_end?&lt;br /&gt;
		is_valid_month_range_style (range_start, range_end) then				-- do months have the same style?&lt;br /&gt;
			return true;														-- proper order and same style&lt;br /&gt;
	end&lt;br /&gt;
	return false;																-- range_start month number is greater than or equal to range end number; or range end isn&#039;t a month&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; M A K E _ C O I N S _ D A T E &amp;gt;------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
This function receives a table of date parts for one or two dates and an empty table reference declared in&lt;br /&gt;
Module:Citation/CS1.  The function is called only for |date= parameters and only if the |date=&amp;lt;value&amp;gt; is &lt;br /&gt;
determined to be a valid date format.  The question of what to do with invalid date formats is not answered here.&lt;br /&gt;
&lt;br /&gt;
The date parts in the input table are converted to an ISO 8601 conforming date string:&lt;br /&gt;
	single whole dates:		yyyy-mm-dd&lt;br /&gt;
	month and year dates:	yyyy-mm&lt;br /&gt;
	year dates:				yyyy&lt;br /&gt;
	ranges:					yyyy-mm-dd/yyyy-mm-dd&lt;br /&gt;
							yyyy-mm/yyyy-mm&lt;br /&gt;
							yyyy/yyyy&lt;br /&gt;
&lt;br /&gt;
Dates in the Julian calendar are reduced to year or year/year so that we don&#039;t have to do calendar conversion from&lt;br /&gt;
Julian to Proleptic Gregorian.&lt;br /&gt;
&lt;br /&gt;
The input table has:&lt;br /&gt;
	year, year2 – always present; if before 1582, ignore months and days if present&lt;br /&gt;
	month, month2 – 0 if not provided, 1-12 for months, 21-24 for seasons; 99 Christmas&lt;br /&gt;
	day, day2 –  0 if not provided, 1-31 for days&lt;br /&gt;
	&lt;br /&gt;
the output table receives:&lt;br /&gt;
	rftdate:	an ISO 8601 formatted date&lt;br /&gt;
	rftchron:	a free-form version of the date, usually without year which is in rftdate (season ranges and proper-name dates)&lt;br /&gt;
	rftssn:		one of four season keywords: winter, spring, summer, fall (lowercase)&lt;br /&gt;
	rftquarter:	one of four values: 1, 2, 3, 4&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function make_COinS_date (input, tCOinS_date)&lt;br /&gt;
	local date;																	-- one date or first date in a range&lt;br /&gt;
	local date2 = &#039;&#039;;															-- end of range date&lt;br /&gt;
-- start temporary Julian / Gregorian calendar uncertainty detection&lt;br /&gt;
	local year = tonumber(input.year);											-- this temporary code to determine the extent of sources dated to the Julian/Gregorian&lt;br /&gt;
	local month = tonumber(input.month);										-- interstice 1 October 1582 – 1 January 1926&lt;br /&gt;
	local day = tonumber (input.day);&lt;br /&gt;
	if (0 ~= day) and															-- day must have a value for this to be a whole date&lt;br /&gt;
		(((1582 == year) and (10 &amp;lt;= month) and (12 &amp;gt;= month)) or				-- any whole 1582 date from 1 October to 31 December or&lt;br /&gt;
			((1926 == year) and (1 == month) and (1 == input.day)) or			-- 1 January 1926 or&lt;br /&gt;
				((1582 &amp;lt; year) and (1925 &amp;gt;= year))) then						-- any date 1 January 1583 – 31 December 1925&lt;br /&gt;
					tCOinS_date.inter_cal_cat = true;							-- set category flag true&lt;br /&gt;
	end&lt;br /&gt;
-- end temporary Julian / Gregorian calendar uncertainty detection&lt;br /&gt;
	&lt;br /&gt;
	if 1582 &amp;gt; tonumber(input.year) or 20 &amp;lt; tonumber(input.month) then			-- Julian calendar or season so &amp;amp;rft.date gets year only&lt;br /&gt;
		date = input.year;&lt;br /&gt;
		if 0 ~= input.year2 and input.year ~= input.year2 then					-- if a range, only the second year portion when not the same as range start year&lt;br /&gt;
			date = string.format (&#039;%.4d/%.4d&#039;, tonumber(input.year), tonumber(input.year2))		-- assemble the date range&lt;br /&gt;
		end&lt;br /&gt;
		if 20 &amp;lt; tonumber(input.month) then										-- if season or proper-name date&lt;br /&gt;
			local season = {[24] = &#039;winter&#039;, [21] = &#039;spring&#039;, [22] = &#039;summer&#039;, [23] = &#039;fall&#039;, [33] = &#039;1&#039;, [34] = &#039;2&#039;, [35] = &#039;3&#039;, [36] = &#039;4&#039;, [98] = &#039;Easter&#039;, [99] = &#039;Christmas&#039;};	-- seasons lowercase, no autumn; proper-names use title case&lt;br /&gt;
			if 0 == input.month2 then											-- single season date&lt;br /&gt;
				if 40 &amp;lt; tonumber(input.month) then&lt;br /&gt;
					tCOinS_date.rftchron = season[input.month];					-- proper-name dates&lt;br /&gt;
				elseif 30 &amp;lt; tonumber(input.month) then&lt;br /&gt;
					tCOinS_date.rftquarter = season[input.month];				-- quarters&lt;br /&gt;
				else&lt;br /&gt;
					tCOinS_date.rftssn = season[input.month];					-- seasons&lt;br /&gt;
				end&lt;br /&gt;
			else																-- season range with a second season specified&lt;br /&gt;
				if input.year ~= input.year2 then								-- season year – season year range or season year–year&lt;br /&gt;
					tCOinS_date.rftssn = season[input.month];					-- start of range season; keep this?&lt;br /&gt;
					if 0~= input.month2 then&lt;br /&gt;
						tCOinS_date.rftchron = string.format (&#039;%s %s – %s %s&#039;, season[input.month], input.year, season[input.month2], input.year2);&lt;br /&gt;
					end&lt;br /&gt;
				else															-- season–season year range&lt;br /&gt;
					tCOinS_date.rftssn = season[input.month];					-- start of range season; keep this?&lt;br /&gt;
					tCOinS_date.rftchron = season[input.month] .. &#039;–&#039; .. season[input.month2];	-- season–season year range&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		tCOinS_date.rftdate = date;&lt;br /&gt;
		return;																	-- done&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if 0 ~= input.day then&lt;br /&gt;
		date = string.format (&#039;%s-%.2d-%.2d&#039;, input.year, tonumber(input.month), tonumber(input.day));	-- whole date&lt;br /&gt;
	elseif 0 ~= input.month then&lt;br /&gt;
		date = string.format (&#039;%s-%.2d&#039;, input.year, tonumber(input.month));	-- year and month&lt;br /&gt;
	else&lt;br /&gt;
		date = string.format (&#039;%s&#039;, input.year);								-- just year&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if 0 ~= input.year2 then&lt;br /&gt;
		if 0 ~= input.day2 then&lt;br /&gt;
			date2 = string.format (&#039;/%s-%.2d-%.2d&#039;, input.year2, tonumber(input.month2), tonumber(input.day2));		-- whole date&lt;br /&gt;
		elseif 0 ~= input.month2 then&lt;br /&gt;
			date2 = string.format (&#039;/%s-%.2d&#039;, input.year2, tonumber(input.month2));	-- year and month&lt;br /&gt;
		else&lt;br /&gt;
			date2 = string.format (&#039;/%s&#039;, input.year2);							-- just year&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	tCOinS_date.rftdate = date .. date2;										-- date2 has the &#039;/&#039; separator&lt;br /&gt;
	return;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; P A T T E R N S &amp;gt;--------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
this is the list of patterns for date formats that this module recognizes.  Approximately the first half of these&lt;br /&gt;
patterns represent formats that might be reformatted into another format.  Those that might be reformatted have&lt;br /&gt;
&#039;indicator&#039; letters that identify the content of the matching capture: &#039;d&#039; (day), &#039;m&#039; (month), &#039;a&#039; (anchor year),&lt;br /&gt;
&#039;y&#039; (year); second day, month, year have a &#039;2&#039; suffix.&lt;br /&gt;
&lt;br /&gt;
These patterns are used for both date validation and for reformatting.  This table should not be moved to ~/Configuration&lt;br /&gt;
because changes to this table require changes to check_date() and to reformatter() and reformat_date()&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local patterns = {&lt;br /&gt;
	 																			-- year-initial numerical year-month-day&lt;br /&gt;
	[&#039;ymd&#039;] = {&#039;^(%d%d%d%d)%-(%d%d)%-(%d%d)$&#039;, &#039;y&#039;, &#039;m&#039;, &#039;d&#039;},					&lt;br /&gt;
																				-- month-initial: month day, year&lt;br /&gt;
	[&#039;Mdy&#039;] = {&#039;^(%D-) +([1-9]%d?), +((%d%d%d%d?)%a?)$&#039;, &#039;m&#039;, &#039;d&#039;, &#039;a&#039;, &#039;y&#039;},&lt;br /&gt;
																				-- month-initial day range: month day–day, year; days are separated by endash&lt;br /&gt;
	[&#039;Md-dy&#039;] = {&#039;^(%D-) +([1-9]%d?)[%-–]([1-9]%d?), +((%d%d%d%d)%a?)$&#039;, &#039;m&#039;, &#039;d&#039;, &#039;d2&#039;, &#039;a&#039;, &#039;y&#039;},&lt;br /&gt;
																				-- day-initial: day month year&lt;br /&gt;
	[&#039;dMy&#039;] = {&#039;^([1-9]%d?) +(%D-) +((%d%d%d%d?)%a?)$&#039;, &#039;d&#039;, &#039;m&#039;, &#039;a&#039;, &#039;y&#039;},&lt;br /&gt;
																				-- year-initial: year month day; day: 1 or 2 two digits, leading zero allowed; not supported at en.wiki&lt;br /&gt;
	--	[&#039;yMd&#039;] = {&#039;^((%d%d%d%d?)%a?) +(%D-) +(%d%d?)$&#039;, &#039;a&#039;, &#039;y&#039;, &#039;m&#039;, &#039;d&#039;},&lt;br /&gt;
																				-- day-range-initial: day–day month year; days are separated by endash&lt;br /&gt;
	[&#039;d-dMy&#039;] = {&#039;^([1-9]%d?)[%-–]([1-9]%d?) +(%D-) +((%d%d%d%d)%a?)$&#039;, &#039;d&#039;, &#039;d2&#039;, &#039;m&#039;, &#039;a&#039;, &#039;y&#039;},&lt;br /&gt;
																				-- day initial month-day-range: day month - day month year; uses spaced endash&lt;br /&gt;
	[&#039;dM-dMy&#039;] = {&#039;^([1-9]%d?) +(%D-) +[%-–] +([1-9]%d?) +(%D-) +((%d%d%d%d)%a?)$&#039;, &#039;d&#039;, &#039;m&#039;, &#039;d2&#039;, &#039;m2&#039;, &#039;a&#039;, &#039;y&#039;},&lt;br /&gt;
																				-- month initial month-day-range: month day – month day, year;  uses spaced endash&lt;br /&gt;
	[&#039;Md-Mdy&#039;] = {&#039;^(%D-) +([1-9]%d?) +[%-–] +(%D-) +([1-9]%d?), +((%d%d%d%d)%a?)$&#039;,&#039;m&#039;, &#039;d&#039;, &#039;m2&#039;, &#039;d2&#039;, &#039;a&#039;, &#039;y&#039;},&lt;br /&gt;
																				-- day initial month-day-year-range: day month year - day month year; uses spaced endash&lt;br /&gt;
	[&#039;dMy-dMy&#039;] = {&#039;^([1-9]%d?) +(%D-) +(%d%d%d%d) +[%-–] +([1-9]%d?) +(%D-) +((%d%d%d%d)%a?)$&#039;, &#039;d&#039;, &#039;m&#039;, &#039;y&#039;, &#039;d2&#039;, &#039;m2&#039;, &#039;a&#039;, &#039;y2&#039;},&lt;br /&gt;
																				-- month initial month-day-year-range: month day, year – month day, year;  uses spaced endash&lt;br /&gt;
	[&#039;Mdy-Mdy&#039;] = {&#039;^(%D-) +([1-9]%d?), +(%d%d%d%d) +[%-–] +(%D-) +([1-9]%d?), +((%d%d%d%d)%a?)$&#039;, &#039;m&#039;, &#039;d&#039;, &#039;y&#039;, &#039;m2&#039;, &#039;d2&#039;, &#039;a&#039;, &#039;y2&#039;},&lt;br /&gt;
&lt;br /&gt;
																				-- these date formats cannot be converted, per se, but month name can be rendered short or long&lt;br /&gt;
																				-- month/season year - month/season year; separated by spaced endash&lt;br /&gt;
	[&#039;My-My&#039;] = {&#039;^(%D-) +(%d%d%d%d) +[%-–] +(%D-) +((%d%d%d%d)%a?)$&#039;, &#039;m&#039;, &#039;y&#039;, &#039;m2&#039;, &#039;a&#039;, &#039;y2&#039;},&lt;br /&gt;
																				-- month/season range year; months separated by endash&lt;br /&gt;
	[&#039;M-My&#039;] = {&#039;^(%D-)[%-–](%D-) +((%d%d%d%d)%a?)$&#039;, &#039;m&#039;, &#039;m2&#039;, &#039;a&#039;, &#039;y&#039;},&lt;br /&gt;
																				-- month/season year or proper-name year; quarter year when First Quarter YYYY etc.&lt;br /&gt;
	[&#039;My&#039;] = {&#039;^([^%d–]-) +((%d%d%d%d)%a?)$&#039;, &#039;m&#039;, &#039;a&#039;, &#039;y&#039;},					-- this way because endash is a member of %D; %D- will match January–March 2019 when it shouldn&#039;t&lt;br /&gt;
&lt;br /&gt;
																				-- these date formats cannot be converted&lt;br /&gt;
	[&#039;Sy4-y2&#039;] = {&#039;^(%D-) +((%d%d)%d%d)[%-–]((%d%d)%a?)$&#039;},						-- special case Winter/Summer year-year (YYYY-YY); year separated with unspaced endash&lt;br /&gt;
	[&#039;Sy-y&#039;] = {&#039;^(%D-) +(%d%d%d%d)[%-–]((%d%d%d%d)%a?)$&#039;},						-- special case Winter/Summer year-year; year separated with unspaced endash&lt;br /&gt;
	[&#039;y-y&#039;] = {&#039;^(%d%d%d%d?)[%-–]((%d%d%d%d?)%a?)$&#039;},							-- year range: YYY-YYY or YYY-YYYY or YYYY–YYYY; separated by unspaced endash; 100-9999&lt;br /&gt;
	[&#039;y4-y2&#039;] = {&#039;^((%d%d)%d%d)[%-–]((%d%d)%a?)$&#039;},								-- year range: YYYY–YY; separated by unspaced endash&lt;br /&gt;
	[&#039;y&#039;] = {&#039;^((%d%d%d%d?)%a?)$&#039;},												-- year; here accept either YYY or YYYY&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; I S _ V A L I D _ E M B A R G O _ D A T E &amp;gt;------------------------------------&lt;br /&gt;
&lt;br /&gt;
returns true and date value if that value has proper dmy, mdy, ymd format.&lt;br /&gt;
&lt;br /&gt;
returns false and 9999 (embargoed forever) when date value is not proper format; assumes that when |pmc-embargo-date= is&lt;br /&gt;
set, the editor intended to embargo a PMC but |pmc-embargo-date= does not hold a single date.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function is_valid_embargo_date (v)&lt;br /&gt;
	if v:match (patterns[&#039;ymd&#039;][1]) or											-- ymd&lt;br /&gt;
		v:match (patterns[&#039;Mdy&#039;][1]) or											-- dmy&lt;br /&gt;
		v:match (patterns[&#039;dMy&#039;][1]) then										-- mdy&lt;br /&gt;
			return true, v;&lt;br /&gt;
	end&lt;br /&gt;
	return false, &#039;9999&#039;;														-- if here not good date so return false and set embargo date to long time in future&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; C H E C K _ D A T E &amp;gt;----------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Check date format to see that it is one of the formats approved by WP:DATESNO or WP:DATERANGE. Exception: only&lt;br /&gt;
allowed range separator is endash.  Additionally, check the date to see that it is a real date: no 31 in 30-day&lt;br /&gt;
months; no 29 February when not a leap year.  Months, both long-form and three character abbreviations, and seasons&lt;br /&gt;
must be spelled correctly.  Future years beyond next year are not allowed.&lt;br /&gt;
&lt;br /&gt;
If the date fails the format tests, this function returns false and does not return values for anchor_year and&lt;br /&gt;
COinS_date.  When this happens, the date parameter is (DEBUG: not?) used in the COinS metadata and the CITEREF identifier gets&lt;br /&gt;
its year from the year parameter if present otherwise CITEREF does not get a date value.&lt;br /&gt;
&lt;br /&gt;
Inputs:&lt;br /&gt;
	date_string - date string from date-holding parameters (date, year, publication-date, access-date, pmc-embargo-date, archive-date, lay-date)&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
	false if date string is not a real date; else&lt;br /&gt;
	true, anchor_year, COinS_date&lt;br /&gt;
		anchor_year can be used in CITEREF anchors&lt;br /&gt;
		COinS_date is ISO 8601 format date; see make_COInS_date()&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function check_date (date_string, param, tCOinS_date)&lt;br /&gt;
	local year;																	-- assume that year2, months, and days are not used;&lt;br /&gt;
	local year2 = 0;															-- second year in a year range&lt;br /&gt;
	local month = 0;&lt;br /&gt;
	local month2 = 0;															-- second month in a month range&lt;br /&gt;
	local day = 0;&lt;br /&gt;
	local day2 = 0;																-- second day in a day range&lt;br /&gt;
	local anchor_year;&lt;br /&gt;
	local coins_date;&lt;br /&gt;
&lt;br /&gt;
	if date_string:match (patterns[&#039;ymd&#039;][1]) then								-- year-initial numerical year month day format&lt;br /&gt;
		year, month, day = date_string:match (patterns[&#039;ymd&#039;][1]);&lt;br /&gt;
		if 12 &amp;lt; tonumber(month) or 1 &amp;gt; tonumber(month) or 1582 &amp;gt; tonumber(year) or 0 == tonumber(day) then return false; end	-- month or day number not valid or not Gregorian calendar&lt;br /&gt;
		anchor_year = year;&lt;br /&gt;
	&lt;br /&gt;
	elseif mw.ustring.match(date_string, patterns[&#039;Mdy&#039;][1]) then				-- month-initial: month day, year&lt;br /&gt;
		month, day, anchor_year, year = mw.ustring.match(date_string, patterns[&#039;Mdy&#039;][1]);&lt;br /&gt;
		month = get_month_number (month);&lt;br /&gt;
		if 0 == month then return false; end									-- return false if month text isn&#039;t one of the twelve months&lt;br /&gt;
				&lt;br /&gt;
	elseif mw.ustring.match(date_string, patterns[&#039;Md-dy&#039;][1]) then				-- month-initial day range: month day–day, year; days are separated by endash&lt;br /&gt;
		month, day, day2, anchor_year, year = mw.ustring.match(date_string, patterns[&#039;Md-dy&#039;][1]);&lt;br /&gt;
		if tonumber(day) &amp;gt;= tonumber(day2) then return false; end				-- date range order is left to right: earlier to later; dates may not be the same;&lt;br /&gt;
		month = get_month_number (month);&lt;br /&gt;
		if 0 == month then return false; end									-- return false if month text isn&#039;t one of the twelve months&lt;br /&gt;
		month2=month;															-- for metadata&lt;br /&gt;
		year2 = year;&lt;br /&gt;
&lt;br /&gt;
	elseif mw.ustring.match(date_string, patterns[&#039;dMy&#039;][1]) then				-- day-initial: day month year&lt;br /&gt;
		day, month, anchor_year, year = mw.ustring.match(date_string, patterns[&#039;dMy&#039;][1]);&lt;br /&gt;
		month = get_month_number (month);&lt;br /&gt;
		if 0 == month then return false; end									-- return false if month text isn&#039;t one of the twelve months&lt;br /&gt;
&lt;br /&gt;
--[[ NOT supported at en.wiki&lt;br /&gt;
	elseif mw.ustring.match(date_string, patterns[&#039;yMd&#039;][1]) then				-- year-initial: year month day; day: 1 or 2 two digits, leading zero allowed&lt;br /&gt;
		anchor_year, year, month, day = mw.ustring.match(date_string, patterns[&#039;yMd&#039;][1]);&lt;br /&gt;
		month = get_month_number (month);&lt;br /&gt;
		if 0 == month then return false; end									-- return false if month text isn&#039;t one of the twelve months&lt;br /&gt;
-- end NOT supported at en.wiki ]]&lt;br /&gt;
&lt;br /&gt;
	elseif mw.ustring.match(date_string, patterns[&#039;d-dMy&#039;][1]) then				-- day-range-initial: day–day month year; days are separated by endash&lt;br /&gt;
		day, day2, month, anchor_year, year = mw.ustring.match(date_string, patterns[&#039;d-dMy&#039;][1]);&lt;br /&gt;
		if tonumber(day) &amp;gt;= tonumber(day2) then return false; end				-- date range order is left to right: earlier to later; dates may not be the same;&lt;br /&gt;
		month = get_month_number (month);&lt;br /&gt;
		if 0 == month then return false; end									-- return false if month text isn&#039;t one of the twelve months&lt;br /&gt;
		month2 = month;															-- for metadata&lt;br /&gt;
		year2 = year;&lt;br /&gt;
&lt;br /&gt;
	elseif mw.ustring.match(date_string, patterns[&#039;dM-dMy&#039;][1]) then			-- day initial month-day-range: day month - day month year; uses spaced endash&lt;br /&gt;
		day, month, day2, month2, anchor_year, year = mw.ustring.match(date_string, patterns[&#039;dM-dMy&#039;][1]);&lt;br /&gt;
		if (not is_valid_month_season_range(month, month2)) or not is_valid_year(year) then return false; end	-- date range order is left to right: earlier to later;&lt;br /&gt;
		month = get_month_number (month);										-- for metadata&lt;br /&gt;
		month2 = get_month_number (month2);&lt;br /&gt;
		year2 = year;&lt;br /&gt;
&lt;br /&gt;
	elseif mw.ustring.match(date_string, patterns[&#039;Md-Mdy&#039;][1]) then			-- month initial month-day-range: month day – month day, year; uses spaced endash&lt;br /&gt;
		month, day, month2, day2, anchor_year, year = mw.ustring.match(date_string, patterns[&#039;Md-Mdy&#039;][1]);&lt;br /&gt;
		if (not is_valid_month_season_range(month, month2, param)) or not is_valid_year(year) then return false; end&lt;br /&gt;
		month = get_month_number (month);										-- for metadata&lt;br /&gt;
		month2 = get_month_number (month2);&lt;br /&gt;
		year2 = year;&lt;br /&gt;
&lt;br /&gt;
	elseif mw.ustring.match(date_string, patterns[&#039;dMy-dMy&#039;][1]) then			-- day initial month-day-year-range: day month year - day month year; uses spaced endash&lt;br /&gt;
		day, month, year, day2, month2, anchor_year, year2 = mw.ustring.match(date_string, patterns[&#039;dMy-dMy&#039;][1]);&lt;br /&gt;
		if tonumber(year2) &amp;lt;= tonumber(year) then return false; end				-- must be sequential years, left to right, earlier to later&lt;br /&gt;
		if not is_valid_year(year2) or not is_valid_month_range_style(month, month2) then return false; end		-- year2 no more than one year in the future; months same style&lt;br /&gt;
		month = get_month_number (month);										-- for metadata&lt;br /&gt;
		month2 = get_month_number (month2);&lt;br /&gt;
		if 0 == month or 0 == month2 then return false; end						-- both must be valid&lt;br /&gt;
&lt;br /&gt;
	elseif mw.ustring.match(date_string, patterns[&#039;Mdy-Mdy&#039;][1]) then			-- month initial month-day-year-range: month day, year – month day, year; uses spaced endash&lt;br /&gt;
		month, day, year, month2, day2, anchor_year, year2 = mw.ustring.match(date_string, patterns[&#039;Mdy-Mdy&#039;][1]);&lt;br /&gt;
		if tonumber(year2) &amp;lt;= tonumber(year) then return false; end				-- must be sequential years, left to right, earlier to later&lt;br /&gt;
		if not is_valid_year(year2) or not is_valid_month_range_style(month, month2) then return false; end		-- year2 no more than one year in the future; months same style&lt;br /&gt;
		month = get_month_number (month);										-- for metadata&lt;br /&gt;
		month2 = get_month_number(month2);&lt;br /&gt;
		if 0 == month or 0 == month2 then return false; end						-- both must be valid&lt;br /&gt;
&lt;br /&gt;
	elseif mw.ustring.match(date_string, patterns[&#039;Sy4-y2&#039;][1]) then			-- special case Winter/Summer year-year (YYYY-YY); year separated with unspaced endash&lt;br /&gt;
		local century;&lt;br /&gt;
		month, year, century, anchor_year, year2 = mw.ustring.match(date_string, patterns[&#039;Sy4-y2&#039;][1]);&lt;br /&gt;
		if &#039;Winter&#039; ~= month and &#039;Summer&#039; ~= month then return false end;		-- &#039;month&#039; can only be Winter or Summer&lt;br /&gt;
		anchor_year = year .. &#039;–&#039; .. anchor_year;								-- assemble anchor_year from both years&lt;br /&gt;
		year2 = century..year2;													-- add the century to year2 for comparisons&lt;br /&gt;
		if 1 ~= tonumber(year2) - tonumber(year) then return false; end			-- must be sequential years, left to right, earlier to later&lt;br /&gt;
		if not is_valid_year(year2) then return false; end						-- no year farther in the future than next year&lt;br /&gt;
		month = get_season_number(month, param);&lt;br /&gt;
&lt;br /&gt;
	elseif mw.ustring.match(date_string, patterns[&#039;Sy-y&#039;][1]) then				-- special case Winter/Summer year-year; year separated with unspaced endash&lt;br /&gt;
		month, year, anchor_year, year2 = mw.ustring.match(date_string, patterns[&#039;Sy-y&#039;][1]);&lt;br /&gt;
		month = get_season_number (month, param);								-- &amp;lt;month&amp;gt; can only be winter or summer; also for metadata&lt;br /&gt;
		if (month ~= cfg.date_names[&#039;en&#039;].season[&#039;Winter&#039;]) and (month ~= cfg.date_names[&#039;en&#039;].season[&#039;Summer&#039;]) then&lt;br /&gt;
			return false;														-- not Summer or Winter; abandon&lt;br /&gt;
		end&lt;br /&gt;
		anchor_year = year .. &#039;–&#039; .. anchor_year;								-- assemble anchor_year from both years&lt;br /&gt;
		if 1 ~= tonumber(year2) - tonumber(year) then return false; end			-- must be sequential years, left to right, earlier to later&lt;br /&gt;
		if not is_valid_year(year2) then return false; end						-- no year farther in the future than next year&lt;br /&gt;
&lt;br /&gt;
	elseif mw.ustring.match(date_string, patterns[&#039;My-My&#039;][1]) then				-- month/season year - month/season year; separated by spaced endash&lt;br /&gt;
		month, year, month2, anchor_year, year2 = mw.ustring.match(date_string, patterns[&#039;My-My&#039;][1]);&lt;br /&gt;
		anchor_year = year .. &#039;–&#039; .. anchor_year;								-- assemble anchor_year from both years&lt;br /&gt;
		if tonumber(year) &amp;gt;= tonumber(year2) then return false; end				-- left to right, earlier to later, not the same&lt;br /&gt;
		if not is_valid_year(year2) then return false; end						-- no year farther in the future than next year&lt;br /&gt;
		if 0 ~= get_month_number(month) and 0 ~= get_month_number(month2) and is_valid_month_range_style(month, month2) then 	-- both must be month year, same month style&lt;br /&gt;
			month = get_month_number(month);&lt;br /&gt;
			month2 = get_month_number(month2);&lt;br /&gt;
		elseif 0 ~= get_season_number(month, param) and 0 ~= get_season_number(month2, param) then	-- both must be season year, not mixed&lt;br /&gt;
			month = get_season_number(month, param);&lt;br /&gt;
			month2 = get_season_number(month2, param);&lt;br /&gt;
		else&lt;br /&gt;
			 return false;&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
	elseif mw.ustring.match(date_string, patterns[&#039;M-My&#039;][1]) then				-- month/season range year; months separated by endash &lt;br /&gt;
		month, month2, anchor_year, year = mw.ustring.match(date_string, patterns[&#039;M-My&#039;][1]);&lt;br /&gt;
		if (not is_valid_month_season_range(month, month2, param)) or (not is_valid_year(year)) then return false; end&lt;br /&gt;
		if 0 ~= get_month_number(month) then									-- determined to be a valid range so just check this one to know if month or season&lt;br /&gt;
			month = get_month_number(month);&lt;br /&gt;
			month2 = get_month_number(month2);&lt;br /&gt;
			if 0 == month or 0 == month2 then return false; end&lt;br /&gt;
		else&lt;br /&gt;
			month = get_season_number(month, param);&lt;br /&gt;
			month2 = get_season_number(month2, param);&lt;br /&gt;
		end&lt;br /&gt;
		year2 = year;&lt;br /&gt;
		&lt;br /&gt;
	elseif mw.ustring.match(date_string, patterns[&#039;My&#039;][1]) then				-- month/season/quarter/proper-name year&lt;br /&gt;
		month, anchor_year, year = mw.ustring.match(date_string, patterns[&#039;My&#039;][1]);&lt;br /&gt;
		if not is_valid_year(year) then return false; end&lt;br /&gt;
		month = get_element_number(month, param);								-- get month season quarter proper-name number or nil&lt;br /&gt;
		if not month then return false; end										-- not valid whatever it is&lt;br /&gt;
&lt;br /&gt;
	elseif mw.ustring.match(date_string, patterns[&#039;y-y&#039;][1]) then				-- Year range: YYY-YYY or YYY-YYYY or YYYY–YYYY; separated by unspaced endash; 100-9999&lt;br /&gt;
		year, anchor_year, year2 = mw.ustring.match(date_string, patterns[&#039;y-y&#039;][1]);&lt;br /&gt;
		anchor_year = year .. &#039;–&#039; .. anchor_year;								-- assemble anchor year from both years&lt;br /&gt;
		if tonumber(year) &amp;gt;= tonumber(year2) then return false; end				-- left to right, earlier to later, not the same&lt;br /&gt;
		if not is_valid_year(year2) then return false; end						-- no year farther in the future than next year&lt;br /&gt;
&lt;br /&gt;
	elseif mw.ustring.match(date_string, patterns[&#039;y4-y2&#039;][1]) then				-- Year range: YYYY–YY; separated by unspaced endash&lt;br /&gt;
		local century;&lt;br /&gt;
		year, century, anchor_year, year2 = mw.ustring.match(date_string, patterns[&#039;y4-y2&#039;][1]);&lt;br /&gt;
		anchor_year = year .. &#039;–&#039; .. anchor_year;								-- assemble anchor year from both years&lt;br /&gt;
&lt;br /&gt;
		if in_array (param, {&#039;date&#039;, &#039;publication-date&#039;, &#039;year&#039;}) then&lt;br /&gt;
			add_prop_cat (&#039;year-range-abbreviated&#039;);&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		if 13 &amp;gt; tonumber(year2) then return false; end							-- don&#039;t allow 2003-05 which might be May 2003&lt;br /&gt;
		year2 = century .. year2;													-- add the century to year2 for comparisons&lt;br /&gt;
		if tonumber(year) &amp;gt;= tonumber(year2) then return false; end				-- left to right, earlier to later, not the same&lt;br /&gt;
		if not is_valid_year(year2) then return false; end						-- no year farther in the future than next year&lt;br /&gt;
&lt;br /&gt;
	elseif mw.ustring.match(date_string, patterns[&#039;y&#039;][1]) then					-- year; here accept either YYY or YYYY&lt;br /&gt;
		anchor_year, year = mw.ustring.match(date_string, patterns[&#039;y&#039;][1]);&lt;br /&gt;
		if false == is_valid_year(year) then&lt;br /&gt;
			return false;&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
	else&lt;br /&gt;
		return false;															-- date format not one of the MOS:DATE approved formats&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if &#039;access-date&#039; == param then												-- test accessdate here because we have numerical date parts&lt;br /&gt;
		if 0 ~= year and 0 ~= month and 0 ~= day and 							-- all parts of a single date required&lt;br /&gt;
			0 == year2 and 0 == month2 and 0 == day2 then						-- none of these; accessdate must not be a range&lt;br /&gt;
				if not is_valid_accessdate(year .. &#039;-&#039; .. month .. &#039;-&#039; .. day) then	&lt;br /&gt;
					return false;												-- return false when accessdate out of bounds&lt;br /&gt;
				end&lt;br /&gt;
		else&lt;br /&gt;
			return false;														-- return false when accessdate is a range of two dates&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local result=true;															-- check whole dates for validity; assume true because not all dates will go through this test&lt;br /&gt;
	if 0 ~= year and 0 ~= month and 0 ~= day and 0 == year2 and 0 == month2 and 0 == day2 then		-- YMD (simple whole date)&lt;br /&gt;
		result = is_valid_date (year, month, day, param);						-- &amp;lt;param&amp;gt; for |pmc-embargo-date=&lt;br /&gt;
&lt;br /&gt;
	elseif 0 ~= year and 0 ~= month and 0 ~= day and 0 == year2 and 0 == month2 and 0 ~= day2 then	-- YMD-d (day range)&lt;br /&gt;
		result = is_valid_date (year, month, day);&lt;br /&gt;
		result = result and is_valid_date (year, month, day2);&lt;br /&gt;
&lt;br /&gt;
	elseif 0 ~= year and 0 ~= month and 0 ~= day and 0 == year2 and 0 ~= month2 and 0 ~= day2 then	-- YMD-md (day month range)&lt;br /&gt;
		result = is_valid_date (year, month, day);&lt;br /&gt;
		result = result and is_valid_date (year, month2, day2);&lt;br /&gt;
&lt;br /&gt;
	elseif 0 ~= year and 0 ~= month and 0 ~= day and 0 ~= year2 and 0 ~= month2 and 0 ~= day2 then	-- YMD-ymd (day month year range)&lt;br /&gt;
		result = is_valid_date(year, month, day);&lt;br /&gt;
		result = result and is_valid_date(year2, month2, day2);&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if false == result then return false; end&lt;br /&gt;
&lt;br /&gt;
	if nil ~= tCOinS_date then													-- this table only passed into this function when testing |date= parameter values&lt;br /&gt;
		make_COinS_date ({year = year, month = month, day = day, year2 = year2, month2 = month2, day2 = day2}, tCOinS_date);	-- make an ISO 8601 date string for COinS&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return true, anchor_year;													-- format is good and date string represents a real date&lt;br /&gt;
end	&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; D A T E S &amp;gt;--------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Cycle the date-holding parameters in passed table date_parameters_list through check_date() to check compliance with MOS:DATE. For all valid dates, check_date() returns&lt;br /&gt;
true. The |date= parameter test is unique, it is the only date holding parameter from which values for anchor_year (used in CITEREF identifiers) and COinS_date (used in&lt;br /&gt;
the COinS metadata) are derived.  The |date= parameter is the only date-holding parameter that is allowed to contain the no-date keywords &amp;quot;n.d.&amp;quot; or &amp;quot;nd&amp;quot; (without quotes).&lt;br /&gt;
&lt;br /&gt;
Unlike most error messages created in this module, only one error message is created by this function. Because all of the date holding parameters are processed serially,&lt;br /&gt;
parameters with errors are added to the &amp;lt;error_list&amp;gt; sequence table as the dates are tested.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function dates(date_parameters_list, tCOinS_date, error_list)&lt;br /&gt;
	local anchor_year;															-- will return as nil if the date being tested is not |date=&lt;br /&gt;
	local COinS_date;															-- will return as nil if the date being tested is not |date=&lt;br /&gt;
	local embargo_date;															-- if embargo date is a good dmy, mdy, ymd date then holds original value else reset to 9999&lt;br /&gt;
	local good_date = false;&lt;br /&gt;
&lt;br /&gt;
	for k, v in pairs(date_parameters_list) do									-- for each date-holding parameter in the list&lt;br /&gt;
		if is_set(v.val) then													-- if the parameter has a value&lt;br /&gt;
			v.val = mw.ustring.gsub(v.val, &#039;%d&#039;, cfg.date_names.local_digits);	-- translate &#039;local&#039; digits to Western 0-9&lt;br /&gt;
			if v.val:match(&amp;quot;^c%. [1-9]%d%d%d?%a?$&amp;quot;) then						-- special case for c. year or with or without CITEREF disambiguator - only |date= and |year=&lt;br /&gt;
				local year = v.val:match(&amp;quot;c%. ([1-9]%d%d%d?)%a?&amp;quot;);				-- get the year portion so it can be tested&lt;br /&gt;
				if &#039;date&#039; == k then&lt;br /&gt;
					anchor_year, COinS_date = v.val:match(&amp;quot;((c%. [1-9]%d%d%d?)%a?)&amp;quot;);	-- anchor year and COinS_date only from |date= parameter&lt;br /&gt;
					good_date = is_valid_year(year);&lt;br /&gt;
				elseif &#039;year&#039; == k then&lt;br /&gt;
					good_date = is_valid_year(year);&lt;br /&gt;
				end&lt;br /&gt;
			elseif &#039;date&#039; == k then												-- if the parameter is |date=&lt;br /&gt;
				if v.val:match(&amp;quot;^n%.d%.%a?$&amp;quot;) then -- ToDo: I18N								-- if |date=n.d. with or without a CITEREF disambiguator&lt;br /&gt;
					good_date, anchor_year, COinS_date = true, v.val:match(&amp;quot;((n%.d%.)%a?)&amp;quot;); -- ToDo: I18N	-- &amp;quot;n.d.&amp;quot;; no error when date parameter is set to no date&lt;br /&gt;
				elseif v.val:match(&amp;quot;^nd%a?$&amp;quot;) then -- ToDo: I18N								-- if |date=nd with or without a CITEREF disambiguator&lt;br /&gt;
					good_date, anchor_year, COinS_date = true, v.val:match(&amp;quot;((nd)%a?)&amp;quot;); -- ToDo: I18N	-- &amp;quot;nd&amp;quot;;	no error when date parameter is set to no date&lt;br /&gt;
				else&lt;br /&gt;
					good_date, anchor_year, COinS_date = check_date (v.val, k, tCOinS_date);	-- go test the date&lt;br /&gt;
				end&lt;br /&gt;
			elseif &#039;year&#039; == k then												-- if the parameter is |year= it should hold only a year value&lt;br /&gt;
				if v.val:match(&amp;quot;^[1-9]%d%d%d?%a?$&amp;quot;) then						-- if |year = 3 or 4 digits only with or without a CITEREF disambiguator&lt;br /&gt;
					good_date, anchor_year, COinS_date = true, v.val:match(&amp;quot;((%d+)%a?)&amp;quot;);&lt;br /&gt;
				end&lt;br /&gt;
			elseif &#039;pmc-embargo-date&#039; == k then									-- if the parameter is |pmc-embargo-date=&lt;br /&gt;
				good_date = check_date (v.val, k);								-- go test the date&lt;br /&gt;
				if true == good_date then										-- if the date is a valid date&lt;br /&gt;
					good_date, embargo_date = is_valid_embargo_date (v.val);	-- is |pmc-embargo-date= date a single dmy, mdy, or ymd formatted date? yes: returns embargo date; no: returns 9999&lt;br /&gt;
				end&lt;br /&gt;
			else																-- any other date-holding parameter&lt;br /&gt;
				good_date = check_date (v.val, k);								-- go test the date&lt;br /&gt;
			end&lt;br /&gt;
			if false == good_date then											-- assemble one error message so we don&#039;t add the tracking category multiple times&lt;br /&gt;
				table.insert (error_list, wrap_style (&#039;parameter&#039;, v.name));	-- make parameter name suitable for error message list&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return anchor_year, embargo_date;											-- and done&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; Y E A R _ D A T E _ C H E C K &amp;gt;------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Compare the value provided in |year= with the year value(s) provided in |date=.  This function sets a local numeric value:&lt;br /&gt;
	0 - year value does not match the year value in date&lt;br /&gt;
	1 - (default) year value matches the year value in date or one of the year values when date contains two years&lt;br /&gt;
	2 - year value matches the year value in date when date is in the form YYYY-MM-DD and year is disambiguated (|year=YYYYx)&lt;br /&gt;
&lt;br /&gt;
the numeric value in &amp;lt;result&amp;gt; determines the &#039;output&#039; if any from this function:&lt;br /&gt;
	0 – adds error message to error_list sequence table&lt;br /&gt;
	1 – adds maint cat&lt;br /&gt;
	2 – does nothing&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function year_date_check (year_string, year_origin, date_string, date_origin, error_list)&lt;br /&gt;
	local year;&lt;br /&gt;
	local date1;&lt;br /&gt;
	local date2;&lt;br /&gt;
	local result = 1;															-- result of the test; assume that the test passes&lt;br /&gt;
&lt;br /&gt;
	year = year_string:match (&#039;(%d%d%d%d?)&#039;);&lt;br /&gt;
&lt;br /&gt;
	if date_string:match (&#039;%d%d%d%d%-%d%d%-%d%d&#039;) and year_string:match (&#039;%d%d%d%d%a&#039;) then	--special case where both date and year are required YYYY-MM-DD and YYYYx&lt;br /&gt;
		date1 = date_string:match (&#039;(%d%d%d%d)&#039;);&lt;br /&gt;
		year = year_string:match (&#039;(%d%d%d%d)&#039;);&lt;br /&gt;
		if year ~= date1 then&lt;br /&gt;
			result = 0;															-- years don&#039;t match&lt;br /&gt;
		else&lt;br /&gt;
			result = 2;															-- years match; but because disambiguated, don&#039;t add to maint cat&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
	elseif date_string:match (&amp;quot;%d%d%d%d?.-%d%d%d%d?&amp;quot;) then						-- any of the standard range formats of date with two three- or four-digit years&lt;br /&gt;
		date1, date2 = date_string:match (&amp;quot;(%d%d%d%d?).-(%d%d%d%d?)&amp;quot;);&lt;br /&gt;
		if year ~= date1 and year ~= date2 then&lt;br /&gt;
			result = 0;&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
	elseif mw.ustring.match(date_string, &amp;quot;%d%d%d%d[%-–]%d%d&amp;quot;) then				-- YYYY-YY date ranges&lt;br /&gt;
		local century;&lt;br /&gt;
		date1, century, date2 = mw.ustring.match(date_string, &amp;quot;((%d%d)%d%d)[%-–]+(%d%d)&amp;quot;);&lt;br /&gt;
		date2 = century..date2;													-- convert YY to YYYY&lt;br /&gt;
		if year ~= date1 and year ~= date2 then&lt;br /&gt;
			result = 0;&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
	elseif date_string:match (&amp;quot;%d%d%d%d?&amp;quot;) then									-- any of the standard formats of date with one year&lt;br /&gt;
		date1 = date_string:match (&amp;quot;(%d%d%d%d?)&amp;quot;);&lt;br /&gt;
		if year ~= date1 then&lt;br /&gt;
			result = 0;&lt;br /&gt;
		end&lt;br /&gt;
	else																		-- should never get here; this function called only when no other date errors&lt;br /&gt;
		result = 0;																-- no recognizable year in date&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if 0 == result then															-- year / date mismatch&lt;br /&gt;
		table.insert (error_list, substitute (cfg.messages[&#039;mismatch&#039;], {year_origin, date_origin}));	-- add error message to error_list sequence table&lt;br /&gt;
	elseif 1 == result then														-- redundant year / date&lt;br /&gt;
		set_message (&#039;maint_date_year&#039;);										-- add a maint cat&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; R E F O R M A T T E R &amp;gt;--------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
reformat &#039;date&#039; into new format specified by format_param if pattern_idx (the current format of &#039;date&#039;) can be&lt;br /&gt;
reformatted.  Does the grunt work for reformat_dates().&lt;br /&gt;
&lt;br /&gt;
The table re_formats maps pattern_idx (current format) and format_param (desired format) to a table that holds:&lt;br /&gt;
	format string used by string.format()&lt;br /&gt;
	identifier letters (&#039;d&#039;, &#039;m&#039;, &#039;y&#039;, &#039;d2&#039;, &#039;m2&#039;, &#039;y2&#039;) that serve as indexes into a table t{} that holds captures&lt;br /&gt;
		from mw.ustring.match() for the various date parts specified by  patterns[pattern_idx][1]&lt;br /&gt;
&lt;br /&gt;
Items in patterns{} have the general form:&lt;br /&gt;
	[&#039;ymd&#039;] = {&#039;^(%d%d%d%d)%-(%d%d)%-(%d%d)$&#039;, &#039;y&#039;, &#039;m&#039;, &#039;d&#039;}, where:&lt;br /&gt;
		[&#039;ymd&#039;] is pattern_idx&lt;br /&gt;
		patterns[&#039;ymd&#039;][1] is the match pattern with captures for mw.ustring.match()&lt;br /&gt;
		patterns[&#039;ymd&#039;][2] is an indicator letter identifying the content of the first capture&lt;br /&gt;
		patterns[&#039;ymd&#039;][3] ... the second capture etc.&lt;br /&gt;
&lt;br /&gt;
when a pattern matches a date, the captures are loaded into table t{} in capture order using the idemtifier&lt;br /&gt;
characters as indexes into t{}  For the above, a ymd date is in t{} as:&lt;br /&gt;
	t.y = first capture (year), t.m = second capture (month), t.d = third capture (day)&lt;br /&gt;
&lt;br /&gt;
To reformat, this function is called with the pattern_idx that matches the current format of the date and with&lt;br /&gt;
format_param set to the desired format.  This function loads table t{} as described and then calls string.format()&lt;br /&gt;
with the format string specified by re_format[pattern_idx][format_param][1] using values taken from t{} according&lt;br /&gt;
to the capture identifier letters specified by patterns[pattern_idx][format_param][n] where n is 2..&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local re_formats = {&lt;br /&gt;
	[&#039;ymd&#039;] = {																	-- date format is ymd; reformat to:&lt;br /&gt;
		[&#039;mdy&#039;] = {&#039;%s %s, %s&#039;, &#039;m&#039;, &#039;d&#039;, &#039;y&#039;},									-- |df=mdy&lt;br /&gt;
		[&#039;dmy&#039;] = {&#039;%s %s %s&#039;, &#039;d&#039;, &#039;m&#039;, &#039;y&#039;},									-- |df=dmy&lt;br /&gt;
	--		[&#039;yMd&#039;] = {&#039;%s %s %s&#039;, &#039;y&#039;, &#039;m&#039;, &#039;d&#039;},								-- |df=yMd; not supported at en.wiki&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;Mdy&#039;] = {																	-- date format is Mdy; reformat to:&lt;br /&gt;
		[&#039;mdy&#039;] = {&#039;%s %s, %s&#039;, &#039;m&#039;, &#039;d&#039;, &#039;y&#039;},									-- for long/short reformatting&lt;br /&gt;
		[&#039;dmy&#039;] = {&#039;%s %s %s&#039;, &#039;d&#039;, &#039;m&#039;, &#039;y&#039;},									-- |df=dmy&lt;br /&gt;
		[&#039;ymd&#039;] = {&#039;%s-%s-%s&#039;, &#039;y&#039;, &#039;m&#039;, &#039;d&#039;},									-- |df=ymd&lt;br /&gt;
	--		[&#039;yMd&#039;] = {&#039;%s %s %s&#039;, &#039;y&#039;, &#039;m&#039;, &#039;d&#039;},								-- |df=yMd; not supported at en.wiki&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;dMy&#039;] = {																	-- date format is dMy; reformat to:&lt;br /&gt;
		[&#039;dmy&#039;] = {&#039;%s %s %s&#039;, &#039;d&#039;, &#039;m&#039;, &#039;y&#039;},									-- for long/short reformatting&lt;br /&gt;
		[&#039;mdy&#039;] = {&#039;%s %s, %s&#039;, &#039;m&#039;, &#039;d&#039;, &#039;y&#039;},									-- |df=mdy&lt;br /&gt;
		[&#039;ymd&#039;] = {&#039;%s-%s-%s&#039;, &#039;y&#039;, &#039;m&#039;, &#039;d&#039;},									-- |df=ymd&lt;br /&gt;
	--		[&#039;yMd&#039;] = {&#039;%s %s %s&#039;, &#039;y&#039;, &#039;m&#039;, &#039;d&#039;},								-- |df=yMd; not supported at en.wiki&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;Md-dy&#039;] = {																-- date format is Md-dy; reformat to:&lt;br /&gt;
		[&#039;mdy&#039;] = {&#039;%s %s–%s, %s&#039;, &#039;m&#039;, &#039;d&#039;, &#039;d2&#039;, &#039;y&#039;},						-- for long/short reformatting&lt;br /&gt;
		[&#039;dmy&#039;] = {&#039;%s–%s %s %s&#039;, &#039;d&#039;, &#039;d2&#039;, &#039;m&#039;, &#039;y&#039;},							-- |df=dmy -&amp;gt; d-dMy &lt;br /&gt;
		},&lt;br /&gt;
	[&#039;d-dMy&#039;] = {																-- date format is d-d&amp;gt;y; reformat to:&lt;br /&gt;
		[&#039;dmy&#039;] = {&#039;%s–%s %s %s&#039;, &#039;d&#039;, &#039;d2&#039;, &#039;m&#039;, &#039;y&#039;},							-- for long/short reformatting&lt;br /&gt;
		[&#039;mdy&#039;] = {&#039;%s %s–%s, %s&#039;, &#039;m&#039;, &#039;d&#039;, &#039;d2&#039;, &#039;y&#039;},						-- |df=mdy -&amp;gt; Md-dy &lt;br /&gt;
		},&lt;br /&gt;
	[&#039;dM-dMy&#039;] = {																-- date format is dM-dMy; reformat to:&lt;br /&gt;
		[&#039;dmy&#039;] = {&#039;%s %s – %s %s %s&#039;, &#039;d&#039;, &#039;m&#039;, &#039;d2&#039;, &#039;m2&#039;, &#039;y&#039;},				-- for long/short reformatting&lt;br /&gt;
		[&#039;mdy&#039;] = {&#039;%s %s – %s %s, %s&#039;, &#039;m&#039;, &#039;d&#039;, &#039;m2&#039;, &#039;d2&#039;, &#039;y&#039;},				-- |df=mdy -&amp;gt; Md-Mdy &lt;br /&gt;
		},&lt;br /&gt;
	[&#039;Md-Mdy&#039;] = {																-- date format is Md-Mdy; reformat to:&lt;br /&gt;
		[&#039;mdy&#039;] = {&#039;%s %s – %s %s, %s&#039;, &#039;m&#039;, &#039;d&#039;,  &#039;m2&#039;, &#039;d2&#039;, &#039;y&#039;},			-- for long/short reformatting&lt;br /&gt;
		[&#039;dmy&#039;] = {&#039;%s %s – %s %s %s&#039;, &#039;d&#039;, &#039;m&#039;, &#039;d2&#039;, &#039;m2&#039;, &#039;y&#039;},				-- |df=dmy -&amp;gt; dM-dMy &lt;br /&gt;
		},&lt;br /&gt;
	[&#039;dMy-dMy&#039;] = {																-- date format is dMy-dMy; reformat to:&lt;br /&gt;
		[&#039;dmy&#039;] = {&#039;%s %s %s – %s %s %s&#039;, &#039;d&#039;, &#039;m&#039;, &#039;y&#039;, &#039;d2&#039;, &#039;m2&#039;, &#039;y2&#039;},		-- for long/short reformatting&lt;br /&gt;
		[&#039;mdy&#039;] = {&#039;%s %s, %s – %s %s, %s&#039;, &#039;m&#039;, &#039;d&#039;, &#039;y&#039;, &#039;m2&#039;, &#039;d2&#039;, &#039;y2&#039;},	-- |df=mdy -&amp;gt; Mdy-Mdy &lt;br /&gt;
		},&lt;br /&gt;
	[&#039;Mdy-Mdy&#039;] = {																-- date format is Mdy-Mdy; reformat to:&lt;br /&gt;
		[&#039;mdy&#039;] = {&#039;%s %s, %s – %s %s, %s&#039;, &#039;m&#039;, &#039;d&#039;, &#039;y&#039;, &#039;m2&#039;, &#039;d2&#039;, &#039;y2&#039;},	-- for long/short reformatting&lt;br /&gt;
		[&#039;dmy&#039;] = {&#039;%s %s %s – %s %s %s&#039;, &#039;d&#039;, &#039;m&#039;, &#039;y&#039;, &#039;d2&#039;, &#039;m2&#039;, &#039;y2&#039;},		-- |df=dmy -&amp;gt; dMy-dMy &lt;br /&gt;
		},&lt;br /&gt;
	[&#039;My-My&#039;] = {																-- these for long/short reformatting&lt;br /&gt;
		[&#039;any&#039;] = {&#039;%s %s – %s %s&#039;, &#039;m&#039;, &#039;y&#039;, &#039;m2&#039;, &#039;y2&#039;},						-- dmy/mdy agnostic&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;M-My&#039;] = {																-- these for long/short reformatting&lt;br /&gt;
		[&#039;any&#039;] = {&#039;%s–%s %s&#039;, &#039;m&#039;, &#039;m2&#039;, &#039;y&#039;},									-- dmy/mdy agnostic&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;My&#039;] = {																	-- these for long/short reformatting&lt;br /&gt;
		[&#039;any&#039;] = {&#039;%s %s&#039;, &#039;m&#039;, &#039;y&#039;},											-- dmy/mdy agnostic&lt;br /&gt;
		},&lt;br /&gt;
	--	[&#039;yMd&#039;] = {																-- not supported at en.wiki&lt;br /&gt;
	--		[&#039;mdy&#039;] = {&#039;%s %s, %s&#039;, &#039;m&#039;, &#039;d&#039;, &#039;y&#039;},								-- |df=mdy&lt;br /&gt;
	--		[&#039;dmy&#039;] = {&#039;%s %s %s&#039;, &#039;d&#039;, &#039;m&#039;, &#039;y&#039;},								-- |df=dmy&lt;br /&gt;
	--		[&#039;ymd&#039;] = {&#039;%s-%s-%s&#039;, &#039;y&#039;, &#039;m&#039;, &#039;d&#039;},								-- |df=ymd&lt;br /&gt;
	--		},&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function reformatter (date, pattern_idx, format_param, mon_len)&lt;br /&gt;
	if not in_array (pattern_idx, {&#039;ymd&#039;, &#039;Mdy&#039;, &#039;Md-dy&#039;, &#039;dMy&#039;, &#039;yMd&#039;, &#039;d-dMy&#039;, &#039;dM-dMy&#039;, &#039;Md-Mdy&#039;, &#039;dMy-dMy&#039;, &#039;Mdy-Mdy&#039;, &#039;My-My&#039;, &#039;M-My&#039;, &#039;My&#039;}) then&lt;br /&gt;
		return;																	-- not in this set of date format patterns then not a reformattable date&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if &#039;ymd&#039; == format_param and in_array (pattern_idx, {&#039;ymd&#039;, &#039;Md-dy&#039;, &#039;d-dMy&#039;, &#039;dM-dMy&#039;, &#039;Md-Mdy&#039;, &#039;dMy-dMy&#039;, &#039;Mdy-Mdy&#039;, &#039;My-My&#039;, &#039;M-My&#039;, &#039;My&#039;}) then&lt;br /&gt;
		return;																	-- ymd date ranges not supported at en.wiki; no point in reformatting ymd to ymd&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if in_array (pattern_idx, {&#039;My&#039;, &#039;M-My&#039;, &#039;My-My&#039;}) then						-- these are not dmy/mdy so can&#039;t be &#039;reformatted&#039; into either&lt;br /&gt;
		format_param = &#039;any&#039;;													-- so format-agnostic &lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
																				-- yMd is not supported at en.wiki; when yMd is supported at your wiki, uncomment the next line&lt;br /&gt;
	--	if &#039;yMd&#039; == format_param and in_array (pattern_idx, {&#039;yMd&#039;, &#039;Md-dy&#039;, &#039;d-dMy&#039;, &#039;dM-dMy&#039;, &#039;Md-Mdy&#039;, &#039;dMy-dMy&#039;, &#039;Mdy-Mdy&#039;}) then	-- these formats not convertable; yMd not supported at en.wiki&lt;br /&gt;
	if &#039;yMd&#039; == format_param then												-- yMd not supported at en.wiki; when yMd is supported at your wiki, remove or comment-out this line&lt;br /&gt;
		return;																	-- not a reformattable date&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local c1, c2, c3, c4, c5, c6, c7;											-- these hold the captures specified in patterns[pattern_idx][1]&lt;br /&gt;
	c1, c2, c3, c4, c5, c6, c7 = mw.ustring.match (date, patterns[pattern_idx][1]);	-- get the captures&lt;br /&gt;
&lt;br /&gt;
	local t = {																	-- table that holds k/v pairs of date parts from the captures and patterns[pattern_idx][2..]&lt;br /&gt;
		[patterns[pattern_idx][2]] = c1;										-- at minimum there is always one capture with a matching indicator letter&lt;br /&gt;
		[patterns[pattern_idx][3] or &#039;x&#039;] = c2;									-- patterns can have a variable number of captures; each capture requires an indicator letter;&lt;br /&gt;
		[patterns[pattern_idx][4] or &#039;x&#039;] = c3;									-- where there is no capture, there is no indicator letter so n in patterns[pattern_idx][n] will be nil;&lt;br /&gt;
		[patterns[pattern_idx][5] or &#039;x&#039;] = c4;									-- the &#039;x&#039; here spoofs an indicator letter to prevent &#039;table index is nil&#039; error&lt;br /&gt;
		[patterns[pattern_idx][6] or &#039;x&#039;] = c5;&lt;br /&gt;
		[patterns[pattern_idx][7] or &#039;x&#039;] = c6;&lt;br /&gt;
		[patterns[pattern_idx][8] or &#039;x&#039;] = c7;&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
	if t.a then																	-- if this date has an anchor year capture (all convertable date formats except ymd)&lt;br /&gt;
		if t.y2 then															-- for year range date formats														&lt;br /&gt;
			t.y2 = t.a;															-- use the anchor year capture when reassembling the date&lt;br /&gt;
		else																	-- here for single date formats (except ymd)&lt;br /&gt;
			t.y = t.a;															-- use the anchor year capture when reassembling the date&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if tonumber(t.m) then														-- if raw month is a number (converting from ymd)&lt;br /&gt;
		if &#039;s&#039; == mon_len then													-- if we are to use abbreviated month names&lt;br /&gt;
			t.m = cfg.date_names[&#039;inv_local_short&#039;][tonumber(t.m)];					-- convert it to a month name&lt;br /&gt;
		else&lt;br /&gt;
			t.m = cfg.date_names[&#039;inv_local_long&#039;][tonumber(t.m)];					-- convert it to a month name&lt;br /&gt;
		end&lt;br /&gt;
		t.d = t.d:gsub (&#039;0(%d)&#039;, &#039;%1&#039;);											-- strip leading &#039;0&#039; from day if present&lt;br /&gt;
	elseif &#039;ymd&#039; == format_param then											-- when converting to ymd&lt;br /&gt;
		t.y = t.y:gsub (&#039;%a&#039;, &#039;&#039;);												-- strip CITREF disambiguator if present; anchor year already known so process can proceed; TODO: maint message?&lt;br /&gt;
		if 1582 &amp;gt; tonumber (t.y) then											-- ymd format dates not allowed before 1582&lt;br /&gt;
			return;&lt;br /&gt;
		end&lt;br /&gt;
		t.m = string.format (&#039;%02d&#039;, get_month_number (t.m));					-- make sure that month and day are two digits&lt;br /&gt;
		t.d = string.format (&#039;%02d&#039;, t.d);&lt;br /&gt;
	elseif mon_len then															-- if mon_len is set to either &#039;short&#039; or &#039;long&#039;&lt;br /&gt;
		for _, mon in ipairs ({&#039;m&#039;, &#039;m2&#039;}) do									-- because there can be two month names, check both &lt;br /&gt;
			if t[mon] then&lt;br /&gt;
				t[mon] = get_month_number (t[mon]);								-- get the month number for this month (is length agnostic)&lt;br /&gt;
				if 0 == t[mon] then return; end									-- seasons and named dates can&#039;t be converted&lt;br /&gt;
				t[mon] = ((&#039;s&#039; == mon_len) and cfg.date_names[&#039;inv_local_short&#039;][t[mon]]) or cfg.date_names[&#039;inv_local_long&#039;][t[mon]];	-- fetch month name according to length&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local new_date = string.format (re_formats[pattern_idx][format_param][1],	-- format string&lt;br /&gt;
		t[re_formats[pattern_idx][format_param][2]],							-- named captures from t{}&lt;br /&gt;
		t[re_formats[pattern_idx][format_param][3]],&lt;br /&gt;
		t[re_formats[pattern_idx][format_param][4]],&lt;br /&gt;
		t[re_formats[pattern_idx][format_param][5]],&lt;br /&gt;
		t[re_formats[pattern_idx][format_param][6]],&lt;br /&gt;
		t[re_formats[pattern_idx][format_param][7]],&lt;br /&gt;
		t[re_formats[pattern_idx][format_param][8]]&lt;br /&gt;
		);&lt;br /&gt;
&lt;br /&gt;
	return new_date;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[-------------------------&amp;lt; R E F O R M A T _ D A T E S &amp;gt;--------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Reformats existing dates into the format specified by format.&lt;br /&gt;
&lt;br /&gt;
format is one of several manual keywords: dmy, dmy-all, mdy, mdy-all, ymd, ymd-all.  The -all version includes&lt;br /&gt;
access- and archive-dates; otherwise these dates are not reformatted.&lt;br /&gt;
&lt;br /&gt;
This function allows automatic date formatting.  In ~/Configuration, the article source is searched for one of&lt;br /&gt;
the {{use xxx dates}} templates.  If found, xxx becomes the global date format as xxx-all.  If |cs1-dates= in&lt;br /&gt;
{{use xxx dates}} has legitimate value then that value determines how cs1|2 dates will be rendered.  Legitimate&lt;br /&gt;
values for |cs1-dates= are:&lt;br /&gt;
	l - all dates are rendered with long month names&lt;br /&gt;
	ls - publication dates use long month names; access-/archive-dates use abbreviated month names&lt;br /&gt;
	ly - publication dates use long month names; access-/archive-dates rendered in ymd format&lt;br /&gt;
	s - all dates are rendered with abbreviated (short) month names&lt;br /&gt;
	sy - publication dates use abbreviated month names; access-/archive-dates rendered in ymd format&lt;br /&gt;
	y - all dates are rendered in ymd format&lt;br /&gt;
&lt;br /&gt;
the format argument for automatic date formatting will be the format specified by {{use xxx dates}} with the&lt;br /&gt;
value supplied by |cs1-dates so one of: xxx-l, xxx-ls, xxx-ly, xxx-s, xxx-sy, xxx-y, or simply xxx (|cs1-dates=&lt;br /&gt;
empty, omitted, or invalid) where xxx shall be either of dmy or mdy.&lt;br /&gt;
&lt;br /&gt;
dates are extracted from date_parameters_list, reformatted (if appropriate), and then written back into the&lt;br /&gt;
list in the new format.  Dates in date_parameters_list are presumed here to be valid (no errors).  This function&lt;br /&gt;
returns true when a date has been reformatted, false else.  Actual reformatting is done by reformatter().&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function reformat_dates (date_parameters_list, format)&lt;br /&gt;
	local all = false;															-- set to false to skip access- and archive-dates&lt;br /&gt;
	local len_p = &#039;l&#039;;															-- default publication date length shall be long&lt;br /&gt;
	local len_a = &#039;l&#039;;															-- default access-/archive-date length shall be long&lt;br /&gt;
	local result = false;&lt;br /&gt;
	local new_date;																&lt;br /&gt;
	&lt;br /&gt;
	if format:match(&#039;%a+%-all&#039;) then											-- manual df keyword; auto df keyword when length not specified in {{use xxx dates}}; &lt;br /&gt;
		format = format:match(&#039;(%a+)%-all&#039;);									-- extract the format&lt;br /&gt;
		all = true;																-- all dates are long format dates because this keyword doesn&#039;t specify length&lt;br /&gt;
	elseif format:match(&#039;%a+%-[lsy][sy]?&#039;) then									-- auto df keywords; internal only&lt;br /&gt;
		all = true;																-- auto df applies to all dates; use length specified by capture len_p for all dates&lt;br /&gt;
		format, len_p, len_a = format:match(&#039;(%a+)%-([lsy])([sy]?)&#039;);			-- extract the format and length keywords&lt;br /&gt;
		if &#039;y&#039; == len_p then													-- because allowed by MOS:DATEUNIFY (sort of) range dates and My dates not reformatted&lt;br /&gt;
			format = &#039;ymd&#039;;														-- override {{use xxx dates}}&lt;br /&gt;
		elseif (not is_set(len_a)) or (len_p == len_a) then						-- no access-/archive-date length specified or same length as publication dates then&lt;br /&gt;
			len_a = len_p;														-- in case len_a not set&lt;br /&gt;
		end&lt;br /&gt;
	end																			-- else only publication dates and they are long&lt;br /&gt;
&lt;br /&gt;
	for param_name, param_val in pairs (date_parameters_list) do				-- for each date-holding parameter in the list&lt;br /&gt;
		if is_set (param_val.val) then											-- if the parameter has a value&lt;br /&gt;
			if not (not all and in_array (param_name, {&#039;access-date&#039;, &#039;archive-date&#039;})) then	-- skip access- or archive-date unless format is xxx-all; yeah, ugly; TODO: find a better way&lt;br /&gt;
				for pattern_idx, pattern in pairs (patterns) do&lt;br /&gt;
					if mw.ustring.match (param_val.val, pattern[1]) then&lt;br /&gt;
						if all and in_array (param_name, {&#039;access-date&#039;, &#039;archive-date&#039;}) then	-- if this date is an access- or archive-date&lt;br /&gt;
							new_date = reformatter (param_val.val, pattern_idx, ((&#039;y&#039; == len_a) and &#039;ymd&#039;) or format, len_a);	-- choose ymd or dmy/mdy according to len_a setting&lt;br /&gt;
						else													-- all other dates&lt;br /&gt;
							new_date = reformatter (param_val.val, pattern_idx, format, len_p);&lt;br /&gt;
						end&lt;br /&gt;
						&lt;br /&gt;
						if new_date then										-- set when date was reformatted&lt;br /&gt;
							date_parameters_list[param_name].val = new_date;	-- update date in date list&lt;br /&gt;
							result = true;										-- and announce that changes have been made&lt;br /&gt;
						end&lt;br /&gt;
					end	-- if&lt;br /&gt;
				end		-- for&lt;br /&gt;
			end			-- if&lt;br /&gt;
		end				-- if&lt;br /&gt;
	end					-- for&lt;br /&gt;
	return result;																-- declare boolean result and done&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; D A T E _ H Y P H E N _ T O _ D A S H &amp;gt;----------------------------------------&lt;br /&gt;
&lt;br /&gt;
Loops through the list of date-holding parameters and converts any hyphen to an ndash.  Not called if the cs1|2&lt;br /&gt;
template has any date errors.&lt;br /&gt;
&lt;br /&gt;
Modifies the date_parameters_list and returns true if hyphens are replaced, else returns false.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function date_hyphen_to_dash (date_parameters_list)&lt;br /&gt;
	local result = false;&lt;br /&gt;
	local n;&lt;br /&gt;
	for param_name, param_val in pairs(date_parameters_list) do					-- for each date-holding parameter in the list&lt;br /&gt;
		if is_set (param_val.val) and&lt;br /&gt;
			not mw.ustring.match (param_val.val, patterns.ymd[1]) then			-- for those that are not ymd dates (ustring because here digits may not be Western)&lt;br /&gt;
				param_val.val, n = param_val.val:gsub (&#039;%-&#039;, &#039;–&#039;);				-- replace any hyphen with ndash&lt;br /&gt;
				if 0 ~= n then&lt;br /&gt;
					date_parameters_list[param_name].val = param_val.val;		-- update the list&lt;br /&gt;
					result = true;&lt;br /&gt;
				end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return result;																-- so we know if any hyphens were replaced&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[-------------------------&amp;lt; D A T E _ N A M E _ X L A T E &amp;gt;------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Attempts to translate English date names to local-language date names using names supplied by MediaWiki&#039;s&lt;br /&gt;
date parser function.  This is simple name-for-name replacement and may not work for all languages.&lt;br /&gt;
&lt;br /&gt;
if xlat_dig is true, this function will also translate Western (English) digits to the local language&#039;s digits.&lt;br /&gt;
This will also translate ymd dates.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function date_name_xlate (date_parameters_list, xlt_dig)&lt;br /&gt;
	local xlate;&lt;br /&gt;
	local mode;																	-- long or short month names&lt;br /&gt;
	local modified = false;&lt;br /&gt;
	local date;&lt;br /&gt;
	&lt;br /&gt;
	local sources_t = {&lt;br /&gt;
		{cfg.date_names.en.long, cfg.date_names.inv_local_long},				-- for translating long English month names to long local month names&lt;br /&gt;
		{cfg.date_names.en.short, cfg.date_names.inv_local_short},				-- short month names&lt;br /&gt;
		{cfg.date_names.en.quarter, cfg.date_names.inv_local_quarter},			-- quarter date names&lt;br /&gt;
		{cfg.date_names.en.season, cfg.date_names.inv_local_season},			-- season date nam&lt;br /&gt;
		{cfg.date_names.en.named, cfg.date_names.inv_local_named},				-- named dates&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
	local function is_xlateable (month)											-- local function to get local date name that replaces existing English-language date name&lt;br /&gt;
		for _, date_names_t in ipairs (sources_t) do							-- for each sequence table in date_names_t&lt;br /&gt;
			if date_names_t[1][month] then										-- if date name is English month (long or short), quarter, season or named and&lt;br /&gt;
				if date_names_t[2][date_names_t[1][month]] then					-- if there is a matching local date name&lt;br /&gt;
					return date_names_t[2][date_names_t[1][month]];				-- return the local date name&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	for param_name, param_val in pairs(date_parameters_list) do					-- for each date-holding parameter in the list&lt;br /&gt;
		if is_set(param_val.val) then											-- if the parameter has a value&lt;br /&gt;
			date = param_val.val;&lt;br /&gt;
			for month in mw.ustring.gmatch (date, &#039;[%a ]+&#039;) do					-- iterate through all date names in the date (single date or date range)&lt;br /&gt;
				month = mw.text.trim (month);									-- this because quarterly dates contain whitespace&lt;br /&gt;
				xlate = is_xlateable (month);									-- get translate &amp;lt;month&amp;gt;; returns translation or nil&lt;br /&gt;
				&lt;br /&gt;
--				if cfg.date_names.en.long[month] then							-- long month dates&lt;br /&gt;
--					if cfg.date_names.inv_local_long[cfg.date_names.en.long[month]] then&lt;br /&gt;
--						xlate = cfg.date_names.inv_local_long[cfg.date_names.en.long[month]];&lt;br /&gt;
--					end&lt;br /&gt;
----					mode = &#039;F&#039;;													-- English name is long so use long local name&lt;br /&gt;
--				elseif cfg.date_names.en.short[month] then						-- short month dates&lt;br /&gt;
--					if cfg.date_names.inv_local_short[cfg.date_names.en.short[month]] then&lt;br /&gt;
--						xlate = cfg.date_names.inv_local_short[cfg.date_names.en.short[month]];&lt;br /&gt;
--					end&lt;br /&gt;
----					mode = &#039;M&#039;;													-- English name is short so use short local name&lt;br /&gt;
--				elseif cfg.date_names.en.quarter[month] then					-- quarter dates&lt;br /&gt;
--					if cfg.date_names.inv_local_quarter[cfg.date_names.en.quarter[month]] then&lt;br /&gt;
--						xlate = cfg.date_names.inv_local_quarter[cfg.date_names.en.quarter[month]];&lt;br /&gt;
--					end&lt;br /&gt;
--				elseif cfg.date_names.en.season[month] then						-- season dates&lt;br /&gt;
--					if cfg.date_names.inv_local_season[cfg.date_names.en.season[month]] then&lt;br /&gt;
--						xlate = cfg.date_names.inv_local_season[cfg.date_names.en.season[month]];&lt;br /&gt;
--					end&lt;br /&gt;
--				elseif cfg.date_names.en.named[month] then						-- named dates&lt;br /&gt;
--					if cfg.date_names.inv_local_named[cfg.date_names.en.named[month]] then&lt;br /&gt;
--						xlate = cfg.date_names.inv_local_named[cfg.date_names.en.named[month]];&lt;br /&gt;
--					end&lt;br /&gt;
--				else&lt;br /&gt;
--					xlate=nil;													-- not an English month name; could be local language month name&lt;br /&gt;
----					mode = nil;													-- not an English month name; could be local language month name or an English season name&lt;br /&gt;
--				end&lt;br /&gt;
&lt;br /&gt;
				if xlate then		&lt;br /&gt;
--				if mode then													-- might be a season&lt;br /&gt;
--					xlate = lang_object:formatDate(mode, &#039;1&#039; .. month);			-- translate the month name to this local language&lt;br /&gt;
					date = mw.ustring.gsub (date, month, xlate);				-- replace the English with the translation&lt;br /&gt;
					date_parameters_list[param_name].val = date;				-- save the translated date&lt;br /&gt;
					modified = true;&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
&lt;br /&gt;
			if xlt_dig then														-- shall we also translate digits?&lt;br /&gt;
				date = date:gsub (&#039;%d&#039;, cfg.date_names.xlate_digits);			-- translate digits from Western to &#039;local digits&#039;&lt;br /&gt;
				date_parameters_list[param_name].val = date;					-- save the translated date&lt;br /&gt;
				modified = true;&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return modified;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S E T _ S E L E C T E D _ M O D U L E S &amp;gt;--------------------------------------&lt;br /&gt;
&lt;br /&gt;
Sets local imported functions table to same (live or sandbox) as that used by the other modules.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function set_selected_modules (cfg_table_ptr, utilities_page_ptr)&lt;br /&gt;
	add_prop_cat = utilities_page_ptr.add_prop_cat ;							-- import functions from selected Module:Citation/CS1/Utilities module&lt;br /&gt;
	is_set = utilities_page_ptr.is_set;&lt;br /&gt;
	in_array = utilities_page_ptr.in_array;&lt;br /&gt;
	set_message = utilities_page_ptr.set_message;&lt;br /&gt;
	substitute = utilities_page_ptr.substitute;&lt;br /&gt;
	wrap_style = utilities_page_ptr.wrap_style;&lt;br /&gt;
&lt;br /&gt;
	cfg = cfg_table_ptr;														-- import tables from selected Module:Citation/CS1/Configuration&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; E X P O R T E D   F U N C T I O N S &amp;gt;------------------------------------------&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
return {																		-- return exported functions&lt;br /&gt;
	dates = dates,&lt;br /&gt;
	year_date_check = year_date_check,&lt;br /&gt;
	reformat_dates = reformat_dates,&lt;br /&gt;
	date_hyphen_to_dash = date_hyphen_to_dash,&lt;br /&gt;
	date_name_xlate = date_name_xlate,&lt;br /&gt;
	set_selected_modules = set_selected_modules&lt;br /&gt;
	}&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Modul:Citation/CS1/Configuration&amp;diff=1521</id>
		<title>Modul:Citation/CS1/Configuration</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Modul:Citation/CS1/Configuration&amp;diff=1521"/>
		<updated>2022-08-12T16:59:11Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;local lang_obj = mw.language.getContentLanguage();								-- make a language object for the local language; used here for languages and dates &lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; U N C A T E G O R I Z E D _ N A M E S P A C E S &amp;gt;------------------------------&lt;br /&gt;
&lt;br /&gt;
List of namespaces that should not be included in citation error categories.&lt;br /&gt;
Same as setting notracking = true by default.&lt;br /&gt;
&lt;br /&gt;
Note: Namespace names should use underscores instead of spaces.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local uncategorized_namespaces = { &#039;User&#039;, &#039;Talk&#039;, &#039;User_talk&#039;, &#039;Wikipedia_talk&#039;,&lt;br /&gt;
	&#039;File_talk&#039;, &#039;Template_talk&#039;, &#039;Help_talk&#039;, &#039;Category_talk&#039;, &#039;Portal_talk&#039;,&lt;br /&gt;
	&#039;Book_talk&#039;, &#039;Draft_talk&#039;, &#039;Education_Program_talk&#039;, &#039;Module_talk&#039;, &#039;MediaWiki_talk&#039; };&lt;br /&gt;
local uncategorized_subpages = {&#039;/[Ss]andbox&#039;, &#039;/[Tt]estcases&#039;, &#039;/[^/]*[Ll]og&#039;, &#039;/[Aa]rchive&#039;};		-- list of Lua patterns found in page names of pages we should not categorize&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; M E S S A G E S &amp;gt;--------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Translation table&lt;br /&gt;
&lt;br /&gt;
The following contains fixed text that may be output as part of a citation.&lt;br /&gt;
This is separated from the main body to aid in future translations of this&lt;br /&gt;
module.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local messages = {&lt;br /&gt;
	[&#039;agency&#039;] = &#039;$1 $2&#039;,														-- $1 is sepc, $2 is agency&lt;br /&gt;
	[&#039;archived-dead&#039;] = &#039;Archived from $1 on $2&#039;,&lt;br /&gt;
	[&#039;archived-live&#039;] = &#039;$1 from the original on $2&#039;,&lt;br /&gt;
	[&#039;archived-missing&#039;] = &#039;Archived from the original$1 on $2&#039;,&lt;br /&gt;
	[&#039;archived-unfit&#039;] = &#039;Archived from the original on &#039;,&lt;br /&gt;
	[&#039;archived&#039;] = &#039;Archived&#039;,&lt;br /&gt;
	[&#039;by&#039;] = &#039;By&#039;,																-- contributions to authored works: introduction, foreword, afterword&lt;br /&gt;
	[&#039;cartography&#039;] = &#039;Cartography by $1&#039;,&lt;br /&gt;
	[&#039;editor&#039;] = &#039;ed.&#039;,&lt;br /&gt;
	[&#039;editors&#039;] = &#039;eds.&#039;,&lt;br /&gt;
	[&#039;edition&#039;] = &#039;($1&amp;amp;nbsp;ed.)&#039;,&lt;br /&gt;
	[&#039;episode&#039;] = &#039;Episode $1&#039;,&lt;br /&gt;
	[&#039;et al&#039;] = &#039;et&amp;amp;nbsp;al.&#039;,&lt;br /&gt;
	[&#039;in&#039;] = &#039;In&#039;,																-- edited works&lt;br /&gt;
	[&#039;inactive&#039;] = &#039;inactive&#039;,&lt;br /&gt;
	[&#039;inset&#039;] = &#039;$1 inset&#039;,&lt;br /&gt;
	[&#039;interview&#039;] = &#039;Interviewed by $1&#039;,										&lt;br /&gt;
	[&#039;lay summary&#039;] = &#039;Lay summary&#039;,&lt;br /&gt;
	[&#039;mismatch&#039;] = &#039;&amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1=&amp;lt;/code&amp;gt; / &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$2=&amp;lt;/code&amp;gt; mismatch&#039;,	-- $1 is year param name; $2 is date param name&lt;br /&gt;
	[&#039;newsgroup&#039;] = &#039;[[Usenet newsgroup|Newsgroup]]:&amp;amp;nbsp;$1&#039;,&lt;br /&gt;
	[&#039;notitle&#039;] = &#039;No title&#039;,													-- for |title=(()) and (in the future) |title=none&lt;br /&gt;
	[&#039;original&#039;] = &#039;the original&#039;,&lt;br /&gt;
	[&#039;origdate&#039;] = &#039; [$1]&#039;,&lt;br /&gt;
	[&#039;published&#039;] = &#039; (published $1)&#039;,&lt;br /&gt;
	[&#039;retrieved&#039;] = &#039;Retrieved $1&#039;,&lt;br /&gt;
	[&#039;season&#039;] = &#039;Season $1&#039;,&lt;br /&gt;
	[&#039;section&#039;] = &#039;§&amp;amp;nbsp;$1&#039;,&lt;br /&gt;
	[&#039;sections&#039;] = &#039;§§&amp;amp;nbsp;$1&#039;,&lt;br /&gt;
	[&#039;series&#039;] = &#039;$1 $2&#039;,														-- $1 is sepc, $2 is series&lt;br /&gt;
	[&#039;seriesnum&#039;] = &#039;Series $1&#039;,&lt;br /&gt;
	[&#039;translated&#039;] = &#039;Translated by $1&#039;,&lt;br /&gt;
	[&#039;type&#039;] = &#039; ($1)&#039;,															-- for titletype&lt;br /&gt;
	[&#039;written&#039;] = &#039;Written at $1&#039;,&lt;br /&gt;
&lt;br /&gt;
	[&#039;vol&#039;] = &#039;$1 Vol.&amp;amp;nbsp;$2&#039;,												-- $1 is sepc; bold journal style volume is in presentation{}&lt;br /&gt;
	[&#039;vol-no&#039;] = &#039;$1 Vol.&amp;amp;nbsp;$2, no.&amp;amp;nbsp;$3&#039;,									-- sepc, volume, issue (alternatively insert $1 after $2, but then we&#039;d also have to change capitalization)&lt;br /&gt;
	[&#039;issue&#039;] = &#039;$1 No.&amp;amp;nbsp;$2&#039;,												-- $1 is sepc&lt;br /&gt;
&lt;br /&gt;
	[&#039;j-vol&#039;] = &#039;$1 $2&#039;,														-- sepc, volume; bold journal volume is in presentation{}&lt;br /&gt;
	[&#039;j-issue&#039;] = &#039; ($1)&#039;,&lt;br /&gt;
&lt;br /&gt;
	[&#039;nopp&#039;] = &#039;$1 $2&#039;;															-- page(s) without prefix; $1 is sepc&lt;br /&gt;
&lt;br /&gt;
	[&#039;p-prefix&#039;] = &amp;quot;$1 p.&amp;amp;nbsp;$2&amp;quot;,												-- $1 is sepc&lt;br /&gt;
	[&#039;pp-prefix&#039;] = &amp;quot;$1 pp.&amp;amp;nbsp;$2&amp;quot;,											-- $1 is sepc&lt;br /&gt;
	[&#039;j-page(s)&#039;] = &#039;: $1&#039;,														-- same for page and pages&lt;br /&gt;
&lt;br /&gt;
	[&#039;sheet&#039;] = &#039;$1 Sheet&amp;amp;nbsp;$2&#039;,												-- $1 is sepc&lt;br /&gt;
	[&#039;sheets&#039;] = &#039;$1 Sheets&amp;amp;nbsp;$2&#039;,											-- $1 is sepc&lt;br /&gt;
	[&#039;j-sheet&#039;] = &#039;: Sheet&amp;amp;nbsp;$1&#039;,&lt;br /&gt;
	[&#039;j-sheets&#039;] = &#039;: Sheets&amp;amp;nbsp;$1&#039;,&lt;br /&gt;
	&lt;br /&gt;
	[&#039;language&#039;] = &#039;(in $1)&#039;,&lt;br /&gt;
	[&#039;via&#039;] = &amp;quot; &amp;amp;ndash; via $1&amp;quot;,&lt;br /&gt;
	[&#039;event&#039;] = &#039;Event occurs at&#039;,&lt;br /&gt;
	[&#039;minutes&#039;] = &#039;minutes in&#039;,&lt;br /&gt;
	&lt;br /&gt;
	-- Determines the location of the help page&lt;br /&gt;
	[&#039;help page link&#039;] = &#039;Help:CS1 errors&#039;,&lt;br /&gt;
	[&#039;help page label&#039;] = &#039;help&#039;,&lt;br /&gt;
	&lt;br /&gt;
	-- categories&lt;br /&gt;
	[&#039;cat wikilink&#039;] = &#039;[[Category:$1]]&#039;,										-- $1 is the category name&lt;br /&gt;
	[&#039;:cat wikilink&#039;] = &#039;[[:Category:$1|link]]&#039;,								-- category name as maintenance message wikilink; $1 is the category name&lt;br /&gt;
&lt;br /&gt;
	-- Internal errors (should only occur if configuration is bad)&lt;br /&gt;
	[&#039;undefined_error&#039;] = &#039;Called with an undefined error condition&#039;,&lt;br /&gt;
	[&#039;unknown_ID_key&#039;] = &#039;Unrecognized ID key: &#039;,								-- an ID key in id_handlers not found in ~/Identifiers func_map{}&lt;br /&gt;
	[&#039;unknown_ID_access&#039;] = &#039;Unrecognized ID access keyword: &#039;,					-- an ID access keyword in id_handlers not found in keywords_lists[&#039;id-access&#039;]{}&lt;br /&gt;
	[&#039;unknown_argument_map&#039;] = &#039;Argument map not defined for this variable&#039;,&lt;br /&gt;
	[&#039;bare_url_no_origin&#039;] = &#039;Bare URL found but origin indicator is nil or empty&#039;,&lt;br /&gt;
	&lt;br /&gt;
	[&#039;warning_msg_e&#039;] = &#039;&amp;lt;span style=&amp;quot;color:#d33&amp;quot;&amp;gt;One or more &amp;lt;code style=&amp;quot;color: inherit; background: inherit; border: none; padding: inherit;&amp;quot;&amp;gt;&amp;amp;#123;{$1}}&amp;lt;/code&amp;gt; templates have errors&amp;lt;/span&amp;gt;; messages may be hidden ([[Help:CS1_errors#Controlling_error_message_display|help]]).&#039;;	-- $1 is template link&lt;br /&gt;
	[&#039;warning_msg_m&#039;] = &#039;&amp;lt;span style=&amp;quot;color:#3a3&amp;quot;&amp;gt;One or more &amp;lt;code style=&amp;quot;color: inherit; background: inherit; border: none; padding: inherit;&amp;quot;&amp;gt;&amp;amp;#123;{$1}}&amp;lt;/code&amp;gt; templates have maintenance messages&amp;lt;/span&amp;gt;; messages may be hidden ([[Help:CS1_errors#Controlling_error_message_display|help]]).&#039;;	-- $1 is template link&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; C I T A T I O N _ C L A S S _ M A P &amp;gt;------------------------------------------&lt;br /&gt;
&lt;br /&gt;
this table maps the value assigned to |CitationClass= in the cs1|2 templates to the canonical template name when&lt;br /&gt;
the value assigned to |CitationClass= is different from the canonical template name.  |CitationClass= values are&lt;br /&gt;
used as class attributes in the &amp;lt;cite&amp;gt; tag that encloses the citation so these names may not contain spaces while&lt;br /&gt;
the canonical template name may.  These names are used in warning_msg_e and warning_msg_m to create links to the&lt;br /&gt;
template&#039;s documentation when an article is displayed in preivew mode.&lt;br /&gt;
&lt;br /&gt;
Most cs1|2 template |CitationClass= values at en.wiki match their canonical template names so are not listed here.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
	local citation_class_map_t = {												-- TODO: if kept, these and all other config.CitationClass &#039;names&#039; require some sort of i18n&lt;br /&gt;
		[&#039;audio-visual&#039;] = &#039;AV media&#039;,											-- TODO: move to ~/Configuration&lt;br /&gt;
		[&#039;AV-media-notes&#039;] = &#039;AV media notes&#039;,&lt;br /&gt;
		[&#039;encyclopaedia&#039;] = &#039;encyclopedia&#039;,&lt;br /&gt;
		[&#039;mailinglist&#039;] = &#039;mailing list&#039;,&lt;br /&gt;
		[&#039;pressrelease&#039;] = &#039;press release&#039;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[=[-------------------------&amp;lt; E T _ A L _ P A T T E R N S &amp;gt;--------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
This table provides Lua patterns for the phrase &amp;quot;et al&amp;quot; and variants in name text&lt;br /&gt;
(author, editor, etc.). The main module uses these to identify and emit the &#039;etal&#039; message.&lt;br /&gt;
&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local et_al_patterns = {&lt;br /&gt;
	&amp;quot;[;,]? *[\&amp;quot;&#039;]*%f[%a][Ee][Tt]%.? *[Aa][Ll][%.;,\&amp;quot;&#039;]*$&amp;quot;,						-- variations on the &#039;et al&#039; theme&lt;br /&gt;
	&amp;quot;[;,]? *[\&amp;quot;&#039;]*%f[%a][Ee][Tt]%.? *[Aa][Ll][Ii][AaIi][Ee]?[%.;,\&amp;quot;&#039;]*$&amp;quot;,		-- variations on the &#039;et alia&#039;, &#039;et alii&#039; and &#039;et aliae&#039; themes (false positive &#039;et aliie&#039; unlikely to match)&lt;br /&gt;
	&amp;quot;[;,]? *%f[%a]and [Oo]thers&amp;quot;,												-- an alternative to et al.&lt;br /&gt;
	&amp;quot;%[%[ *[Ee][Tt]%.? *[Aa][Ll]%.? *%]%]&amp;quot;,										-- a wikilinked form&lt;br /&gt;
	&amp;quot;%(%( *[Ee][Tt]%.? *[Aa][Ll]%.? *%)%)&amp;quot;,										-- a double-bracketed form (to counter partial removal of ((...)) syntax)&lt;br /&gt;
	&amp;quot;[%(%[] *[Ee][Tt]%.? *[Aa][Ll]%.? *[%)%]]&amp;quot;,									-- a bracketed form&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; P R E S E N T A T I O N &amp;gt;------------------------&lt;br /&gt;
&lt;br /&gt;
Fixed presentation markup.  Originally part of citation_config.messages it has&lt;br /&gt;
been moved into its own, more semantically correct place.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local presentation = &lt;br /&gt;
	{&lt;br /&gt;
	-- .citation-comment class is specified at Help:CS1_errors#Controlling_error_message_display&lt;br /&gt;
	[&#039;hidden-error&#039;] = &#039;&amp;lt;span class=&amp;quot;cs1-hidden-error citation-comment&amp;quot;&amp;gt;$1&amp;lt;/span&amp;gt;&#039;,&lt;br /&gt;
	[&#039;visible-error&#039;] = &#039;&amp;lt;span class=&amp;quot;cs1-visible-error citation-comment&amp;quot;&amp;gt;$1&amp;lt;/span&amp;gt;&#039;,&lt;br /&gt;
	[&#039;hidden-maint&#039;] = &#039;&amp;lt;span class=&amp;quot;cs1-maint citation-comment&amp;quot;&amp;gt;$1&amp;lt;/span&amp;gt;&#039;,&lt;br /&gt;
	&lt;br /&gt;
	[&#039;accessdate&#039;] = &#039;&amp;lt;span class=&amp;quot;reference-accessdate&amp;quot;&amp;gt;$1$2&amp;lt;/span&amp;gt;&#039;,			-- to allow editors to hide accessdate using personal CSS&lt;br /&gt;
&lt;br /&gt;
	[&#039;bdi&#039;] = &#039;&amp;lt;bdi$1&amp;gt;$2&amp;lt;/bdi&amp;gt;&#039;,												-- bidirectional isolation used with |script-title= and the like&lt;br /&gt;
&lt;br /&gt;
	[&#039;cite&#039;] = &#039;&amp;lt;cite class=&amp;quot;$1&amp;quot;&amp;gt;$2&amp;lt;/cite&amp;gt;&#039;;									-- for use when citation does not have a namelist and |ref= not set so no id=&amp;quot;...&amp;quot; attribute&lt;br /&gt;
	[&#039;cite-id&#039;] = &#039;&amp;lt;cite id=&amp;quot;$1&amp;quot; class=&amp;quot;$2&amp;quot;&amp;gt;$3&amp;lt;/cite&amp;gt;&#039;;							-- for use when when |ref= is set or when citation has a namelist&lt;br /&gt;
&lt;br /&gt;
	[&#039;format&#039;] = &#039; &amp;lt;span class=&amp;quot;cs1-format&amp;quot;&amp;gt;($1)&amp;lt;/span&amp;gt;&#039;,						-- for |format=, |chapter-format=, etc.&lt;br /&gt;
&lt;br /&gt;
	-- various access levels, for |access=, |doi-access=, |arxiv=, ...&lt;br /&gt;
	-- narrow no-break space &amp;amp;#8239; may work better than nowrap CSS. Or not? Browser support?&lt;br /&gt;
&lt;br /&gt;
	[&#039;ext-link-access-signal&#039;] = &#039;&amp;lt;span class=&amp;quot;$1&amp;quot; title=&amp;quot;$2&amp;quot;&amp;gt;$3&amp;lt;/span&amp;gt;&#039;,		-- external link with appropriate lock icon&lt;br /&gt;
		[&#039;free&#039;] = {class=&#039;cs1-lock-free&#039;, title=&#039;Freely accessible&#039;},			-- classes defined in Module:Citation/CS1/styles.css&lt;br /&gt;
		[&#039;registration&#039;] = {class=&#039;cs1-lock-registration&#039;, title=&#039;Free registration required&#039;},&lt;br /&gt;
		[&#039;limited&#039;] = {class=&#039;cs1-lock-limited&#039;, title=&#039;Free access subject to limited trial, subscription normally required&#039;},&lt;br /&gt;
		[&#039;subscription&#039;] = {class=&#039;cs1-lock-subscription&#039;, title=&#039;Paid subscription required&#039;},&lt;br /&gt;
&lt;br /&gt;
	[&#039;interwiki-icon&#039;] = &#039;&amp;lt;span class=&amp;quot;$1&amp;quot; title=&amp;quot;$2&amp;quot;&amp;gt;$3&amp;lt;/span&amp;gt;&#039;,&lt;br /&gt;
		[&#039;class-wikisource&#039;] = &#039;cs1-ws-icon&#039;,&lt;br /&gt;
&lt;br /&gt;
	[&#039;italic-title&#039;] = &amp;quot;&#039;&#039;$1&#039;&#039;&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
	[&#039;kern-left&#039;] = &#039;&amp;lt;span class=&amp;quot;cs1-kern-left&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;$1&#039;,					-- spacing to use when title contains leading single or double quote mark&lt;br /&gt;
	[&#039;kern-right&#039;] = &#039;$1&amp;lt;span class=&amp;quot;cs1-kern-right&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;,					-- spacing to use when title contains trailing single or double quote mark&lt;br /&gt;
&lt;br /&gt;
	[&#039;nowrap1&#039;] = &#039;&amp;lt;span class=&amp;quot;nowrap&amp;quot;&amp;gt;$1&amp;lt;/span&amp;gt;&#039;,								-- for nowrapping an item: &amp;lt;span ...&amp;gt;yyyy-mm-dd&amp;lt;/span&amp;gt;&lt;br /&gt;
	[&#039;nowrap2&#039;] = &#039;&amp;lt;span class=&amp;quot;nowrap&amp;quot;&amp;gt;$1&amp;lt;/span&amp;gt; $2&#039;,							-- for nowrapping portions of an item: &amp;lt;span ...&amp;gt;dd mmmm&amp;lt;/span&amp;gt; yyyy (note white space)&lt;br /&gt;
&lt;br /&gt;
	[&#039;ocins&#039;] = &#039;&amp;lt;span title=&amp;quot;$1&amp;quot; class=&amp;quot;Z3988&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;,&lt;br /&gt;
	&lt;br /&gt;
	[&#039;parameter&#039;] = &#039;&amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1=&amp;lt;/code&amp;gt;&#039;,&lt;br /&gt;
	&lt;br /&gt;
	[&#039;ps_cs1&#039;] = &#039;.&#039;;															-- CS1 style postscript (terminal) character&lt;br /&gt;
	[&#039;ps_cs2&#039;] = &#039;&#039;;															-- CS2 style postscript (terminal) character (empty string)&lt;br /&gt;
&lt;br /&gt;
	[&#039;quoted-text&#039;] = &#039;&amp;lt;q&amp;gt;$1&amp;lt;/q&amp;gt;&#039;,												-- for wrapping |quote= content&lt;br /&gt;
	[&#039;quoted-title&#039;] = &#039;&amp;quot;$1&amp;quot;&#039;,&lt;br /&gt;
&lt;br /&gt;
	[&#039;sep_cs1&#039;] = &#039;.&#039;,															-- CS1 element separator&lt;br /&gt;
	[&#039;sep_cs2&#039;] = &#039;,&#039;,															-- CS2 separator&lt;br /&gt;
	[&#039;sep_nl&#039;] = &#039;;&#039;,															-- CS1|2 style name-list separator between names is a semicolon&lt;br /&gt;
	[&#039;sep_nl_and&#039;] = &#039; and &#039;,													-- used as last nl sep when |name-list-style=and and list has 2 items&lt;br /&gt;
	[&#039;sep_nl_end&#039;] = &#039;; and &#039;,													-- used as last nl sep when |name-list-style=and and list has 3+ names&lt;br /&gt;
	[&#039;sep_name&#039;] = &#039;, &#039;,														-- CS1|2 style last/first separator is &amp;lt;comma&amp;gt;&amp;lt;space&amp;gt;&lt;br /&gt;
	[&#039;sep_nl_vanc&#039;] = &#039;,&#039;,														-- Vancouver style name-list separator between authors is a comma&lt;br /&gt;
	[&#039;sep_name_vanc&#039;] = &#039; &#039;,													-- Vancouver style last/first separator is a space&lt;br /&gt;
&lt;br /&gt;
	[&#039;sep_list&#039;] = &#039;, &#039;,														-- used for |language= when list has 3+ items except for last sep which uses sep_list_end&lt;br /&gt;
	[&#039;sep_list_pair&#039;] = &#039; and &#039;,												-- used for |language= when list has 2 items&lt;br /&gt;
	[&#039;sep_list_end&#039;] = &#039;, and &#039;,												-- used as last list sep for |language= when list has 3+ items&lt;br /&gt;
	&lt;br /&gt;
	[&#039;trans-italic-title&#039;] = &amp;quot;&amp;amp;#91;&#039;&#039;$1&#039;&#039;&amp;amp;#93;&amp;quot;,&lt;br /&gt;
	[&#039;trans-quoted-title&#039;] = &amp;quot;&amp;amp;#91;$1&amp;amp;#93;&amp;quot;,									-- for |trans-title= and |trans-quote=&lt;br /&gt;
	[&#039;vol-bold&#039;] = &#039;$1 &amp;lt;b&amp;gt;$2&amp;lt;/b&amp;gt;&#039;,												-- sepc, volume; for bold journal cites; for other cites [&#039;vol&#039;] in messages{}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
--[[--------------------------&amp;lt; A L I A S E S &amp;gt;---------------------------------&lt;br /&gt;
&lt;br /&gt;
Aliases table for commonly passed parameters.&lt;br /&gt;
&lt;br /&gt;
Parameter names on the right side in the assignments in this table must have been&lt;br /&gt;
defined in the Whitelist before they will be recognized as valid parameter names&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local aliases = {&lt;br /&gt;
	[&#039;AccessDate&#039;] = {&#039;access-date&#039;, &#039;accessdate&#039;},								-- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;Agency&#039;] = &#039;agency&#039;,&lt;br /&gt;
	[&#039;ArchiveDate&#039;] = {&#039;archive-date&#039;, &#039;archivedate&#039;},							-- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;ArchiveFormat&#039;] = &#039;archive-format&#039;,&lt;br /&gt;
	[&#039;ArchiveURL&#039;] = {&#039;archive-url&#039;, &#039;archiveurl&#039;},								-- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;ASINTLD&#039;] = &#039;asin-tld&#039;,&lt;br /&gt;
	[&#039;At&#039;] = &#039;at&#039;,																-- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;Authors&#039;] = {&#039;authors&#039;, &#039;people&#039;, &#039;credits&#039;},&lt;br /&gt;
	[&#039;BookTitle&#039;] = {&#039;book-title&#039;, &#039;booktitle&#039;},&lt;br /&gt;
	[&#039;Cartography&#039;] = &#039;cartography&#039;,&lt;br /&gt;
	[&#039;Chapter&#039;] = {&#039;chapter&#039;, &#039;contribution&#039;, &#039;entry&#039;, &#039;article&#039;, &#039;section&#039;},&lt;br /&gt;
	[&#039;ChapterFormat&#039;] = {&#039;chapter-format&#039;, &#039;contribution-format&#039;, &#039;entry-format&#039;,&lt;br /&gt;
		&#039;article-format&#039;, &#039;section-format&#039;};&lt;br /&gt;
	[&#039;ChapterURL&#039;] = {&#039;chapter-url&#039;, &#039;contribution-url&#039;, &#039;entry-url&#039;, &#039;article-url&#039;, &#039;section-url&#039;, &#039;chapterurl&#039;},	-- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;ChapterUrlAccess&#039;] = {&#039;chapter-url-access&#039;, &#039;contribution-url-access&#039;,&lt;br /&gt;
		&#039;entry-url-access&#039;, &#039;article-url-access&#039;, &#039;section-url-access&#039;},		-- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;Class&#039;] = &#039;class&#039;,														-- cite arxiv and arxiv identifier&lt;br /&gt;
	[&#039;Collaboration&#039;] = &#039;collaboration&#039;,&lt;br /&gt;
	[&#039;Conference&#039;] = {&#039;conference&#039;, &#039;event&#039;},&lt;br /&gt;
	[&#039;ConferenceFormat&#039;] = &#039;conference-format&#039;,&lt;br /&gt;
	[&#039;ConferenceURL&#039;] = &#039;conference-url&#039;,										-- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;Date&#039;] = {&#039;date&#039;, &#039;air-date&#039;, &#039;airdate&#039;},									-- air-date and airdate for cite episode and cite serial only&lt;br /&gt;
	[&#039;Degree&#039;] = &#039;degree&#039;,&lt;br /&gt;
	[&#039;DF&#039;] = &#039;df&#039;,&lt;br /&gt;
	[&#039;DisplayAuthors&#039;] = {&#039;display-authors&#039;, &#039;display-subjects&#039;},&lt;br /&gt;
	[&#039;DisplayContributors&#039;] = &#039;display-contributors&#039;,&lt;br /&gt;
	[&#039;DisplayEditors&#039;] = &#039;display-editors&#039;,&lt;br /&gt;
	[&#039;DisplayInterviewers&#039;] = &#039;display-interviewers&#039;,&lt;br /&gt;
	[&#039;DisplayTranslators&#039;] = &#039;display-translators&#039;,&lt;br /&gt;
	[&#039;Docket&#039;] = &#039;docket&#039;,&lt;br /&gt;
	[&#039;DoiBroken&#039;] = &#039;doi-broken-date&#039;,&lt;br /&gt;
	[&#039;Edition&#039;] = &#039;edition&#039;,&lt;br /&gt;
	[&#039;Embargo&#039;] = &#039;pmc-embargo-date&#039;,&lt;br /&gt;
	[&#039;Encyclopedia&#039;] = {&#039;encyclopedia&#039;, &#039;encyclopaedia&#039;, &#039;dictionary&#039;},			-- cite encyclopedia only&lt;br /&gt;
	[&#039;Episode&#039;] = &#039;episode&#039;,													-- cite serial only TODO: make available to cite episode?&lt;br /&gt;
	[&#039;Format&#039;] = &#039;format&#039;,&lt;br /&gt;
	[&#039;ID&#039;] = {&#039;id&#039;, &#039;ID&#039;},&lt;br /&gt;
	[&#039;Inset&#039;] = &#039;inset&#039;,&lt;br /&gt;
	[&#039;Issue&#039;] = {&#039;issue&#039;, &#039;number&#039;},&lt;br /&gt;
	[&#039;Language&#039;] = {&#039;language&#039;, &#039;lang&#039;},&lt;br /&gt;
	[&#039;LayDate&#039;] = &#039;lay-date&#039;,&lt;br /&gt;
	[&#039;LayFormat&#039;] = &#039;lay-format&#039;,&lt;br /&gt;
	[&#039;LaySource&#039;] = &#039;lay-source&#039;,&lt;br /&gt;
	[&#039;LayURL&#039;] = &#039;lay-url&#039;,&lt;br /&gt;
	[&#039;MailingList&#039;] = {&#039;mailing-list&#039;, &#039;mailinglist&#039;},							-- cite mailing list only&lt;br /&gt;
	[&#039;Map&#039;] = &#039;map&#039;,															-- cite map only&lt;br /&gt;
	[&#039;MapFormat&#039;] = &#039;map-format&#039;,												-- cite map only&lt;br /&gt;
	[&#039;MapURL&#039;] = {&#039;map-url&#039;, &#039;mapurl&#039;},											-- cite map only -- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;MapUrlAccess&#039;] = &#039;map-url-access&#039;,										-- cite map only -- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;Minutes&#039;] = &#039;minutes&#039;,&lt;br /&gt;
	[&#039;Mode&#039;] = &#039;mode&#039;,&lt;br /&gt;
	[&#039;NameListStyle&#039;] = &#039;name-list-style&#039;,&lt;br /&gt;
	[&#039;Network&#039;] = &#039;network&#039;,&lt;br /&gt;
	[&#039;Newsgroup&#039;] = &#039;newsgroup&#039;,												-- cite newsgroup only&lt;br /&gt;
	[&#039;NoPP&#039;] = {&#039;no-pp&#039;, &#039;nopp&#039;},&lt;br /&gt;
	[&#039;NoTracking&#039;] = {&#039;no-tracking&#039;, &#039;template-doc-demo&#039;},&lt;br /&gt;
	[&#039;Number&#039;] = &#039;number&#039;,														-- this case only for cite techreport&lt;br /&gt;
	[&#039;OrigDate&#039;] = {&#039;orig-date&#039;, &#039;orig-year&#039;, &#039;origyear&#039;},&lt;br /&gt;
	[&#039;Others&#039;] = &#039;others&#039;,&lt;br /&gt;
	[&#039;Page&#039;] = {&#039;page&#039;, &#039;p&#039;},													-- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;Pages&#039;] = {&#039;pages&#039;, &#039;pp&#039;},												-- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;Periodical&#039;] = {&#039;journal&#039;, &#039;magazine&#039;, &#039;newspaper&#039;, &#039;periodical&#039;, &#039;website&#039;, &#039;work&#039;},&lt;br /&gt;
	[&#039;Place&#039;] = {&#039;place&#039;, &#039;location&#039;},&lt;br /&gt;
	[&#039;PostScript&#039;] = &#039;postscript&#039;,&lt;br /&gt;
	[&#039;PublicationDate&#039;] = {&#039;publication-date&#039;, &#039;publicationdate&#039;},&lt;br /&gt;
	[&#039;PublicationPlace&#039;] = {&#039;publication-place&#039;, &#039;publicationplace&#039;},&lt;br /&gt;
	[&#039;PublisherName&#039;] = {&#039;publisher&#039;, &#039;institution&#039;},&lt;br /&gt;
	[&#039;Quote&#039;] = {&#039;quote&#039;, &#039;quotation&#039;},&lt;br /&gt;
	[&#039;QuotePage&#039;] = &#039;quote-page&#039;,&lt;br /&gt;
	[&#039;QuotePages&#039;] = &#039;quote-pages&#039;,&lt;br /&gt;
	[&#039;Ref&#039;] = &#039;ref&#039;,&lt;br /&gt;
	[&#039;Scale&#039;] = &#039;scale&#039;,&lt;br /&gt;
	[&#039;ScriptChapter&#039;] = {&#039;script-chapter&#039;, &#039;script-contribution&#039;, &#039;script-entry&#039;,&lt;br /&gt;
		&#039;script-article&#039;, &#039;script-section&#039;},&lt;br /&gt;
	[&#039;ScriptMap&#039;] = &#039;script-map&#039;,&lt;br /&gt;
	[&#039;ScriptPeriodical&#039;] = {&#039;script-journal&#039;, &#039;script-magazine&#039;, &#039;script-newspaper&#039;,&lt;br /&gt;
		&#039;script-periodical&#039;, &#039;script-website&#039;, &#039;script-work&#039;},&lt;br /&gt;
	[&#039;ScriptQuote&#039;] = &#039;script-quote&#039;,&lt;br /&gt;
	[&#039;ScriptTitle&#039;] = &#039;script-title&#039;,											-- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;Season&#039;] = &#039;season&#039;,&lt;br /&gt;
	[&#039;Sections&#039;] = &#039;sections&#039;,													-- cite map only&lt;br /&gt;
	[&#039;Series&#039;] = {&#039;series&#039;, &#039;version&#039;},&lt;br /&gt;
	[&#039;SeriesLink&#039;] = {&#039;series-link&#039;, &#039;serieslink&#039;},&lt;br /&gt;
	[&#039;SeriesNumber&#039;] = {&#039;series-number&#039;, &#039;series-no&#039;},&lt;br /&gt;
	[&#039;Sheet&#039;] = &#039;sheet&#039;,														-- cite map only&lt;br /&gt;
	[&#039;Sheets&#039;] = &#039;sheets&#039;,														-- cite map only&lt;br /&gt;
	[&#039;Station&#039;] = &#039;station&#039;,&lt;br /&gt;
	[&#039;Time&#039;] = &#039;time&#039;,&lt;br /&gt;
	[&#039;TimeCaption&#039;] = &#039;time-caption&#039;,&lt;br /&gt;
	[&#039;Title&#039;] = &#039;title&#039;,														-- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;TitleLink&#039;] = {&#039;title-link&#039;, &#039;episode-link&#039;, &#039;episodelink&#039;},				-- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;TitleNote&#039;] = &#039;department&#039;,&lt;br /&gt;
	[&#039;TitleType&#039;] = {&#039;type&#039;, &#039;medium&#039;},&lt;br /&gt;
	[&#039;TransChapter&#039;] = {&#039;trans-article&#039;, &#039;trans-chapter&#039;, &#039;trans-contribution&#039;,&lt;br /&gt;
		&#039;trans-entry&#039;, &#039;trans-section&#039;},&lt;br /&gt;
	[&#039;Transcript&#039;] = &#039;transcript&#039;,&lt;br /&gt;
	[&#039;TranscriptFormat&#039;] = &#039;transcript-format&#039;,	&lt;br /&gt;
	[&#039;TranscriptURL&#039;] = {&#039;transcript-url&#039;, &#039;transcripturl&#039;},					-- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;TransMap&#039;] = &#039;trans-map&#039;,													-- cite map only&lt;br /&gt;
	[&#039;TransPeriodical&#039;] = {&#039;trans-journal&#039;, &#039;trans-magazine&#039;, &#039;trans-newspaper&#039;,&lt;br /&gt;
		&#039;trans-periodical&#039;, &#039;trans-website&#039;, &#039;trans-work&#039;},&lt;br /&gt;
	[&#039;TransQuote&#039;] = &#039;trans-quote&#039;,&lt;br /&gt;
	[&#039;TransTitle&#039;] = &#039;trans-title&#039;,												-- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;URL&#039;] = {&#039;url&#039;, &#039;URL&#039;},													-- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;UrlAccess&#039;] = &#039;url-access&#039;,												-- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;UrlStatus&#039;] = &#039;url-status&#039;,												-- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;Vauthors&#039;] = &#039;vauthors&#039;,&lt;br /&gt;
	[&#039;Veditors&#039;] = &#039;veditors&#039;,&lt;br /&gt;
	[&#039;Via&#039;] = &#039;via&#039;,&lt;br /&gt;
	[&#039;Volume&#039;] = &#039;volume&#039;,&lt;br /&gt;
	[&#039;Year&#039;] = &#039;year&#039;,&lt;br /&gt;
&lt;br /&gt;
	[&#039;AuthorList-First&#039;] = {&amp;quot;first#&amp;quot;, &amp;quot;author-first#&amp;quot;, &amp;quot;author#-first&amp;quot;, &amp;quot;given#&amp;quot;,&lt;br /&gt;
		&amp;quot;author-given#&amp;quot;, &amp;quot;author#-given&amp;quot;},&lt;br /&gt;
	[&#039;AuthorList-Last&#039;] = {&amp;quot;last#&amp;quot;, &amp;quot;author-last#&amp;quot;, &amp;quot;author#-last&amp;quot;, &amp;quot;surname#&amp;quot;,&lt;br /&gt;
		&amp;quot;author-surname#&amp;quot;, &amp;quot;author#-surname&amp;quot;, &amp;quot;author#&amp;quot;, &amp;quot;subject#&amp;quot;, &#039;host#&#039;},&lt;br /&gt;
	[&#039;AuthorList-Link&#039;] = {&amp;quot;author-link#&amp;quot;, &amp;quot;author#-link&amp;quot;, &amp;quot;subject-link#&amp;quot;,&lt;br /&gt;
		&amp;quot;subject#-link&amp;quot;, &amp;quot;authorlink#&amp;quot;, &amp;quot;author#link&amp;quot;},&lt;br /&gt;
	[&#039;AuthorList-Mask&#039;] = {&amp;quot;author-mask#&amp;quot;, &amp;quot;author#-mask&amp;quot;, &amp;quot;subject-mask#&amp;quot;, &amp;quot;subject#-mask&amp;quot;},&lt;br /&gt;
&lt;br /&gt;
	[&#039;ContributorList-First&#039;] = {&#039;contributor-first#&#039;, &#039;contributor#-first&#039;,&lt;br /&gt;
		&#039;contributor-given#&#039;, &#039;contributor#-given&#039;},&lt;br /&gt;
	[&#039;ContributorList-Last&#039;] = {&#039;contributor-last#&#039;, &#039;contributor#-last&#039;,&lt;br /&gt;
		&#039;contributor-surname#&#039;, &#039;contributor#-surname&#039;, &#039;contributor#&#039;},&lt;br /&gt;
	[&#039;ContributorList-Link&#039;] = {&#039;contributor-link#&#039;, &#039;contributor#-link&#039;},&lt;br /&gt;
	[&#039;ContributorList-Mask&#039;] = {&#039;contributor-mask#&#039;, &#039;contributor#-mask&#039;},&lt;br /&gt;
&lt;br /&gt;
	[&#039;EditorList-First&#039;] = {&amp;quot;editor-first#&amp;quot;, &amp;quot;editor#-first&amp;quot;, &amp;quot;editor-given#&amp;quot;, &amp;quot;editor#-given&amp;quot;},&lt;br /&gt;
	[&#039;EditorList-Last&#039;] = {&amp;quot;editor-last#&amp;quot;, &amp;quot;editor#-last&amp;quot;, &amp;quot;editor-surname#&amp;quot;,&lt;br /&gt;
		&amp;quot;editor#-surname&amp;quot;, &amp;quot;editor#&amp;quot;},&lt;br /&gt;
	[&#039;EditorList-Link&#039;] = {&amp;quot;editor-link#&amp;quot;, &amp;quot;editor#-link&amp;quot;},&lt;br /&gt;
	[&#039;EditorList-Mask&#039;] = {&amp;quot;editor-mask#&amp;quot;, &amp;quot;editor#-mask&amp;quot;},&lt;br /&gt;
	&lt;br /&gt;
	[&#039;InterviewerList-First&#039;] = {&#039;interviewer-first#&#039;, &#039;interviewer#-first&#039;,&lt;br /&gt;
		&#039;interviewer-given#&#039;, &#039;interviewer#-given&#039;},&lt;br /&gt;
	[&#039;InterviewerList-Last&#039;] = {&#039;interviewer-last#&#039;, &#039;interviewer#-last&#039;,&lt;br /&gt;
		&#039;interviewer-surname#&#039;, &#039;interviewer#-surname&#039;, &#039;interviewer#&#039;},&lt;br /&gt;
	[&#039;InterviewerList-Link&#039;] = {&#039;interviewer-link#&#039;, &#039;interviewer#-link&#039;},&lt;br /&gt;
	[&#039;InterviewerList-Mask&#039;] = {&#039;interviewer-mask#&#039;, &#039;interviewer#-mask&#039;},&lt;br /&gt;
&lt;br /&gt;
	[&#039;TranslatorList-First&#039;] = {&#039;translator-first#&#039;, &#039;translator#-first&#039;,&lt;br /&gt;
		&#039;translator-given#&#039;, &#039;translator#-given&#039;},&lt;br /&gt;
	[&#039;TranslatorList-Last&#039;] = {&#039;translator-last#&#039;, &#039;translator#-last&#039;,&lt;br /&gt;
		&#039;translator-surname#&#039;, &#039;translator#-surname&#039;, &#039;translator#&#039;},&lt;br /&gt;
	[&#039;TranslatorList-Link&#039;] = {&#039;translator-link#&#039;, &#039;translator#-link&#039;},&lt;br /&gt;
	[&#039;TranslatorList-Mask&#039;] = {&#039;translator-mask#&#039;, &#039;translator#-mask&#039;},&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; P U N C T _ S K I P &amp;gt;---------------------------&lt;br /&gt;
&lt;br /&gt;
builds a table of parameter names that the extraneous terminal punctuation check should not check.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local punct_meta_params = {														-- table of aliases[] keys (meta parameters); each key has a table of parameter names for a value&lt;br /&gt;
	&#039;BookTitle&#039;, &#039;Chapter&#039;, &#039;ScriptChapter&#039;, &#039;ScriptTitle&#039;, &#039;Title&#039;, &#039;TransChapter&#039;, &#039;Transcript&#039;, &#039;TransMap&#039;,	&#039;TransTitle&#039;,	-- title-holding parameters&lt;br /&gt;
	&#039;AuthorList-Mask&#039;, &#039;ContributorList-Mask&#039;, &#039;EditorList-Mask&#039;, &#039;InterviewerList-Mask&#039;, &#039;TranslatorList-Mask&#039;,	-- name-list mask may have name separators&lt;br /&gt;
	&#039;PostScript&#039;, &#039;Quote&#039;, &#039;ScriptQuote&#039;, &#039;TransQuote&#039;, &#039;Ref&#039;,											-- miscellaneous&lt;br /&gt;
	&#039;ArchiveURL&#039;, &#039;ChapterURL&#039;, &#039;ConferenceURL&#039;, &#039;LayURL&#039;, &#039;MapURL&#039;, &#039;TranscriptURL&#039;, &#039;URL&#039;,			-- URL-holding parameters&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
local url_meta_params = {														-- table of aliases[] keys (meta parameters); each key has a table of parameter names for a value&lt;br /&gt;
	&#039;ArchiveURL&#039;, &#039;ChapterURL&#039;, &#039;ConferenceURL&#039;, &#039;ID&#039;, &#039;LayURL&#039;, &#039;MapURL&#039;, &#039;TranscriptURL&#039;, &#039;URL&#039;,		-- parameters allowed to hold urls&lt;br /&gt;
	&#039;Page&#039;, &#039;Pages&#039;, &#039;At&#039;, &#039;QuotePage&#039;, &#039;QuotePages&#039;,							-- insource locators allowed to hold urls&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
local function build_skip_table (skip_t, meta_params)&lt;br /&gt;
	for _, meta_param in ipairs (meta_params) do								-- for each meta parameter key&lt;br /&gt;
		local params = aliases[meta_param];										-- get the parameter or the table of parameters associated with the meta parameter name&lt;br /&gt;
		if &#039;string&#039; == type (params) then&lt;br /&gt;
			skip_t[params] = 1;													-- just a single parameter&lt;br /&gt;
		else&lt;br /&gt;
			for _, param in ipairs (params) do									-- get the parameter name&lt;br /&gt;
				skip_t[param] = 1;												-- add the parameter name to the skip table&lt;br /&gt;
				local count;&lt;br /&gt;
				param, count = param:gsub (&#039;#&#039;, &#039;&#039;);							-- remove enumerator marker from enumerated parameters&lt;br /&gt;
				if 0 ~= count then												-- if removed&lt;br /&gt;
					skip_t[param] = 1;											-- add param name without enumerator marker&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return skip_t;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local punct_skip = {};&lt;br /&gt;
local url_skip = {};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[-----------&amp;lt; S P E C I A L   C A S E   T R A N S L A T I O N S &amp;gt;------------&lt;br /&gt;
&lt;br /&gt;
This table is primarily here to support internationalization.  Translations in&lt;br /&gt;
this table are used, for example, when an error message, category name, etc.,&lt;br /&gt;
is extracted from the English alias key.  There may be other cases where&lt;br /&gt;
this translation table may be useful.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
local is_Latn = &#039;A-Za-z\195\128-\195\150\195\152-\195\182\195\184-\198\191\199\132-\201\143&#039;;&lt;br /&gt;
local special_case_translation = {&lt;br /&gt;
	[&#039;AuthorList&#039;] = &#039;authors list&#039;,											-- used to assemble maintenance category names&lt;br /&gt;
	[&#039;ContributorList&#039;] = &#039;contributors list&#039;,									-- translation of these names plus translation of the base mainenance category names in maint_cats{} table below&lt;br /&gt;
	[&#039;EditorList&#039;] = &#039;editors list&#039;,											-- must match the names of the actual categories&lt;br /&gt;
	[&#039;InterviewerList&#039;] = &#039;interviewers list&#039;,									-- this group or translations used by name_has_ed_markup() and name_has_mult_names()&lt;br /&gt;
	[&#039;TranslatorList&#039;] = &#039;translators list&#039;,&lt;br /&gt;
	&lt;br /&gt;
																				-- Lua patterns to match pseudo-titles used by InternetArchiveBot and others as placeholder for unknown |title= value&lt;br /&gt;
	[&#039;archived_copy&#039;] = {														-- used with CS1 maint: Archive[d] copy as title&lt;br /&gt;
		[&#039;en&#039;] = &#039;^archived?%s+copy$&#039;,											-- for English; translators: keep this because templates imported from en.wiki&lt;br /&gt;
		[&#039;local&#039;] = nil,														-- translators: replace [&#039;local&#039;] = nil with lowercase translation only when bots or tools create generic titles in your language&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
																				-- Lua patterns to match generic titles; usually created by bots or reference filling tools&lt;br /&gt;
																				-- translators: replace [&#039;local&#039;] = nil with lowercase translation only when bots or tools create generic titles in your language&lt;br /&gt;
		-- generic titles and patterns in this table should be lowercase only&lt;br /&gt;
		-- leave [&#039;local&#039;] nil except when there is a matching generic title in your language&lt;br /&gt;
		-- boolean &#039;true&#039; for plain-text searches; &#039;false&#039; for pattern searches&lt;br /&gt;
&lt;br /&gt;
	[&#039;generic_titles&#039;] = {&lt;br /&gt;
		[&#039;accept&#039;] = {&lt;br /&gt;
			},&lt;br /&gt;
		[&#039;reject&#039;] = {&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;^wayback%s+machine$&#039;, false},				[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;are you a robot&#039;, true},					[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;hugedomains.com&#039;, true},					[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;^[%(%[{&amp;lt;]?no +title[&amp;gt;}%]%)]?$&#039;, false},		[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;page not found&#039;, true},						[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;subscribe to read&#039;, true},					[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;^[%(%[{&amp;lt;]?unknown[&amp;gt;}%]%)]?$&#039;, false},		[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;website is for sale&#039;, true},				[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;^404&#039;, false},								[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;internet archive wayback machine&#039;, true},	[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;log into facebook&#039;, true},					[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;login • instagram&#039;, true},					[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;redirecting...&#039;, true},						[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;usurped title&#039;, true},						[&#039;local&#039;] = nil},	-- added by a GreenC bot&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;webcite query result&#039;, true},				[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;wikiwix\&#039;s cache&#039;, true},					[&#039;local&#039;] = nil},&lt;br /&gt;
			}&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
		-- boolean &#039;true&#039; for plain-text searches, search string must be lowercase only&lt;br /&gt;
		-- boolean &#039;false&#039; for pattern searches&lt;br /&gt;
		-- leave [&#039;local&#039;] nil except when there is a matching generic name in your language&lt;br /&gt;
&lt;br /&gt;
	[&#039;generic_names&#039;] = {&lt;br /&gt;
		[&#039;accept&#039;] = {&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;%[%[[^|]*%(author%) *|[^%]]*%]%]&#039;, false},				[&#039;local&#039;] = nil},&lt;br /&gt;
			},&lt;br /&gt;
		[&#039;reject&#039;] = {&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;about us&#039;, true},										[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;%f[%a][Aa]dvisor%f[%A]&#039;, false},						[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;%f[%a][Aa]uthor%f[%A]&#039;, false},							[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;collaborator&#039;, true},									[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;contributor&#039;, true},									[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;contact us&#039;, true},										[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;directory&#039;, true},										[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;%f[%(%[][%(%[]%s*eds?%.?%s*[%)%]]?$&#039;, false},			[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;[,%.%s]%f[e]eds?%.?$&#039;, false},							[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;^eds?[%.,;]&#039;, false},									[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;^[%(%[]%s*[Ee][Dd][Ss]?%.?%s*[%)%]]&#039;, false},			[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;%f[%a][Ee]dited%f[%A]&#039;, false},							[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;%f[%a][Ee]ditors?%f[%A]&#039;, false},						[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;%f[%a]]Ee]mail%f[%A]&#039;, false},							[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;facebook&#039;, true},										[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;google&#039;, true},											[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;home page&#039;, true},										[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;instagram&#039;, true},										[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;interviewer&#039;, true},									[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;linkedIn&#039;, true},										[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;^[Nn]ews$&#039;, false},										[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;pinterest&#039;, true},										[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;policy&#039;, true},											[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;privacy&#039;, true},										[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;translator&#039;, true},										[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;tumblr&#039;, true},											[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;twitter&#039;, true},										[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;site name&#039;, true},										[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;statement&#039;, true},										[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;submitted&#039;, true},										[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;super.?user&#039;, false},									[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;%f[&#039;..is_Latn..&#039;][Uu]ser%f[^&#039;..is_Latn..&#039;]&#039;, false},	[&#039;local&#039;] = nil},&lt;br /&gt;
			{[&#039;en&#039;] = {&#039;verfasser&#039;, true},										[&#039;local&#039;] = nil},&lt;br /&gt;
			}&lt;br /&gt;
	}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; D A T E _ N A M E S &amp;gt;----------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
This table of tables lists local language date names and fallback English date names.&lt;br /&gt;
The code in Date_validation will look first in the local table for valid date names.&lt;br /&gt;
If date names are not found in the local table, the code will look in the English table.&lt;br /&gt;
&lt;br /&gt;
Because citations can be copied to the local wiki from en.wiki, the English is&lt;br /&gt;
required when the date-name translation function date_name_xlate() is used.&lt;br /&gt;
&lt;br /&gt;
In these tables, season numbering is defined by&lt;br /&gt;
Extended Date/Time Format (EDTF) Specification (https://www.loc.gov/standards/datetime/)&lt;br /&gt;
which became part of ISO 8601 in 2019.  See &#039;§Sub-year groupings&#039;. The standard&lt;br /&gt;
defines various divisions using numbers 21-41. CS1|2 only supports generic seasons.&lt;br /&gt;
EDTF does support the distinction between north and south hemisphere seasons&lt;br /&gt;
but CS1|2 has no way to make that distinction.&lt;br /&gt;
&lt;br /&gt;
33-36 = Quarter 1, Quarter 2, Quarter 3, Quarter 4 (3 months each)&lt;br /&gt;
&lt;br /&gt;
The standard does not address &#039;named&#039; dates so, for the purposes of CS1|2,&lt;br /&gt;
Easter and Christmas are defined here as 98 and 99, which should be out of the&lt;br /&gt;
ISO 8601 (EDTF) range of uses for a while.&lt;br /&gt;
&lt;br /&gt;
local_date_names_from_mediawiki is a boolean.  When set to:&lt;br /&gt;
	true – module will fetch local month names from MediaWiki for both date_names[&#039;local&#039;][&#039;long&#039;] and date_names[&#039;local&#039;][&#039;short&#039;]&lt;br /&gt;
	false – module will *not* fetch local month names from MediaWiki&lt;br /&gt;
&lt;br /&gt;
Caveat lector:  There is no guarantee that MediaWiki will provide short month names.  At your wiki you can test&lt;br /&gt;
the results of the MediaWiki fetch in the debug console with this command (the result is alpha sorted):&lt;br /&gt;
	=mw.dumpObject (p.date_names[&#039;local&#039;])&lt;br /&gt;
&lt;br /&gt;
While the module can fetch month names from MediaWiki, it cannot fetch the quarter, season, and named date names&lt;br /&gt;
from MediaWiki.  Those must be translated manually.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local local_date_names_from_mediawiki = true;									-- when false, manual translation required for date_names[&#039;local&#039;][&#039;long&#039;] and date_names[&#039;local&#039;][&#039;short&#039;]&lt;br /&gt;
																				-- when true, module fetches long and short month names from MediaWiki&lt;br /&gt;
local date_names = {&lt;br /&gt;
	[&#039;en&#039;] = {																	-- English&lt;br /&gt;
		[&#039;long&#039;]	= {[&#039;January&#039;] = 1, [&#039;February&#039;] = 2, [&#039;March&#039;] = 3, [&#039;April&#039;] = 4, [&#039;May&#039;] = 5, [&#039;June&#039;] = 6, [&#039;July&#039;] = 7, [&#039;August&#039;] = 8, [&#039;September&#039;] = 9, [&#039;October&#039;] = 10, [&#039;November&#039;] = 11, [&#039;December&#039;] = 12},&lt;br /&gt;
		[&#039;short&#039;]	= {[&#039;Jan&#039;] = 1, [&#039;Feb&#039;] = 2, [&#039;Mar&#039;] = 3, [&#039;Apr&#039;] = 4, [&#039;May&#039;] = 5, [&#039;Jun&#039;] = 6, [&#039;Jul&#039;] = 7, [&#039;Aug&#039;] = 8, [&#039;Sep&#039;] = 9, [&#039;Oct&#039;] = 10, [&#039;Nov&#039;] = 11, [&#039;Dec&#039;] = 12},&lt;br /&gt;
		[&#039;quarter&#039;] = {[&#039;First Quarter&#039;] = 33, [&#039;Second Quarter&#039;] = 34, [&#039;Third Quarter&#039;] = 35, [&#039;Fourth Quarter&#039;] = 36},&lt;br /&gt;
		[&#039;season&#039;]	= {[&#039;Winter&#039;] = 24, [&#039;Spring&#039;] = 21, [&#039;Summer&#039;] = 22, [&#039;Fall&#039;] = 23, [&#039;Autumn&#039;] = 23},&lt;br /&gt;
		[&#039;named&#039;]	= {[&#039;Easter&#039;] = 98, [&#039;Christmas&#039;] = 99},&lt;br /&gt;
		},&lt;br /&gt;
																				-- when local_date_names_from_mediawiki = false&lt;br /&gt;
	[&#039;local&#039;] = {																-- replace these English date names with the local language equivalents&lt;br /&gt;
		[&#039;long&#039;]	= {[&#039;January&#039;] = 1, [&#039;February&#039;] = 2, [&#039;March&#039;] = 3, [&#039;April&#039;] = 4, [&#039;May&#039;] = 5, [&#039;June&#039;] = 6, [&#039;July&#039;] = 7, [&#039;August&#039;] = 8, [&#039;September&#039;] = 9, [&#039;October&#039;] = 10, [&#039;November&#039;] = 11, [&#039;December&#039;] = 12},&lt;br /&gt;
		[&#039;short&#039;]	= {[&#039;Jan&#039;] = 1, [&#039;Feb&#039;] = 2, [&#039;Mar&#039;] = 3, [&#039;Apr&#039;] = 4, [&#039;May&#039;] = 5, [&#039;Jun&#039;] = 6, [&#039;Jul&#039;] = 7, [&#039;Aug&#039;] = 8, [&#039;Sep&#039;] = 9, [&#039;Oct&#039;] = 10, [&#039;Nov&#039;] = 11, [&#039;Dec&#039;] = 12},&lt;br /&gt;
		[&#039;quarter&#039;] = {[&#039;First Quarter&#039;] = 33, [&#039;Second Quarter&#039;] = 34, [&#039;Third Quarter&#039;] = 35, [&#039;Fourth Quarter&#039;] = 36},&lt;br /&gt;
		[&#039;season&#039;]	= {[&#039;Winter&#039;] = 24, [&#039;Spring&#039;] = 21, [&#039;Summer&#039;] = 22, [&#039;Fall&#039;] = 23, [&#039;Autumn&#039;] = 23},&lt;br /&gt;
		[&#039;named&#039;]	= {[&#039;Easter&#039;] = 98, [&#039;Christmas&#039;] = 99},&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;inv_local_long&#039;] = {},													-- used in date reformatting &amp;amp; translation; copy of date_names[&#039;local&#039;].long where k/v are inverted: [1]=&#039;&amp;lt;local name&amp;gt;&#039; etc.&lt;br /&gt;
	[&#039;inv_local_short&#039;] = {},													-- used in date reformatting &amp;amp; translation; copy of date_names[&#039;local&#039;].short where k/v are inverted: [1]=&#039;&amp;lt;local name&amp;gt;&#039; etc.&lt;br /&gt;
	[&#039;inv_local_quarter&#039;] = {},													-- used in date translation; copy of date_names[&#039;local&#039;].quarter where k/v are inverted: [1]=&#039;&amp;lt;local name&amp;gt;&#039; etc.&lt;br /&gt;
	[&#039;inv_local_season&#039;] = {},													-- used in date translation; copy of date_names[&#039;local&#039;].season where k/v are inverted: [1]=&#039;&amp;lt;local name&amp;gt;&#039; etc.&lt;br /&gt;
	[&#039;inv_local_named&#039;] = {},													-- used in date translation; copy of date_names[&#039;local&#039;].named where k/v are inverted: [1]=&#039;&amp;lt;local name&amp;gt;&#039; etc.&lt;br /&gt;
	[&#039;local_digits&#039;] = {[&#039;0&#039;] = &#039;0&#039;, [&#039;1&#039;] = &#039;1&#039;, [&#039;2&#039;] = &#039;2&#039;, [&#039;3&#039;] = &#039;3&#039;, [&#039;4&#039;] = &#039;4&#039;, [&#039;5&#039;] = &#039;5&#039;, [&#039;6&#039;] = &#039;6&#039;, [&#039;7&#039;] = &#039;7&#039;, [&#039;8&#039;] = &#039;8&#039;, [&#039;9&#039;] = &#039;9&#039;},	-- used to convert local language digits to Western 0-9&lt;br /&gt;
	[&#039;xlate_digits&#039;] = {},&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
if local_date_names_from_mediawiki then											-- if fetching local month names from MediaWiki is enabled&lt;br /&gt;
	local long_t = {};&lt;br /&gt;
	local short_t = {};&lt;br /&gt;
	for i=1, 12 do																-- loop 12x and &lt;br /&gt;
		local name = lang_obj:formatDate(&#039;F&#039;, &#039;2022-&#039; .. i .. &#039;-1&#039;);			-- get long month name for each i&lt;br /&gt;
		long_t[name] = i;														-- save it&lt;br /&gt;
		name = lang_obj:formatDate(&#039;M&#039;, &#039;2022-&#039; .. i .. &#039;-1&#039;);					-- get short month name for each i&lt;br /&gt;
		short_t[name] = i;														-- save it&lt;br /&gt;
	end&lt;br /&gt;
	date_names[&#039;local&#039;][&#039;long&#039;] = long_t;										-- write the long table – overwrites manual translation&lt;br /&gt;
	date_names[&#039;local&#039;][&#039;short&#039;] = short_t;										-- write the short table – overwrites manual translation&lt;br /&gt;
end&lt;br /&gt;
																				-- create inverted date-name tables for reformatting and/or translation&lt;br /&gt;
for _, invert_t in pairs {{&#039;long&#039;, &#039;inv_local_long&#039;}, {&#039;short&#039;, &#039;inv_local_short&#039;}, {&#039;quarter&#039;, &#039;inv_local_quarter&#039;}, {&#039;season&#039;, &#039;inv_local_season&#039;}, {&#039;named&#039;, &#039;inv_local_named&#039;}} do&lt;br /&gt;
	for name, i in pairs (date_names[&#039;local&#039;][invert_t[1]]) do					-- this table is [&#039;name&#039;] = i&lt;br /&gt;
		date_names[invert_t[2]][i] = name;										-- invert to get [i] = &#039;name&#039; for conversions from ymd&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
for ld, ed in pairs (date_names.local_digits) do								-- make a digit translation table for simple date translation from en to local language using local_digits table&lt;br /&gt;
	date_names.xlate_digits [ed] = ld;											-- en digit becomes index with local digit as the value&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local df_template_patterns = {													-- table of redirects to {{Use dmy dates}} and {{Use mdy dates}}&lt;br /&gt;
	&#039;{{ *[Uu]se +(dmy) +dates *[|}]&#039;,	-- 1159k								-- sorted by approximate transclusion count&lt;br /&gt;
	&#039;{{ *[Uu]se +(mdy) +dates *[|}]&#039;,	-- 212k&lt;br /&gt;
	&#039;{{ *[Uu]se +(MDY) +dates *[|}]&#039;,	-- 788&lt;br /&gt;
	&#039;{{ *[Uu]se +(DMY) +dates *[|}]&#039;,	-- 343&lt;br /&gt;
	&#039;{{ *([Mm]dy) *[|}]&#039;,				-- 176&lt;br /&gt;
	&#039;{{ *[Uu]se *(dmy) *[|}]&#039;,			-- 156 + 18&lt;br /&gt;
	&#039;{{ *[Uu]se *(mdy) *[|}]&#039;,			-- 149 + 11&lt;br /&gt;
	&#039;{{ *([Dd]my) *[|}]&#039;,				-- 56&lt;br /&gt;
	&#039;{{ *[Uu]se +(MDY) *[|}]&#039;,			-- 5&lt;br /&gt;
	&#039;{{ *([Dd]MY) *[|}]&#039;,				-- 3&lt;br /&gt;
	&#039;{{ *[Uu]se(mdy)dates *[|}]&#039;,		-- 1&lt;br /&gt;
	&#039;{{ *[Uu]se +(DMY) *[|}]&#039;,			-- 0&lt;br /&gt;
	&#039;{{ *([Mm]DY) *[|}]&#039;,				-- 0&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
local function get_date_format ()&lt;br /&gt;
	local title_object = mw.title.getCurrentTitle();&lt;br /&gt;
	if title_object.namespace == 10 then										-- not in template space so that unused templates appear in unused-template-reports; &lt;br /&gt;
		return nil;																-- auto-formatting does not work in Template space so don&#039;t set global_df&lt;br /&gt;
	end&lt;br /&gt;
	local content = title_object:getContent() or &#039;&#039;;							-- get the content of the article or &#039;&#039;; new pages edited w/ve do not have &#039;content&#039; until saved; ve does not preview; phab:T221625&lt;br /&gt;
	for _, pattern in ipairs (df_template_patterns) do							-- loop through the patterns looking for {{Use dmy dates}} or {{Use mdy dates}} or any of their redirects&lt;br /&gt;
		local start, _, match = content:find(pattern);							-- match is the three letters indicating desired date format&lt;br /&gt;
		if match then&lt;br /&gt;
			content = content:match (&#039;%b{}&#039;, start);							-- get the whole template&lt;br /&gt;
			if content:match (&#039;| *cs1%-dates *= *[lsy][sy]?&#039;) then				-- look for |cs1-dates=publication date length access-/archive-date length&lt;br /&gt;
				return match:lower() .. &#039;-&#039; .. content:match (&#039;| *cs1%-dates *= *([lsy][sy]?)&#039;);&lt;br /&gt;
			else&lt;br /&gt;
				return match:lower() .. &#039;-all&#039;;									-- no |cs1-dates= k/v pair; return value appropriate for use in |df=&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local global_df;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[-----------------&amp;lt; V O L U M E ,  I S S U E ,  P A G E S &amp;gt;------------------&lt;br /&gt;
&lt;br /&gt;
These tables hold cite class values (from the template invocation) and identify those templates that support&lt;br /&gt;
|volume=, |issue=, and |page(s)= parameters.  Cite conference and cite map require further qualification which&lt;br /&gt;
is handled in the main module.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local templates_using_volume = {&#039;citation&#039;, &#039;audio-visual&#039;, &#039;book&#039;, &#039;conference&#039;, &#039;encyclopaedia&#039;, &#039;interview&#039;, &#039;journal&#039;, &#039;magazine&#039;, &#039;map&#039;, &#039;news&#039;, &#039;report&#039;, &#039;techreport&#039;, &#039;thesis&#039;}&lt;br /&gt;
local templates_using_issue = {&#039;citation&#039;, &#039;conference&#039;, &#039;episode&#039;, &#039;interview&#039;, &#039;journal&#039;, &#039;magazine&#039;, &#039;map&#039;, &#039;news&#039;, &#039;podcast&#039;}&lt;br /&gt;
local templates_not_using_page = {&#039;audio-visual&#039;, &#039;episode&#039;, &#039;mailinglist&#039;, &#039;newsgroup&#039;, &#039;podcast&#039;, &#039;serial&#039;, &#039;sign&#039;, &#039;speech&#039;}&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
&lt;br /&gt;
These tables control when it is appropriate for {{citation}} to render |volume= and/or |issue=.  The parameter&lt;br /&gt;
names in the tables constrain {{citation}} so that its renderings match the renderings of the equivalent cs1&lt;br /&gt;
templates.  For example, {{cite web}} does not support |volume= so the equivalent {{citation |website=...}} must&lt;br /&gt;
not support |volume=.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local citation_no_volume_t = {													-- {{citation}} does not render |volume= when these parameters are used&lt;br /&gt;
	&#039;website&#039;, &#039;mailinglist&#039;, &#039;script-website&#039;,&lt;br /&gt;
	}&lt;br /&gt;
local citation_issue_t = {														-- {{citation}} may render |issue= when these parameters are used&lt;br /&gt;
	&#039;journal&#039;, &#039;magazine&#039;, &#039;newspaper&#039;, &#039;periodical&#039;, &#039;work&#039;,&lt;br /&gt;
	&#039;script-journal&#039;, &#039;script-magazine&#039;, &#039;script-newspaper&#039;, &#039;script-periodical&#039;, &#039;script-work&#039;,&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
&lt;br /&gt;
Patterns for finding extra text in |volume=, |issue=, |page=, |pages=&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local vol_iss_pg_patterns = {&lt;br /&gt;
	good_ppattern = &#039;^P[^%.PpGg]&#039;,												-- OK to begin with uppercase P: P7 (page 7 of section P), but not p123 (page 123); TODO: this allows &#039;Pages&#039; which it should not&lt;br /&gt;
	bad_ppatterns = {															-- patterns for |page= and |pages=&lt;br /&gt;
		&#039;^[Pp][PpGg]?%.?[ %d]&#039;,&lt;br /&gt;
		&#039;^[Pp][Pp]?%.&amp;amp;nbsp;&#039;,													-- from {{p.}} and {{pp.}} templates&lt;br /&gt;
		&#039;^[Pp]ages?&#039;,&lt;br /&gt;
		&#039;^[Pp]gs.?&#039;,&lt;br /&gt;
		},&lt;br /&gt;
	vpatterns = {																-- patterns for |volume=&lt;br /&gt;
		&#039;^volumes?&#039;,&lt;br /&gt;
		&#039;^vols?[%.:=]?&#039;&lt;br /&gt;
		},&lt;br /&gt;
	ipatterns = {																-- patterns for |issue=&lt;br /&gt;
		&#039;^issues?&#039;,&lt;br /&gt;
		&#039;^iss[%.:=]?&#039;,&lt;br /&gt;
		&#039;^numbers?&#039;,&lt;br /&gt;
		&#039;^nos?%A&#039;,																-- don&#039;t match &#039;november&#039; or &#039;nostradamus&#039;&lt;br /&gt;
		&#039;^nr[%.:=]?&#039;,&lt;br /&gt;
		&#039;^n[%.:= ]&#039;																-- might be a valid issue without separator (space char is sep char here)&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; K E Y W O R D S &amp;gt;-------------------------------&lt;br /&gt;
&lt;br /&gt;
These tables hold keywords for those parameters that have defined sets of acceptable keywords.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
--[[-------------------&amp;lt; K E Y W O R D S   T A B L E &amp;gt;--------------------------&lt;br /&gt;
&lt;br /&gt;
this is a list of keywords; each key in the list is associated with a table of&lt;br /&gt;
synonymous keywords possibly from different languages.&lt;br /&gt;
&lt;br /&gt;
for I18N: add local-language keywords to value table; do not change the key.&lt;br /&gt;
For example, adding the German keyword &#039;ja&#039;:&lt;br /&gt;
	[&#039;affirmative&#039;] = {&#039;yes&#039;, &#039;true&#039;, &#039;y&#039;, &#039;ja&#039;},&lt;br /&gt;
&lt;br /&gt;
Because CS1|2 templates from en.wiki articles are often copied to other local wikis,&lt;br /&gt;
it is recommended that the English keywords remain in these tables.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local keywords = {&lt;br /&gt;
	[&#039;amp&#039;] = {&#039;&amp;amp;&#039;, &#039;amp&#039;, &#039;ampersand&#039;}, 										-- |name-list-style=&lt;br /&gt;
	[&#039;and&#039;] = {&#039;and&#039;, &#039;serial&#039;},												-- |name-list-style=&lt;br /&gt;
	[&#039;affirmative&#039;] = {&#039;yes&#039;, &#039;true&#039;, &#039;y&#039;},										-- |no-tracking=, |no-pp= -- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;afterword&#039;] = {&#039;afterword&#039;},												-- |contribution=&lt;br /&gt;
	[&#039;bot: unknown&#039;] = {&#039;bot: unknown&#039;},										-- |url-status= -- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;cs1&#039;] = {&#039;cs1&#039;},															-- |mode=&lt;br /&gt;
	[&#039;cs2&#039;] = {&#039;cs2&#039;},															-- |mode=&lt;br /&gt;
	[&#039;dead&#039;] = {&#039;dead&#039;, &#039;deviated&#039;},											-- |url-status= -- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;dmy&#039;] = {&#039;dmy&#039;},															-- |df=&lt;br /&gt;
	[&#039;dmy-all&#039;] = {&#039;dmy-all&#039;},													-- |df=&lt;br /&gt;
	[&#039;foreword&#039;] = {&#039;foreword&#039;},												-- |contribution=&lt;br /&gt;
	[&#039;free&#039;] = {&#039;free&#039;},														-- |&amp;lt;id&amp;gt;-access= -- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;harv&#039;] = {&#039;harv&#039;},														-- |ref=; this no longer supported; is_valid_parameter_value() called with &amp;lt;invert&amp;gt; = true&lt;br /&gt;
	[&#039;introduction&#039;] = {&#039;introduction&#039;},										-- |contribution=&lt;br /&gt;
	[&#039;limited&#039;] = {&#039;limited&#039;},													-- |url-access= -- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;live&#039;] = {&#039;live&#039;},														-- |url-status= -- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;mdy&#039;] = {&#039;mdy&#039;},															-- |df=&lt;br /&gt;
	[&#039;mdy-all&#039;] = {&#039;mdy-all&#039;},													-- |df=&lt;br /&gt;
	[&#039;none&#039;] = {&#039;none&#039;},														-- |postscript=, |ref=, |title=, |type= -- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;off&#039;] = {&#039;off&#039;},															-- |title= (potentially also: |title-link=, |postscript=, |ref=, |type=)&lt;br /&gt;
	[&#039;preface&#039;] = {&#039;preface&#039;},													-- |contribution=&lt;br /&gt;
	[&#039;registration&#039;] = {&#039;registration&#039;},										-- |url-access= -- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;subscription&#039;] = {&#039;subscription&#039;},										-- |url-access= -- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;unfit&#039;] = {&#039;unfit&#039;},														-- |url-status= -- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;usurped&#039;] = {&#039;usurped&#039;},													-- |url-status= -- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;vanc&#039;] = {&#039;vanc&#039;},														-- |name-list-style=&lt;br /&gt;
	[&#039;ymd&#039;] = {&#039;ymd&#039;},															-- |df=&lt;br /&gt;
	[&#039;ymd-all&#039;] = {&#039;ymd-all&#039;},													-- |df=&lt;br /&gt;
	--	[&#039;yMd&#039;] = {&#039;yMd&#039;},														-- |df=; not supported at en.wiki&lt;br /&gt;
	--	[&#039;yMd-all&#039;] = {&#039;yMd-all&#039;},												-- |df=; not supported at en.wiki&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[------------------------&amp;lt; X L A T E _ K E Y W O R D S &amp;gt;---------------------&lt;br /&gt;
&lt;br /&gt;
this function builds a list, keywords_xlate{}, of the keywords found in keywords{} where the values from keywords{}&lt;br /&gt;
become the keys in keywords_xlate{} and the keys from keywords{} become the values in keywords_xlate{}:&lt;br /&gt;
	[&#039;affirmative&#039;] = {&#039;yes&#039;, &#039;true&#039;, &#039;y&#039;},		-- in keywords{}&lt;br /&gt;
becomes&lt;br /&gt;
	[&#039;yes&#039;] = &#039;affirmative&#039;,					-- in keywords_xlate{}&lt;br /&gt;
	[&#039;true&#039;] = &#039;affirmative&#039;,&lt;br /&gt;
	[&#039;y&#039;] = &#039;affirmative&#039;,&lt;br /&gt;
&lt;br /&gt;
the purpose of this function is to act as a translator between a non-English keyword and its English equivalent&lt;br /&gt;
that may be used in other modules of this suite&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function xlate_keywords ()&lt;br /&gt;
	local out_table = {};														-- output goes here&lt;br /&gt;
	for k, keywords_t in pairs (keywords) do									-- spin through the keywords table&lt;br /&gt;
		for _, keyword in ipairs (keywords_t) do								-- for each keyword&lt;br /&gt;
			out_table[keyword] = k;												-- create an entry in the output table where keyword is the key&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return out_table;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local keywords_xlate = xlate_keywords ();										-- the list of translated keywords&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[----------------&amp;lt; M A K E _ K E Y W O R D S _ L I S T &amp;gt;---------------------&lt;br /&gt;
&lt;br /&gt;
this function assembles, for parameter-value validation, the list of keywords appropriate to that parameter.&lt;br /&gt;
&lt;br /&gt;
keywords_lists{}, is a table of tables from keywords{}&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function make_keywords_list (keywords_lists)&lt;br /&gt;
	local out_table = {};														-- output goes here&lt;br /&gt;
	&lt;br /&gt;
	for _, keyword_list in ipairs (keywords_lists) do							-- spin through keywords_lists{} and get a table of keywords&lt;br /&gt;
		for _, keyword in ipairs (keyword_list) do								-- spin through keyword_list{} and add each keyword, ...&lt;br /&gt;
			table.insert (out_table, keyword);									-- ... as plain text, to the output list&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return out_table;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[----------------&amp;lt; K E Y W O R D S _ L I S T S &amp;gt;-----------------------------&lt;br /&gt;
&lt;br /&gt;
this is a list of lists of valid keywords for the various parameters in [key].&lt;br /&gt;
Generally the keys in this table are the canonical en.wiki parameter names though&lt;br /&gt;
some are contrived because of use in multiple differently named parameters:&lt;br /&gt;
[&#039;yes_true_y&#039;], [&#039;id-access&#039;].&lt;br /&gt;
&lt;br /&gt;
The function make_keywords_list() extracts the individual keywords from the&lt;br /&gt;
appropriate list in keywords{}.&lt;br /&gt;
&lt;br /&gt;
The lists in this table are used to validate the keyword assignment for the&lt;br /&gt;
parameters named in this table&#039;s keys.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local keywords_lists = {&lt;br /&gt;
	[&#039;yes_true_y&#039;] = make_keywords_list ({keywords.affirmative}),&lt;br /&gt;
	[&#039;contribution&#039;] = make_keywords_list ({keywords.afterword, keywords.foreword, keywords.introduction, keywords.preface}),&lt;br /&gt;
	[&#039;df&#039;] = make_keywords_list ({keywords.dmy, keywords[&#039;dmy-all&#039;], keywords.mdy, keywords[&#039;mdy-all&#039;], keywords.ymd, keywords[&#039;ymd-all&#039;]}),&lt;br /&gt;
	--	[&#039;df&#039;] = make_keywords_list ({keywords.dmy, keywords[&#039;dmy-all&#039;], keywords.mdy, keywords[&#039;mdy-all&#039;], keywords.ymd, keywords[&#039;ymd-all&#039;], keywords.yMd, keywords[&#039;yMd-all&#039;]}),	-- not supported at en.wiki&lt;br /&gt;
	[&#039;mode&#039;] = make_keywords_list ({keywords.cs1, keywords.cs2}),&lt;br /&gt;
	[&#039;name-list-style&#039;] = make_keywords_list ({keywords.amp, keywords[&#039;and&#039;], keywords.vanc}),&lt;br /&gt;
	[&#039;ref&#039;] = make_keywords_list ({keywords.harv}),								-- inverted check; |ref=harv no longer supported&lt;br /&gt;
	[&#039;url-access&#039;] = make_keywords_list ({keywords.subscription, keywords.limited, keywords.registration}),&lt;br /&gt;
	[&#039;url-status&#039;] = make_keywords_list ({keywords.dead, keywords.live, keywords.unfit, keywords.usurped, keywords[&#039;bot: unknown&#039;]}),&lt;br /&gt;
	[&#039;id-access&#039;] = make_keywords_list ({keywords.free}),&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[---------------------&amp;lt; S T R I P M A R K E R S &amp;gt;----------------------------&lt;br /&gt;
&lt;br /&gt;
Common pattern definition location for stripmarkers so that we don&#039;t have to go&lt;br /&gt;
hunting for them if (when) MediaWiki changes their form.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local stripmarkers = {&lt;br /&gt;
	[&#039;any&#039;] = &#039;\127[^\127]*UNIQ%-%-(%a+)%-[%a%d]+%-QINU[^\127]*\127&#039;,			-- capture returns name of stripmarker&lt;br /&gt;
	[&#039;math&#039;] = &#039;\127[^\127]*UNIQ%-%-math%-[%a%d]+%-QINU[^\127]*\127&#039;			-- math stripmarkers used in coins_cleanup() and coins_replace_math_stripmarker()&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[------------&amp;lt; I N V I S I B L E _ C H A R A C T E R S &amp;gt;---------------------&lt;br /&gt;
&lt;br /&gt;
This table holds non-printing or invisible characters indexed either by name or&lt;br /&gt;
by Unicode group. Values are decimal representations of UTF-8 codes.  The table&lt;br /&gt;
is organized as a table of tables because the Lua pairs keyword returns table&lt;br /&gt;
data in an arbitrary order.  Here, we want to process the table from top to bottom&lt;br /&gt;
because the entries at the top of the table are also found in the ranges specified&lt;br /&gt;
by the entries at the bottom of the table.&lt;br /&gt;
&lt;br /&gt;
Also here is a pattern that recognizes stripmarkers that begin and end with the&lt;br /&gt;
delete characters.  The nowiki stripmarker is not an error but some others are&lt;br /&gt;
because the parameter values that include them become part of the template&#039;s&lt;br /&gt;
metadata before stripmarker replacement.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local invisible_defs = {&lt;br /&gt;
	del = &#039;\127&#039;,																-- used to distinguish between stripmarker and del char&lt;br /&gt;
	zwj = &#039;\226\128\141&#039;,														-- used with capture because zwj may be allowed&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
local invisible_chars = {&lt;br /&gt;
	{&#039;replacement&#039;, &#039;\239\191\189&#039;},											-- U+FFFD, EF BF BD&lt;br /&gt;
	{&#039;zero width joiner&#039;, &#039;(&#039;.. invisible_defs.zwj .. &#039;)&#039;},						-- U+200D, E2 80 8D; capture because zwj may be allowed&lt;br /&gt;
	{&#039;zero width space&#039;, &#039;\226\128\139&#039;},										-- U+200B, E2 80 8B&lt;br /&gt;
	{&#039;hair space&#039;, &#039;\226\128\138&#039;},												-- U+200A, E2 80 8A&lt;br /&gt;
	{&#039;soft hyphen&#039;, &#039;\194\173&#039;},												-- U+00AD, C2 AD&lt;br /&gt;
	{&#039;horizontal tab&#039;, &#039;\009&#039;},													-- U+0009 (HT), 09&lt;br /&gt;
	{&#039;line feed&#039;, &#039;\010&#039;},														-- U+000A (LF), 0A&lt;br /&gt;
	{&#039;no-break space&#039;, &#039;\194\160&#039;},												-- U+00A0 (NBSP), C2 A0&lt;br /&gt;
	{&#039;carriage return&#039;, &#039;\013&#039;},												-- U+000D (CR), 0D&lt;br /&gt;
	{&#039;stripmarker&#039;, stripmarkers.any},											-- stripmarker; may or may not be an error; capture returns the stripmaker type&lt;br /&gt;
	{&#039;delete&#039;, &#039;(&#039;.. invisible_defs.del .. &#039;)&#039;},								-- U+007F (DEL), 7F; must be done after stripmarker test; capture to distinguish isolated del chars not part of stripmarker&lt;br /&gt;
	{&#039;C0 control&#039;, &#039;[\000-\008\011\012\014-\031]&#039;},								-- U+0000–U+001F (NULL–US), 00–1F (except HT, LF, CR (09, 0A, 0D))&lt;br /&gt;
	{&#039;C1 control&#039;, &#039;[\194\128-\194\159]&#039;},										-- U+0080–U+009F (XXX–APC), C2 80 – C2 9F&lt;br /&gt;
	--	{&#039;Specials&#039;, &#039;[\239\191\185-\239\191\191]&#039;},								-- U+FFF9-U+FFFF, EF BF B9 – EF BF BF&lt;br /&gt;
	--	{&#039;Private use area&#039;, &#039;[\238\128\128-\239\163\191]&#039;},						-- U+E000–U+F8FF, EE 80 80 – EF A3 BF&lt;br /&gt;
	--	{&#039;Supplementary Private Use Area-A&#039;, &#039;[\243\176\128\128-\243\191\191\189]&#039;},	-- U+F0000–U+FFFFD, F3 B0 80 80 – F3 BF BF BD&lt;br /&gt;
	--	{&#039;Supplementary Private Use Area-B&#039;, &#039;[\244\128\128\128-\244\143\191\189]&#039;},	-- U+100000–U+10FFFD, F4 80 80 80 – F4 8F BF BD&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
&lt;br /&gt;
Indic script makes use of zero width joiner as a character modifier so zwj&lt;br /&gt;
characters must be left in.  This pattern covers all of the unicode characters&lt;br /&gt;
for these languages:&lt;br /&gt;
	Devanagari					0900–097F – https://unicode.org/charts/PDF/U0900.pdf&lt;br /&gt;
		Devanagari extended		A8E0–A8FF – https://unicode.org/charts/PDF/UA8E0.pdf&lt;br /&gt;
	Bengali						0980–09FF – https://unicode.org/charts/PDF/U0980.pdf&lt;br /&gt;
	Gurmukhi					0A00–0A7F – https://unicode.org/charts/PDF/U0A00.pdf&lt;br /&gt;
	Gujarati					0A80–0AFF – https://unicode.org/charts/PDF/U0A80.pdf&lt;br /&gt;
	Oriya						0B00–0B7F – https://unicode.org/charts/PDF/U0B00.pdf&lt;br /&gt;
	Tamil						0B80–0BFF – https://unicode.org/charts/PDF/U0B80.pdf&lt;br /&gt;
	Telugu						0C00–0C7F – https://unicode.org/charts/PDF/U0C00.pdf&lt;br /&gt;
	Kannada						0C80–0CFF – https://unicode.org/charts/PDF/U0C80.pdf&lt;br /&gt;
	Malayalam					0D00–0D7F – https://unicode.org/charts/PDF/U0D00.pdf&lt;br /&gt;
plus the not-necessarily Indic scripts for Sinhala and Burmese:&lt;br /&gt;
	Sinhala						0D80-0DFF - https://unicode.org/charts/PDF/U0D80.pdf&lt;br /&gt;
	Myanmar						1000-109F - https://unicode.org/charts/PDF/U1000.pdf&lt;br /&gt;
		Myanmar extended A		AA60-AA7F - https://unicode.org/charts/PDF/UAA60.pdf&lt;br /&gt;
		Myanmar extended B		A9E0-A9FF - https://unicode.org/charts/PDF/UA9E0.pdf&lt;br /&gt;
the pattern is used by has_invisible_chars() and coins_cleanup()&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local indic_script = &#039;[\224\164\128-\224\181\191\224\163\160-\224\183\191\225\128\128-\225\130\159\234\167\160-\234\167\191\234\169\160-\234\169\191]&#039;;&lt;br /&gt;
&lt;br /&gt;
-- list of emoji that use zwj character (U+200D) to combine with another emoji&lt;br /&gt;
local emoji = {																	-- indexes are decimal forms of the hex values in U+xxxx&lt;br /&gt;
	[127752] = true,															-- U+1F308 🌈 rainbow&lt;br /&gt;
	[127806] = true,															-- U+1F33E 🌾 ear of rice&lt;br /&gt;
	[127859] = true,															-- U+1F373 🍳 cooking&lt;br /&gt;
	[127891] = true,															-- U+1F393 🎓 graduation cap&lt;br /&gt;
	[127908] = true,															-- U+1F3A4 🎤 microphone&lt;br /&gt;
	[127912] = true,															-- U+1F3A8 🎨 artist palette&lt;br /&gt;
	[127979] = true,															-- U+1F3EB 🏫 school&lt;br /&gt;
	[127981] = true,															-- U+1F3ED 🏭 factory&lt;br /&gt;
	[128102] = true,															-- U+1F466 👦 boy&lt;br /&gt;
	[128103] = true,															-- U+1F467 👧 girl&lt;br /&gt;
	[128104] = true,															-- U+1F468 👨 man&lt;br /&gt;
	[128105] = true,															-- U+1F469 👩 woman&lt;br /&gt;
	[128139] = true,															-- U+1F48B 💋 kiss mark&lt;br /&gt;
	[128187] = true,															-- U+1F4BB 💻 personal computer&lt;br /&gt;
	[128188] = true,															-- U+1F4BC 💼 brief case&lt;br /&gt;
	[128295] = true,															-- U+1F527 🔧 wrench&lt;br /&gt;
	[128300] = true,															-- U+1F52C 🔬 microscope&lt;br /&gt;
	[128488] = true,															-- U+1F5E8 🗨 left speech bubble&lt;br /&gt;
	[128640] = true,															-- U+1F680 🚀 rocket&lt;br /&gt;
	[128658] = true,															-- U+1F692 🚒 fire engine&lt;br /&gt;
	[129309] = true,															-- U+1F91D 🤝 handshake&lt;br /&gt;
	[129455] = true,															-- U+1F9AF 🦯 probing cane&lt;br /&gt;
	[129456] = true,															-- U+1F9B0 🦰 emoji component red hair&lt;br /&gt;
	[129457] = true,															-- U+1F9B1 🦱 emoji component curly hair&lt;br /&gt;
	[129458] = true,															-- U+1F9B2 🦲 emoji component bald&lt;br /&gt;
	[129459] = true,															-- U+1F9B3 🦳 emoji component white hair&lt;br /&gt;
	[129466] = true,															-- U+1F9BA 🦺 safety vest&lt;br /&gt;
	[129468] = true,															-- U+1F9BC 🦼 motorized wheelchair&lt;br /&gt;
	[129469] = true,															-- U+1F9BD 🦽 manual wheelchair&lt;br /&gt;
	[129489] = true,															-- U+1F9D1 🧑 adult&lt;br /&gt;
	[9760] = true,																-- U+2620 ☠ skull and crossbones&lt;br /&gt;
	[9792] = true,																-- U+2640 ♀ female sign&lt;br /&gt;
	[9794] = true,																-- U+2642 ♂ male sign&lt;br /&gt;
	[9877] = true,																-- U+2695 ⚕ staff of aesculapius&lt;br /&gt;
	[9878] = true,																-- U+2696 ⚖ scales&lt;br /&gt;
	[9992] = true,																-- U+2708 ✈ airplane&lt;br /&gt;
	[10084] = true,																-- U+2764 ❤ heavy black heart&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[----------------------&amp;lt; L A N G U A G E   S U P P O R T &amp;gt;-------------------&lt;br /&gt;
&lt;br /&gt;
These tables and constants support various language-specific functionality.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
--local this_wiki_code = mw.getContentLanguage():getCode();						-- get this wiki&#039;s language code&lt;br /&gt;
local this_wiki_code = lang_obj:getCode();										-- get this wiki&#039;s language code&lt;br /&gt;
if string.match (mw.site.server, &#039;wikidata&#039;) then&lt;br /&gt;
		this_wiki_code = mw.getCurrentFrame():preprocess(&#039;{{int:lang}}&#039;);		-- on Wikidata so use interface language setting instead&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
local mw_languages_by_tag_t = mw.language.fetchLanguageNames (this_wiki_code, &#039;all&#039;);	-- get a table of language tag/name pairs known to Wikimedia; used for interwiki tests&lt;br /&gt;
local mw_languages_by_name_t = {};&lt;br /&gt;
	for k, v in pairs (mw_languages_by_tag_t) do								-- build a &#039;reversed&#039; table name/tag language pairs know to MediaWiki; used for |language=&lt;br /&gt;
		v = mw.ustring.lower (v);												-- lowercase for tag fetch; get name&#039;s proper case from mw_languages_by_tag_t[&amp;lt;tag&amp;gt;]&lt;br /&gt;
		if mw_languages_by_name_t[v] then										-- when name already in the table&lt;br /&gt;
			if 2 == #k or 3 == #k then											-- if tag does not have subtags&lt;br /&gt;
				mw_languages_by_name_t[v] = k;									-- prefer the shortest tag for this name&lt;br /&gt;
			end&lt;br /&gt;
		else																	-- here when name not in the table&lt;br /&gt;
			mw_languages_by_name_t[v] = k;										-- so add name and matching tag&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
local inter_wiki_map = {};														-- map of interwiki prefixes that are language-code prefixes&lt;br /&gt;
	for k, v in pairs (mw.site.interwikiMap (&#039;local&#039;)) do						-- spin through the base interwiki map (limited to local)&lt;br /&gt;
		if mw_languages_by_tag_t[v[&amp;quot;prefix&amp;quot;]] then								-- if the prefix matches a known language tag&lt;br /&gt;
			inter_wiki_map[v[&amp;quot;prefix&amp;quot;]] = true;									-- add it to our local map&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------&amp;lt; S C R I P T _ L A N G _ C O D E S &amp;gt;-------------------&lt;br /&gt;
&lt;br /&gt;
This table is used to hold ISO 639-1 two-character and ISO 639-3 three-character&lt;br /&gt;
language codes that apply only to |script-title= and |script-chapter=&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local script_lang_codes = {&lt;br /&gt;
	&#039;ab&#039;, &#039;am&#039;, &#039;ar&#039;, &#039;be&#039;, &#039;bg&#039;, &#039;bn&#039;, &#039;bo&#039;, &#039;bs&#039;, &#039;dv&#039;, &#039;dz&#039;, &#039;el&#039;, &#039;fa&#039;, &#039;gu&#039;, &lt;br /&gt;
	&#039;he&#039;, &#039;hi&#039;, &#039;hy&#039;, &#039;ja&#039;, &#039;ka&#039;, &#039;kk&#039;, &#039;km&#039;, &#039;kn&#039;, &#039;ko&#039;, &#039;ku&#039;, &#039;ky&#039;, &#039;lo&#039;, &#039;mk&#039;,&lt;br /&gt;
	&#039;ml&#039;, &#039;mn&#039;, &#039;mr&#039;, &#039;my&#039;, &#039;ne&#039;, &#039;or&#039;, &#039;ota&#039;, &#039;ps&#039;, &#039;ru&#039;, &#039;sd&#039;, &#039;si&#039;, &#039;sr&#039;, &#039;syc&#039;,&lt;br /&gt;
	&#039;ta&#039;, &#039;te&#039;, &#039;tg&#039;, &#039;th&#039;, &#039;ti&#039;, &#039;ug&#039;, &#039;uk&#039;, &#039;ur&#039;, &#039;uz&#039;, &#039;yi&#039;, &#039;yue&#039;, &#039;zh&#039;&lt;br /&gt;
	};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[---------------&amp;lt; L A N G U A G E   R E M A P P I N G &amp;gt;----------------------&lt;br /&gt;
&lt;br /&gt;
These tables hold language information that is different (correct) from MediaWiki&#039;s definitions&lt;br /&gt;
&lt;br /&gt;
For each [&#039;code&#039;] = &#039;language name&#039; in lang_code_remap{} there must be a matching [&#039;language name&#039;] = {&#039;language name&#039;, &#039;code&#039;} in lang_name_remap{}&lt;br /&gt;
&lt;br /&gt;
lang_code_remap{}:&lt;br /&gt;
	key is always lowercase ISO 639-1, -2, -3 language code or a valid lowercase IETF language tag&lt;br /&gt;
	value is properly spelled and capitalized language name associated with key&lt;br /&gt;
	only one language name per key;&lt;br /&gt;
	key/value pair must have matching entry in lang_name_remap{}&lt;br /&gt;
&lt;br /&gt;
lang_name_remap{}:&lt;br /&gt;
	key is always lowercase language name&lt;br /&gt;
	value is a table the holds correctly spelled and capitalized language name [1] and associated code [2] (code must match a code key in lang_code_remap{})&lt;br /&gt;
	may have multiple keys referring to a common preferred name and code; For example:&lt;br /&gt;
		[&#039;kolsch&#039;] and [&#039;kölsch&#039;] both refer to &#039;Kölsch&#039; and &#039;ksh&#039;&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local lang_code_remap = {														-- used for |language= and |script-title= / |script-chapter=&lt;br /&gt;
	[&#039;als&#039;] = &#039;Tosk Albanian&#039;,													-- MediaWiki returns Alemannisch &lt;br /&gt;
	[&#039;bh&#039;] = &#039;Bihari&#039;,															-- MediaWiki uses &#039;bh&#039; as a subdomain name for Bhojpuri Wikipedia: bh.wikipedia.org&lt;br /&gt;
	[&#039;bla&#039;] = &#039;Blackfoot&#039;,														-- MediaWiki/IANA/ISO 639: Siksika; use en.wiki preferred name&lt;br /&gt;
	[&#039;bn&#039;] = &#039;Bengali&#039;,															-- MediaWiki returns Bangla&lt;br /&gt;
	[&#039;ca-valencia&#039;] = &#039;Valencian&#039;,												-- IETF variant of Catalan&lt;br /&gt;
	[&#039;ilo&#039;] = &#039;Ilocano&#039;,														-- MediaWiki/IANA/ISO 639: Iloko; use en.wiki preferred name&lt;br /&gt;
	[&#039;ksh&#039;] = &#039;Kölsch&#039;,															-- MediaWiki: Colognian; use IANA/ISO 639 preferred name&lt;br /&gt;
	[&#039;ksh-x-colog&#039;] = &#039;Colognian&#039;,												-- override MediaWiki ksh; no IANA/ISO 639 code for Colognian; IETF private code created at Module:Lang/data&lt;br /&gt;
	[&#039;mis-x-ripuar&#039;] = &#039;Ripuarian&#039;,												-- override MediaWiki ksh; no IANA/ISO 639 code for Ripuarian; IETF private code created at Module:Lang/data&lt;br /&gt;
	[&#039;nan-tw&#039;] = &#039;Taiwanese Hokkien&#039;,											-- make room for MediaWiki/IANA/ISO 639 nan: Min Nan Chinese and support en.wiki preferred name&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
local lang_name_remap = {														-- used for |language=; names require proper capitalization; tags must be lowercase&lt;br /&gt;
	[&#039;alemannisch&#039;] = {&#039;Swiss German&#039;, &#039;gsw&#039;},									-- not an ISO or IANA language name; MediaWiki uses &#039;als&#039; as a subdomain name for Alemannic Wikipedia: als.wikipedia.org&lt;br /&gt;
	[&#039;bangla&#039;] = {&#039;Bengali&#039;, &#039;bn&#039;},												-- MediaWiki returns Bangla (the endonym) but we want Bengali (the exonym); here we remap&lt;br /&gt;
	[&#039;bengali&#039;] = {&#039;Bengali&#039;, &#039;bn&#039;},											-- MediaWiki doesn&#039;t use exonym so here we provide correct language name and 639-1 code&lt;br /&gt;
	[&#039;bhojpuri&#039;] = {&#039;Bhojpuri&#039;, &#039;bho&#039;},											-- MediaWiki uses &#039;bh&#039; as a subdomain name for Bhojpuri Wikipedia: bh.wikipedia.org&lt;br /&gt;
	[&#039;bihari&#039;] = {&#039;Bihari&#039;, &#039;bh&#039;},												-- MediaWiki replaces &#039;Bihari&#039; with &#039;Bhojpuri&#039; so &#039;Bihari&#039; cannot be found&lt;br /&gt;
	[&#039;blackfoot&#039;] = {&#039;Blackfoot&#039;, &#039;bla&#039;},										-- MediaWiki/IANA/ISO 639: Siksika; use en.wiki preferred name&lt;br /&gt;
	[&#039;colognian&#039;] = {&#039;Colognian&#039;, &#039;ksh-x-colog&#039;},								-- MediaWiki preferred name for ksh&lt;br /&gt;
	[&#039;ilocano&#039;] = {&#039;Ilocano&#039;, &#039;ilo&#039;},											-- MediaWiki/IANA/ISO 639: Iloko; use en.wiki preferred name&lt;br /&gt;
	[&#039;kolsch&#039;] = {&#039;Kölsch&#039;, &#039;ksh&#039;},												-- use IANA/ISO 639 preferred name (use non-diacritical o instead of umlaut ö)&lt;br /&gt;
	[&#039;kölsch&#039;] = {&#039;Kölsch&#039;, &#039;ksh&#039;},												-- use IANA/ISO 639 preferred name&lt;br /&gt;
	[&#039;ripuarian&#039;] = {&#039;Ripuarian&#039;, &#039;mis-x-ripuar&#039;},								-- group of dialects; no code in MediaWiki or in IANA/ISO 639&lt;br /&gt;
	[&#039;taiwanese hokkien&#039;] = {&#039;Taiwanese Hokkien&#039;, &#039;nan-tw&#039;},					-- make room for MediaWiki/IANA/ISO 639 nan: Min Nan Chinese &lt;br /&gt;
	[&#039;tosk albanian&#039;] = {&#039;Tosk Albanian&#039;, &#039;als&#039;},								-- MediaWiki replaces &#039;Tosk Albanian&#039; with &#039;Alemannisch&#039; so &#039;Tosk Albanian&#039; cannot be found&lt;br /&gt;
	[&#039;valencian&#039;] = {&#039;Valencian&#039;, &#039;ca&#039;},										-- variant of Catalan; categorizes as Catalan&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[---------------&amp;lt; P R O P E R T I E S _ C A T E G O R I E S &amp;gt;----------------&lt;br /&gt;
&lt;br /&gt;
Properties categories. These are used for investigating qualities of citations.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local prop_cats = {&lt;br /&gt;
	[&#039;foreign-lang-source&#039;] = &#039;CS1 $1-language sources ($2)&#039;,					-- |language= categories; $1 is foreign-language name, $2 is ISO639-1 code&lt;br /&gt;
	[&#039;foreign-lang-source-2&#039;] = &#039;CS1 foreign language sources (ISO 639-2)|$1&#039;,	-- |language= category; a cat for ISO639-2 languages; $1 is the ISO 639-2 code used as a sort key&lt;br /&gt;
	[&#039;jul-greg-uncertainty&#039;] = &#039;CS1: Julian–Gregorian uncertainty&#039;,				-- probably temporary cat to identify scope of template with dates 1 October 1582 – 1 January 1926&lt;br /&gt;
	[&#039;local-lang-source&#039;] = &#039;CS1 $1-language sources ($2)&#039;,						-- |language= categories; $1 is local-language name, $2 is ISO639-1 code; not emitted when local_lang_cat_enable is false&lt;br /&gt;
	[&#039;location-test&#039;] = &#039;CS1 location test&#039;,&lt;br /&gt;
	[&#039;long-vol&#039;] = &#039;CS1: long volume value&#039;,									-- probably temporary cat to identify scope of |volume= values longer than 4 charachters&lt;br /&gt;
	[&#039;script&#039;] = &#039;CS1 uses $1-language script ($2)&#039;,							-- |script-title=xx: has matching category; $1 is language name, $2 is ISO639-1 code&lt;br /&gt;
	[&#039;tracked-param&#039;] = &#039;CS1 tracked parameter: $1&#039;,							-- $1 is base (enumerators removed) parameter name&lt;br /&gt;
	[&#039;year-range-abbreviated&#039;] = &#039;CS1: abbreviated year range&#039;,					-- probably temporary cat to identify scope of |date=, |year= values using YYYY–YY form&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[-------------------&amp;lt; T I T L E _ T Y P E S &amp;gt;--------------------------------&lt;br /&gt;
&lt;br /&gt;
Here we map a template&#039;s CitationClass to TitleType (default values for |type= parameter)&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local title_types = {&lt;br /&gt;
	[&#039;AV-media-notes&#039;] = &#039;Media notes&#039;,&lt;br /&gt;
	[&#039;interview&#039;] = &#039;Interview&#039;,&lt;br /&gt;
	[&#039;mailinglist&#039;] = &#039;Mailing list&#039;,&lt;br /&gt;
	[&#039;map&#039;] = &#039;Map&#039;,&lt;br /&gt;
	[&#039;podcast&#039;] = &#039;Podcast&#039;,&lt;br /&gt;
	[&#039;pressrelease&#039;] = &#039;Press release&#039;,&lt;br /&gt;
	[&#039;report&#039;] = &#039;Report&#039;,&lt;br /&gt;
	[&#039;speech&#039;] = &#039;Speech&#039;,&lt;br /&gt;
	[&#039;techreport&#039;] = &#039;Technical report&#039;,&lt;br /&gt;
	[&#039;thesis&#039;] = &#039;Thesis&#039;,&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[===================&amp;lt;&amp;lt; E R R O R   M E S S A G I N G &amp;gt;&amp;gt;======================&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
--[[----------&amp;lt; E R R O R   M E S S A G E   S U P P L I M E N T S &amp;gt;-------------&lt;br /&gt;
&lt;br /&gt;
I18N for those messages that are supplemented with additional specific text that&lt;br /&gt;
describes the reason for the error&lt;br /&gt;
&lt;br /&gt;
TODO: merge this with special_case_translations{}?&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local err_msg_supl = {&lt;br /&gt;
	[&#039;char&#039;] = &#039;invalid character&#039;,												-- |isbn=, |sbn=&lt;br /&gt;
	[&#039;check&#039;] = &#039;checksum&#039;,														-- |isbn=, |sbn=&lt;br /&gt;
	[&#039;flag&#039;] = &#039;flag&#039;,															-- |archive-url=&lt;br /&gt;
	[&#039;form&#039;] = &#039;invalid form&#039;,													-- |isbn=, |sbn=&lt;br /&gt;
	[&#039;group&#039;] = &#039;invalid group id&#039;,												-- |isbn=&lt;br /&gt;
	[&#039;initials&#039;] = &#039;initials&#039;,													-- Vancouver&lt;br /&gt;
	[&#039;invalid language code&#039;] = &#039;invalid language code&#039;,						-- |script-&amp;lt;param&amp;gt;=&lt;br /&gt;
	[&#039;journal&#039;] = &#039;journal&#039;,													-- |bibcode=&lt;br /&gt;
	[&#039;length&#039;] = &#039;length&#039;,														-- |isbn=, |bibcode=, |sbn=&lt;br /&gt;
	[&#039;liveweb&#039;] = &#039;liveweb&#039;,													-- |archive-url=&lt;br /&gt;
	[&#039;missing comma&#039;] = &#039;missing comma&#039;,										-- Vancouver&lt;br /&gt;
	[&#039;missing prefix&#039;] = &#039;missing prefix&#039;,										-- |script-&amp;lt;param&amp;gt;=&lt;br /&gt;
	[&#039;missing title part&#039;] = &#039;missing title part&#039;,								-- |script-&amp;lt;param&amp;gt;=&lt;br /&gt;
	[&#039;name&#039;] = &#039;name&#039;,															-- Vancouver&lt;br /&gt;
	[&#039;non-Latin char&#039;] = &#039;non-Latin character&#039;,									-- Vancouver&lt;br /&gt;
	[&#039;path&#039;] = &#039;path&#039;,															-- |archive-url=&lt;br /&gt;
	[&#039;prefix&#039;] = &#039;invalid prefix&#039;,												-- |isbn=&lt;br /&gt;
	[&#039;punctuation&#039;] = &#039;punctuation&#039;,											-- Vancouver&lt;br /&gt;
	[&#039;save&#039;] = &#039;save command&#039;,													-- |archive-url=&lt;br /&gt;
	[&#039;suffix&#039;] = &#039;suffix&#039;,														-- Vancouver&lt;br /&gt;
	[&#039;timestamp&#039;] = &#039;timestamp&#039;,												-- |archive-url=&lt;br /&gt;
	[&#039;unknown language code&#039;] = &#039;unknown language code&#039;,						-- |script-&amp;lt;param&amp;gt;=&lt;br /&gt;
	[&#039;value&#039;] = &#039;value&#039;,														-- |bibcode=&lt;br /&gt;
	[&#039;year&#039;] = &#039;year&#039;,															-- |bibcode=&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------&amp;lt; E R R O R _ C O N D I T I O N S &amp;gt;---------------------------&lt;br /&gt;
&lt;br /&gt;
Error condition table.  This table has two sections: errors at the top, maintenance&lt;br /&gt;
at the bottom.  Maint &#039;messaging&#039; does not have a &#039;message&#039; (message=nil)&lt;br /&gt;
&lt;br /&gt;
The following contains a list of IDs for various error conditions defined in the&lt;br /&gt;
code.  For each ID, we specify a text message to display, an error category to&lt;br /&gt;
include, and whether the error message should be wrapped as a hidden comment.&lt;br /&gt;
&lt;br /&gt;
Anchor changes require identical changes to matching anchor in Help:CS1 errors&lt;br /&gt;
&lt;br /&gt;
TODO: rename error_conditions{} to something more generic; create separate error&lt;br /&gt;
and maint tables inside that?&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local error_conditions = {&lt;br /&gt;
	err_accessdate_missing_url = {&lt;br /&gt;
		message = &#039;&amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;access-date=&amp;lt;/code&amp;gt; requires &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;url=&amp;lt;/code&amp;gt;&#039;,&lt;br /&gt;
		anchor = &#039;accessdate_missing_url&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: access-date without URL&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
 		},&lt;br /&gt;
	err_apostrophe_markup = {&lt;br /&gt;
		message = &#039;Italic or bold markup not allowed in: &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1=&amp;lt;/code&amp;gt;&#039;,	-- $1 is parameter name&lt;br /&gt;
		anchor = &#039;apostrophe_markup&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: markup&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
 		},&lt;br /&gt;
	err_archive_missing_date = {&lt;br /&gt;
		message = &#039;&amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;archive-url=&amp;lt;/code&amp;gt; requires &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;archive-date=&amp;lt;/code&amp;gt;&#039;,&lt;br /&gt;
		anchor = &#039;archive_missing_date&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: archive-url&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_archive_missing_url = {&lt;br /&gt;
		message = &#039;&amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;archive-url=&amp;lt;/code&amp;gt; requires &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;url=&amp;lt;/code&amp;gt;&#039;,&lt;br /&gt;
		anchor = &#039;archive_missing_url&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: archive-url&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_archive_url = {&lt;br /&gt;
		message = &#039;&amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;archive-url=&amp;lt;/code&amp;gt; is malformed: $1&#039;,	-- $1 is error message detail&lt;br /&gt;
		anchor = &#039;archive_url&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: archive-url&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_arxiv_missing = {&lt;br /&gt;
		message = &#039;&amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;arxiv=&amp;lt;/code&amp;gt; required&#039;,&lt;br /&gt;
		anchor = &#039;arxiv_missing&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: arXiv&#039;,											-- same as bad arxiv&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_asintld_missing_asin = {&lt;br /&gt;
		message = &#039;&amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1=&amp;lt;/code&amp;gt; requires &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;asin=&amp;lt;/code&amp;gt;&#039;,	-- $1 is parameter name&lt;br /&gt;
		anchor = &#039;asintld_missing_asin&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: ASIN TLD&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_arxiv = {&lt;br /&gt;
		message = &#039;Check &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;arxiv=&amp;lt;/code&amp;gt; value&#039;,&lt;br /&gt;
		anchor = &#039;bad_arxiv&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: arXiv&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_asin = {&lt;br /&gt;
		message = &#039;Check &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;asin=&amp;lt;/code&amp;gt; value&#039;,&lt;br /&gt;
		anchor = &#039;bad_asin&#039;,&lt;br /&gt;
		category =&#039;CS1 errors: ASIN&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_asin_tld = {&lt;br /&gt;
		message = &#039;Check &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;asin-tld=&amp;lt;/code&amp;gt; value&#039;,&lt;br /&gt;
		anchor = &#039;bad_asin_tld&#039;,&lt;br /&gt;
		category =&#039;CS1 errors: ASIN TLD&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_bibcode = {&lt;br /&gt;
		message = &#039;Check &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;bibcode=&amp;lt;/code&amp;gt; $1&#039;,		-- $1 is error message detail&lt;br /&gt;
		anchor = &#039;bad_bibcode&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: bibcode&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_biorxiv = {&lt;br /&gt;
		message = &#039;Check &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;biorxiv=&amp;lt;/code&amp;gt; value&#039;,&lt;br /&gt;
		anchor = &#039;bad_biorxiv&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: bioRxiv&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_citeseerx = {&lt;br /&gt;
		message = &#039;Check &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;citeseerx=&amp;lt;/code&amp;gt; value&#039;,&lt;br /&gt;
		anchor = &#039;bad_citeseerx&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: citeseerx&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_date = {&lt;br /&gt;
		message = &#039;Check date values in: $1&#039;,									-- $1 is a parameter name list&lt;br /&gt;
		anchor = &#039;bad_date&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: dates&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_doi = {&lt;br /&gt;
		message = &#039;Check &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;doi=&amp;lt;/code&amp;gt; value&#039;,&lt;br /&gt;
		anchor = &#039;bad_doi&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: DOI&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_hdl = {&lt;br /&gt;
		message = &#039;Check &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;hdl=&amp;lt;/code&amp;gt; value&#039;,&lt;br /&gt;
		anchor = &#039;bad_hdl&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: HDL&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_isbn = {&lt;br /&gt;
		message = &#039;Check &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;isbn=&amp;lt;/code&amp;gt; value: $1&#039;,	-- $1 is error message detail&lt;br /&gt;
		anchor = &#039;bad_isbn&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: ISBN&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_ismn = {&lt;br /&gt;
		message = &#039;Check &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;ismn=&amp;lt;/code&amp;gt; value&#039;,&lt;br /&gt;
		anchor = &#039;bad_ismn&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: ISMN&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_issn = {&lt;br /&gt;
		message = &#039;Check &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1issn=&amp;lt;/code&amp;gt; value&#039;,	-- $1 is &#039;e&#039; or &#039;&#039; for eissn or issn&lt;br /&gt;
		anchor = &#039;bad_issn&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: ISSN&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_jfm = {&lt;br /&gt;
		message = &#039;Check &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;jfm=&amp;lt;/code&amp;gt; value&#039;,&lt;br /&gt;
		anchor = &#039;bad_jfm&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: JFM&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_jstor = {&lt;br /&gt;
		message = &#039;Check &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;jstor=&amp;lt;/code&amp;gt; value&#039;,&lt;br /&gt;
		anchor = &#039;bad_jstor&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: JSTOR&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_lccn = {&lt;br /&gt;
		message = &#039;Check &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;lccn=&amp;lt;/code&amp;gt; value&#039;,&lt;br /&gt;
		anchor = &#039;bad_lccn&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: LCCN&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_mr = {&lt;br /&gt;
		message = &#039;Check &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;mr=&amp;lt;/code&amp;gt; value&#039;,&lt;br /&gt;
		anchor = &#039;bad_mr&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: MR&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_oclc = {&lt;br /&gt;
		message = &#039;Check &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;oclc=&amp;lt;/code&amp;gt; value&#039;,&lt;br /&gt;
		anchor = &#039;bad_oclc&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: OCLC&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_ol = {&lt;br /&gt;
		message = &#039;Check &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;ol=&amp;lt;/code&amp;gt; value&#039;,&lt;br /&gt;
		anchor = &#039;bad_ol&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: OL&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_osti = {&lt;br /&gt;
		message = &#039;Check &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;osti=&amp;lt;/code&amp;gt; value&#039;,&lt;br /&gt;
		anchor = &#039;bad_osti&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: OSTI&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_paramlink = {														-- for |title-link=, |author/editor/translator-link=, |series-link=, |episode-link=&lt;br /&gt;
		message = &#039;Check &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1=&amp;lt;/code&amp;gt; value&#039;,		-- $1 is parameter name&lt;br /&gt;
		anchor = &#039;bad_paramlink&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: parameter link&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_pmc = {&lt;br /&gt;
		message = &#039;Check &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;pmc=&amp;lt;/code&amp;gt; value&#039;,&lt;br /&gt;
		anchor = &#039;bad_pmc&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: PMC&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_pmid = {&lt;br /&gt;
		message = &#039;Check &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;pmid=&amp;lt;/code&amp;gt; value&#039;,&lt;br /&gt;
		anchor = &#039;bad_pmid&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: PMID&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_rfc = {&lt;br /&gt;
		message = &#039;Check &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;rfc=&amp;lt;/code&amp;gt; value&#039;,&lt;br /&gt;
		anchor = &#039;bad_rfc&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: RFC&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_s2cid = {&lt;br /&gt;
		message = &#039;Check &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;s2cid=&amp;lt;/code&amp;gt; value&#039;,&lt;br /&gt;
		anchor = &#039;bad_s2cid&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: S2CID&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_sbn = {&lt;br /&gt;
		message = &#039;Check &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;sbn=&amp;lt;/code&amp;gt; value: $1&#039;,	-- $1 is error message detail&lt;br /&gt;
		anchor = &#039;bad_sbn&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: SBN&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_ssrn = {&lt;br /&gt;
		message = &#039;Check &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;ssrn=&amp;lt;/code&amp;gt; value&#039;,&lt;br /&gt;
		anchor = &#039;bad_ssrn&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: SSRN&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_url = {&lt;br /&gt;
		message = &#039;Check $1 value&#039;,												-- $1 is parameter name&lt;br /&gt;
		anchor = &#039;bad_url&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: URL&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_usenet_id = {&lt;br /&gt;
		message = &#039;Check &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;message-id=&amp;lt;/code&amp;gt; value&#039;,&lt;br /&gt;
		anchor = &#039;bad_message_id&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: message-id&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bad_zbl = {&lt;br /&gt;
		message = &#039;Check &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;zbl=&amp;lt;/code&amp;gt; value&#039;,&lt;br /&gt;
		anchor = &#039;bad_zbl&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: Zbl&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_bare_url_missing_title = {&lt;br /&gt;
		message = &#039;$1 missing title&#039;,											-- $1 is parameter name&lt;br /&gt;
		anchor = &#039;bare_url_missing_title&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: bare URL&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_biorxiv_missing = {&lt;br /&gt;
		message = &#039;&amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;biorxiv=&amp;lt;/code&amp;gt; required&#039;,&lt;br /&gt;
		anchor = &#039;biorxiv_missing&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: bioRxiv&#039;,										-- same as bad bioRxiv&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_chapter_ignored = {&lt;br /&gt;
		message = &#039;&amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1=&amp;lt;/code&amp;gt; ignored&#039;,			-- $1 is parameter name&lt;br /&gt;
		anchor = &#039;chapter_ignored&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: chapter ignored&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_citation_missing_title = {&lt;br /&gt;
		message = &#039;Missing or empty &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1=&amp;lt;/code&amp;gt;&#039;,	-- $1 is parameter name&lt;br /&gt;
		anchor = &#039;citation_missing_title&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: missing title&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_citeseerx_missing = {&lt;br /&gt;
		message = &#039;&amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;citeseerx=&amp;lt;/code&amp;gt; required&#039;,&lt;br /&gt;
		anchor = &#039;citeseerx_missing&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: citeseerx&#039;,										-- same as bad citeseerx&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_cite_web_url = {														-- this error applies to cite web and to cite podcast&lt;br /&gt;
		message = &#039;Missing or empty &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;url=&amp;lt;/code&amp;gt;&#039;,&lt;br /&gt;
		anchor = &#039;cite_web_url&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: requires URL&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_class_ignored = {&lt;br /&gt;
		message = &#039;&amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;class=&amp;lt;/code&amp;gt; ignored&#039;,&lt;br /&gt;
		anchor = &#039;class_ignored&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: class&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_contributor_ignored = {&lt;br /&gt;
		message = &#039;&amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;contributor=&amp;lt;/code&amp;gt; ignored&#039;,&lt;br /&gt;
		anchor = &#039;contributor_ignored&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: contributor&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_contributor_missing_required_param = {&lt;br /&gt;
		message = &#039;&amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;contributor=&amp;lt;/code&amp;gt; requires &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1=&amp;lt;/code&amp;gt;&#039;,	-- $1 is parameter name&lt;br /&gt;
		anchor = &#039;contributor_missing_required_param&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: contributor&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_deprecated_params = {&lt;br /&gt;
		message = &#039;Cite uses deprecated parameter &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1=&amp;lt;/code&amp;gt;&#039;,	-- $1 is parameter name&lt;br /&gt;
		anchor = &#039;deprecated_params&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: deprecated parameters&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_disp_name = {&lt;br /&gt;
		message = &#039;Invalid &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1=$2&amp;lt;/code&amp;gt;&#039;,			-- $1 is parameter name; $2 is the assigned value&lt;br /&gt;
		anchor = &#039;disp_name&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: display-names&#039;,&lt;br /&gt;
		hidden = false,&lt;br /&gt;
		},&lt;br /&gt;
	err_doibroken_missing_doi = {&lt;br /&gt;
		message = &#039;&amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1=&amp;lt;/code&amp;gt; requires &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;doi=&amp;lt;/code&amp;gt;&#039;,	-- $1 is parameter name&lt;br /&gt;
		anchor = &#039;doibroken_missing_doi&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: DOI&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_embargo_missing_pmc = {&lt;br /&gt;
		message = &#039;&amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1=&amp;lt;/code&amp;gt; requires &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;pmc=&amp;lt;/code&amp;gt;&#039;,	-- $1 is parameter name&lt;br /&gt;
		anchor = &#039;embargo_missing_pmc&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: PMC embargo&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_empty_citation = {&lt;br /&gt;
		message = &#039;Empty citation&#039;,&lt;br /&gt;
		anchor = &#039;empty_citation&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: empty citation&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_etal = {&lt;br /&gt;
		message = &#039;Explicit use of et al. in: &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1=&amp;lt;/code&amp;gt;&#039;,	-- $1 is parameter name&lt;br /&gt;
		anchor = &#039;explicit_et_al&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: explicit use of et al.&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_extra_text_edition = {&lt;br /&gt;
		message = &#039;&amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;edition=&amp;lt;/code&amp;gt; has extra text&#039;,&lt;br /&gt;
		anchor = &#039;extra_text_edition&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: extra text: edition&#039;,&lt;br /&gt;
		hidden = false,&lt;br /&gt;
		},&lt;br /&gt;
	err_extra_text_issue = {&lt;br /&gt;
		message = &#039;&amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1=&amp;lt;/code&amp;gt; has extra text&#039;,		-- $1 is parameter name&lt;br /&gt;
		anchor = &#039;extra_text_issue&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: extra text: issue&#039;,&lt;br /&gt;
		hidden = false,&lt;br /&gt;
		},&lt;br /&gt;
	err_extra_text_pages = {&lt;br /&gt;
		message = &#039;&amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1=&amp;lt;/code&amp;gt; has extra text&#039;,		-- $1 is parameter name&lt;br /&gt;
		anchor = &#039;extra_text_pages&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: extra text: pages&#039;,&lt;br /&gt;
		hidden = false,&lt;br /&gt;
		},&lt;br /&gt;
	err_extra_text_volume = {&lt;br /&gt;
		message = &#039;&amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1=&amp;lt;/code&amp;gt; has extra text&#039;,		-- $1 is parameter name&lt;br /&gt;
		anchor = &#039;extra_text_volume&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: extra text: volume&#039;,&lt;br /&gt;
		hidden = true,&lt;br /&gt;
		},&lt;br /&gt;
	err_first_missing_last = {&lt;br /&gt;
		message = &#039;&amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1=&amp;lt;/code&amp;gt; missing &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$2=&amp;lt;/code&amp;gt;&#039;,	-- $1 is first alias, $2 is matching last alias&lt;br /&gt;
		anchor = &#039;first_missing_last&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: missing name&#039;, -- author, contributor, editor, interviewer, translator&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_format_missing_url = {&lt;br /&gt;
		message = &#039;&amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1=&amp;lt;/code&amp;gt; requires &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$2=&amp;lt;/code&amp;gt;&#039;,	-- $1 is format parameter $2 is url parameter&lt;br /&gt;
		anchor = &#039;format_missing_url&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: format without URL&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_generic_name = {&lt;br /&gt;
		message = &#039;&amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1=&amp;lt;/code&amp;gt; has generic name&#039;,	-- $1 is parameter name&lt;br /&gt;
		anchor = &#039;generic_name&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: generic name&#039;,&lt;br /&gt;
		hidden = false,&lt;br /&gt;
		},&lt;br /&gt;
	err_generic_title = {&lt;br /&gt;
		message = &#039;Cite uses generic title&#039;,&lt;br /&gt;
		anchor = &#039;generic_title&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: generic title&#039;,&lt;br /&gt;
		hidden = false,&lt;br /&gt;
		},&lt;br /&gt;
	err_invalid_param_val = {&lt;br /&gt;
		message = &#039;Invalid &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1=$2&amp;lt;/code&amp;gt;&#039;,			-- $1 is parameter name $2 is parameter value&lt;br /&gt;
		anchor = &#039;invalid_param_val&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: invalid parameter value&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_invisible_char = {&lt;br /&gt;
		message = &#039;$1 in $2 at position $3&#039;,									-- $1 is invisible char $2 is parameter name $3 is position number&lt;br /&gt;
		anchor = &#039;invisible_char&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: invisible characters&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_missing_name = {&lt;br /&gt;
		message = &#039;Missing &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1$2=&amp;lt;/code&amp;gt;&#039;,			-- $1 is modified NameList; $2 is enumerator&lt;br /&gt;
		anchor = &#039;missing_name&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: missing name&#039;,									-- author, contributor, editor, interviewer, translator&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_missing_periodical = {&lt;br /&gt;
		message = &#039;Cite $1 requires &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$2=&amp;lt;/code&amp;gt;&#039;,	-- $1 is cs1 template name; $2 is canonical periodical parameter name for cite $1&lt;br /&gt;
		anchor = &#039;missing_periodical&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: missing periodical&#039;,&lt;br /&gt;
		hidden = true&lt;br /&gt;
		},&lt;br /&gt;
	err_missing_pipe = {&lt;br /&gt;
		message = &#039;Missing pipe in: &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1=&amp;lt;/code&amp;gt;&#039;,	-- $1 is parameter name&lt;br /&gt;
		anchor = &#039;missing_pipe&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: missing pipe&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_param_access_requires_param = {&lt;br /&gt;
		message = &#039;&amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1-access=&amp;lt;/code&amp;gt; requires &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1=&amp;lt;/code&amp;gt;&#039;,	-- $1 is parameter name&lt;br /&gt;
		anchor = &#039;param_access_requires_param&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: param-access&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_param_has_ext_link = {&lt;br /&gt;
		message = &#039;External link in &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;$1&amp;lt;/code&amp;gt;&#039;,			-- $1 is parameter name&lt;br /&gt;
		anchor = &#039;param_has_ext_link&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: external links&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_parameter_ignored = {&lt;br /&gt;
		message = &#039;Unknown parameter &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1=&amp;lt;/code&amp;gt; ignored&#039;,	-- $1 is parameter name&lt;br /&gt;
		anchor = &#039;parameter_ignored&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: unsupported parameter&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_parameter_ignored_suggest = {&lt;br /&gt;
		message = &#039;Unknown parameter &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1=&amp;lt;/code&amp;gt; ignored (&amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$2=&amp;lt;/code&amp;gt; suggested)&#039;,	-- $1 is unknown parameter $2 is suggested parameter name&lt;br /&gt;
		anchor = &#039;parameter_ignored_suggest&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: unsupported parameter&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_redundant_parameters = {&lt;br /&gt;
		message = &#039;More than one of $1 specified&#039;,								-- $1 is error message detail&lt;br /&gt;
		anchor = &#039;redundant_parameters&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: redundant parameter&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_script_parameter = {&lt;br /&gt;
		message = &#039;Invalid &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1=&amp;lt;/code&amp;gt;: $2&#039;,		-- $1 is parameter name $2 is script language code or error detail&lt;br /&gt;
		anchor = &#039;script_parameter&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: script parameters&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_ssrn_missing = {&lt;br /&gt;
		message = &#039;&amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;ssrn=&amp;lt;/code&amp;gt; required&#039;,&lt;br /&gt;
		anchor = &#039;ssrn_missing&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: SSRN&#039;,											-- same as bad arxiv&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_text_ignored = {&lt;br /&gt;
		message = &#039;Text &amp;quot;$1&amp;quot; ignored&#039;,											-- $1 is ignored text&lt;br /&gt;
		anchor = &#039;text_ignored&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: unrecognized parameter&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_trans_missing_title = {&lt;br /&gt;
		message = &#039;&amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;trans-$1=&amp;lt;/code&amp;gt; requires &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;$1=&amp;lt;/code&amp;gt; or &amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;&amp;amp;#124;script-$1=&amp;lt;/code&amp;gt;&#039;,	-- $1 is base parameter name&lt;br /&gt;
		anchor = &#039;trans_missing_title&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: translated title&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_param_unknown_empty = {&lt;br /&gt;
		message = &#039;Cite has empty unknown parameter$1: $2&#039;,						-- $1 is &#039;s&#039; or empty space; $2 is emty unknown param list&lt;br /&gt;
		anchor = &#039;param_unknown_empty&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: empty unknown parameters&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_vancouver = {&lt;br /&gt;
		message = &#039;Vancouver style error: $1 in name $2&#039;,						-- $1 is error detail, $2 is the nth name&lt;br /&gt;
		anchor = &#039;vancouver&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: Vancouver style&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	err_wikilink_in_url = {&lt;br /&gt;
		message = &#039;URL–wikilink conflict&#039;,										-- uses ndash&lt;br /&gt;
		anchor = &#039;wikilink_in_url&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: URL–wikilink conflict&#039;,							-- uses ndash&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; M A I N T &amp;gt;-------------------------------------&lt;br /&gt;
&lt;br /&gt;
maint messages do not have a message (message = nil); otherwise the structure&lt;br /&gt;
is the same as error messages&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
	maint_archived_copy = {&lt;br /&gt;
		message = nil,&lt;br /&gt;
		anchor = &#039;archived_copy&#039;,&lt;br /&gt;
		category = &#039;CS1 maint: archived copy as title&#039;,&lt;br /&gt;
		hidden = true,&lt;br /&gt;
		},&lt;br /&gt;
	maint_authors = {&lt;br /&gt;
		message = nil,&lt;br /&gt;
		anchor = &#039;authors&#039;,&lt;br /&gt;
		category = &#039;CS1 maint: uses authors parameter&#039;,&lt;br /&gt;
		hidden = true,&lt;br /&gt;
		},&lt;br /&gt;
	maint_bot_unknown = {&lt;br /&gt;
		message = nil,&lt;br /&gt;
		anchor = &#039;bot:_unknown&#039;,&lt;br /&gt;
		category = &#039;CS1 maint: bot: original URL status unknown&#039;,&lt;br /&gt;
		hidden = true,&lt;br /&gt;
		},&lt;br /&gt;
	maint_date_auto_xlated = {													-- date auto-translation not supported by en.wiki&lt;br /&gt;
		message = nil,&lt;br /&gt;
		anchor = &#039;date_auto_xlated&#039;,&lt;br /&gt;
		category = &#039;CS1 maint: date auto-translated&#039;,&lt;br /&gt;
		hidden = true,&lt;br /&gt;
		},&lt;br /&gt;
	maint_date_format = {&lt;br /&gt;
		message = nil,&lt;br /&gt;
		anchor = &#039;date_format&#039;,&lt;br /&gt;
		category = &#039;CS1 maint: date format&#039;,&lt;br /&gt;
		hidden = true,&lt;br /&gt;
		},&lt;br /&gt;
	maint_date_year = {&lt;br /&gt;
		message = nil,&lt;br /&gt;
		anchor = &#039;date_year&#039;,&lt;br /&gt;
		category = &#039;CS1 maint: date and year&#039;,&lt;br /&gt;
		hidden = true,&lt;br /&gt;
		},&lt;br /&gt;
	maint_doi_ignore = {&lt;br /&gt;
		message = nil,&lt;br /&gt;
		anchor = &#039;doi_ignore&#039;,&lt;br /&gt;
		category = &#039;CS1 maint: ignored DOI errors&#039;,&lt;br /&gt;
		hidden = true,&lt;br /&gt;
		},&lt;br /&gt;
	maint_doi_inactive = {&lt;br /&gt;
		message = nil,&lt;br /&gt;
		anchor = &#039;doi_inactive&#039;,&lt;br /&gt;
		category = &#039;CS1 maint: DOI inactive&#039;,&lt;br /&gt;
		hidden = true,&lt;br /&gt;
		},&lt;br /&gt;
	maint_doi_inactive_dated = {&lt;br /&gt;
		message = nil,&lt;br /&gt;
		anchor = &#039;doi_inactive_dated&#039;,&lt;br /&gt;
		category = &#039;CS1 maint: DOI inactive as of $2$3$1&#039;,						-- $1 is year, $2 is month-name or empty string, $3 is space or empty string&lt;br /&gt;
		hidden = true,&lt;br /&gt;
		},&lt;br /&gt;
	maint_extra_punct = {&lt;br /&gt;
		message = nil,&lt;br /&gt;
		anchor = &#039;extra_punct&#039;,&lt;br /&gt;
		category = &#039;CS1 maint: extra punctuation&#039;,&lt;br /&gt;
		hidden = true,&lt;br /&gt;
		},&lt;br /&gt;
	maint_isbn_ignore = {&lt;br /&gt;
		message = nil,&lt;br /&gt;
		anchor = &#039;ignore_isbn_err&#039;,&lt;br /&gt;
		category = &#039;CS1 maint: ignored ISBN errors&#039;,&lt;br /&gt;
		hidden = true,&lt;br /&gt;
		},&lt;br /&gt;
	maint_issn_ignore = {&lt;br /&gt;
		message = nil,&lt;br /&gt;
		anchor = &#039;ignore_issn&#039;,&lt;br /&gt;
		category = &#039;CS1 maint: ignored ISSN errors&#039;,&lt;br /&gt;
		hidden = true,&lt;br /&gt;
		},&lt;br /&gt;
	maint_jfm_format = {&lt;br /&gt;
		message = nil,&lt;br /&gt;
		anchor = &#039;jfm_format&#039;,&lt;br /&gt;
		category = &#039;CS1 maint: JFM format&#039;,&lt;br /&gt;
		hidden = true,&lt;br /&gt;
		},&lt;br /&gt;
	maint_location = {&lt;br /&gt;
		message = nil,&lt;br /&gt;
		anchor = &#039;location&#039;,&lt;br /&gt;
		category = &#039;CS1 maint: location&#039;,&lt;br /&gt;
		hidden = true,&lt;br /&gt;
	},&lt;br /&gt;
	maint_mr_format = {&lt;br /&gt;
		message = nil,&lt;br /&gt;
		anchor = &#039;mr_format&#039;,&lt;br /&gt;
		category = &#039;CS1 maint: MR format&#039;,&lt;br /&gt;
		hidden = true,&lt;br /&gt;
	},&lt;br /&gt;
	maint_mult_names = {&lt;br /&gt;
		message = nil,&lt;br /&gt;
		anchor = &#039;mult_names&#039;,&lt;br /&gt;
		category = &#039;CS1 maint: multiple names: $1&#039;,								-- $1 is &#039;&amp;lt;name&amp;gt;s list&#039;; gets value from special_case_translation table&lt;br /&gt;
		hidden = true,&lt;br /&gt;
		},&lt;br /&gt;
	maint_numeric_names = {&lt;br /&gt;
		message = nil,&lt;br /&gt;
		anchor = &#039;numeric_names&#039;,&lt;br /&gt;
		category = &#039;CS1 maint: numeric names: $1&#039;,								-- $1 is &#039;&amp;lt;name&amp;gt;s list&#039;; gets value from special_case_translation table&lt;br /&gt;
		hidden = true,&lt;br /&gt;
		},&lt;br /&gt;
	maint_others = {&lt;br /&gt;
		message = nil,&lt;br /&gt;
		anchor = &#039;others&#039;,&lt;br /&gt;
		category = &#039;CS1 maint: others&#039;,&lt;br /&gt;
		hidden = true,&lt;br /&gt;
		},&lt;br /&gt;
	maint_others_avm = {&lt;br /&gt;
		message = nil,&lt;br /&gt;
		anchor = &#039;others_avm&#039;,&lt;br /&gt;
		category = &#039;CS1 maint: others in cite AV media (notes)&#039;,&lt;br /&gt;
		hidden = true,&lt;br /&gt;
	},&lt;br /&gt;
	maint_pmc_embargo = {&lt;br /&gt;
		message = nil,&lt;br /&gt;
		anchor = &#039;embargo&#039;,&lt;br /&gt;
		category = &#039;CS1 maint: PMC embargo expired&#039;,&lt;br /&gt;
		hidden = true,&lt;br /&gt;
		},&lt;br /&gt;
	maint_pmc_format = {&lt;br /&gt;
		message = nil,&lt;br /&gt;
		anchor = &#039;pmc_format&#039;,&lt;br /&gt;
		category = &#039;CS1 maint: PMC format&#039;,&lt;br /&gt;
		hidden = true,&lt;br /&gt;
		},&lt;br /&gt;
	maint_postscript = {&lt;br /&gt;
		message = nil,&lt;br /&gt;
		anchor = &#039;postscript&#039;,&lt;br /&gt;
		category = &#039;CS1 maint: postscript&#039;,&lt;br /&gt;
		hidden = true,&lt;br /&gt;
	},&lt;br /&gt;
	maint_ref_duplicates_default = {&lt;br /&gt;
		message = nil,&lt;br /&gt;
		anchor = &#039;ref_default&#039;,&lt;br /&gt;
		category = &#039;CS1 maint: ref duplicates default&#039;,&lt;br /&gt;
		hidden = true,&lt;br /&gt;
	},&lt;br /&gt;
	maint_unfit = {&lt;br /&gt;
		message = nil,&lt;br /&gt;
		anchor = &#039;unfit&#039;,&lt;br /&gt;
		category = &#039;CS1 maint: unfit URL&#039;,&lt;br /&gt;
		hidden = true,&lt;br /&gt;
		},&lt;br /&gt;
	maint_unknown_lang = {&lt;br /&gt;
		message = nil,&lt;br /&gt;
		anchor = &#039;unknown_lang&#039;,&lt;br /&gt;
		category = &#039;CS1 maint: unrecognized language&#039;,&lt;br /&gt;
		hidden = true,&lt;br /&gt;
		},&lt;br /&gt;
	maint_untitled = {&lt;br /&gt;
		message = nil,&lt;br /&gt;
		anchor = &#039;untitled&#039;,&lt;br /&gt;
		category = &#039;CS1 maint: untitled periodical&#039;,&lt;br /&gt;
		hidden = true,&lt;br /&gt;
		},&lt;br /&gt;
	maint_url_status = {&lt;br /&gt;
		message = nil,&lt;br /&gt;
		anchor = &#039;url_status&#039;,&lt;br /&gt;
		category = &#039;CS1 maint: url-status&#039;,&lt;br /&gt;
		hidden = true,&lt;br /&gt;
		},&lt;br /&gt;
	maint_zbl = {&lt;br /&gt;
		message = nil,&lt;br /&gt;
		anchor = &#039;zbl&#039;,&lt;br /&gt;
		category = &#039;CS1 maint: Zbl&#039;,&lt;br /&gt;
		hidden = true,&lt;br /&gt;
		},&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; I D _ H A N D L E R S &amp;gt;--------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
The following contains a list of values for various defined identifiers.  For each&lt;br /&gt;
identifier we specify a variety of information necessary to properly render the&lt;br /&gt;
identifier in the citation.&lt;br /&gt;
&lt;br /&gt;
	parameters: a list of parameter aliases for this identifier; first in the list is the canonical form&lt;br /&gt;
	link: Wikipedia article name&lt;br /&gt;
	redirect: a local redirect to a local Wikipedia article name;  at en.wiki, &#039;ISBN (identifier)&#039; is a redirect to &#039;International Standard Book Number&#039;&lt;br /&gt;
	q: Wikidata q number for the identifier&lt;br /&gt;
	label: the label preceeding the identifier; label is linked to a Wikipedia article (in this order):&lt;br /&gt;
		redirect from id_handlers[&#039;&amp;lt;id&amp;gt;&#039;].redirect when use_identifier_redirects is true&lt;br /&gt;
		Wikidata-supplied article name for the local wiki from id_handlers[&#039;&amp;lt;id&amp;gt;&#039;].q&lt;br /&gt;
		local article name from id_handlers[&#039;&amp;lt;id&amp;gt;&#039;].link&lt;br /&gt;
	prefix: the first part of a URL that will be concatenated with a second part which usually contains the identifier&lt;br /&gt;
	suffix: optional third part to be added after the identifier&lt;br /&gt;
	encode: true if URI should be percent-encoded; otherwise false&lt;br /&gt;
	COinS: identifier link or keyword for use in COinS:&lt;br /&gt;
		for identifiers registered at info-uri.info use: info:.... where &#039;...&#039; is the appropriate identifier label &lt;br /&gt;
		for identifiers that have COinS keywords, use the keyword: rft.isbn, rft.issn, rft.eissn&lt;br /&gt;
		for |asin= and |ol=, which require assembly, use the keyword: url&lt;br /&gt;
		for others make a URL using the value in prefix/suffix and #label, use the keyword: pre (not checked; any text other than &#039;info&#039;, &#039;rft&#039;, or &#039;url&#039; works here)&lt;br /&gt;
		set to nil to leave the identifier out of the COinS&lt;br /&gt;
	separator: character or text between label and the identifier in the rendered citation&lt;br /&gt;
	id_limit: for those identifiers with established limits, this property holds the upper limit&lt;br /&gt;
	access: use this parameter to set the access level for all instances of this identifier.&lt;br /&gt;
		the value must be a valid access level for an identifier (see [&#039;id-access&#039;] in this file).&lt;br /&gt;
	custom_access: to enable custom access level for an identifier, set this parameter&lt;br /&gt;
		to the parameter that should control it (normally &#039;id-access&#039;)&lt;br /&gt;
		&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local id_handlers = {&lt;br /&gt;
	[&#039;ARXIV&#039;] = {&lt;br /&gt;
		parameters = {&#039;arxiv&#039;, &#039;eprint&#039;},&lt;br /&gt;
		link = &#039;arXiv&#039;,&lt;br /&gt;
		redirect = &#039;arXiv (identifier)&#039;,&lt;br /&gt;
		q = &#039;Q118398&#039;,&lt;br /&gt;
		label = &#039;arXiv&#039;,&lt;br /&gt;
		prefix = &#039;//arxiv.org/abs/&#039;, 											-- protocol-relative tested 2013-09-04&lt;br /&gt;
		encode = false,&lt;br /&gt;
		COinS = &#039;info:arxiv&#039;,&lt;br /&gt;
		separator = &#039;:&#039;,&lt;br /&gt;
		access = &#039;free&#039;,														-- free to read&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;ASIN&#039;] = {&lt;br /&gt;
		parameters = { &#039;asin&#039;, &#039;ASIN&#039; },&lt;br /&gt;
		link = &#039;Amazon Standard Identification Number&#039;,&lt;br /&gt;
		redirect = &#039;ASIN (identifier)&#039;,&lt;br /&gt;
		q = &#039;Q1753278&#039;,&lt;br /&gt;
		label = &#039;ASIN&#039;,&lt;br /&gt;
		prefix = &#039;//www.amazon.&#039;,&lt;br /&gt;
		COinS = &#039;url&#039;,&lt;br /&gt;
		separator = &#039;&amp;amp;nbsp;&#039;,&lt;br /&gt;
		encode = false;&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;BIBCODE&#039;] = {&lt;br /&gt;
		parameters = {&#039;bibcode&#039;},&lt;br /&gt;
		link = &#039;Bibcode&#039;,&lt;br /&gt;
		redirect = &#039;Bibcode (identifier)&#039;,&lt;br /&gt;
		q = &#039;Q25754&#039;,&lt;br /&gt;
		label = &#039;Bibcode&#039;,&lt;br /&gt;
		prefix = &#039;https://ui.adsabs.harvard.edu/abs/&#039;,&lt;br /&gt;
		encode = false,&lt;br /&gt;
		COinS = &#039;info:bibcode&#039;,&lt;br /&gt;
		separator = &#039;:&#039;,&lt;br /&gt;
		custom_access = &#039;bibcode-access&#039;,&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;BIORXIV&#039;] = {&lt;br /&gt;
		parameters = {&#039;biorxiv&#039;},&lt;br /&gt;
		link = &#039;bioRxiv&#039;,&lt;br /&gt;
		redirect = &#039;bioRxiv (identifier)&#039;,&lt;br /&gt;
		q = &#039;Q19835482&#039;,&lt;br /&gt;
		label = &#039;bioRxiv&#039;,&lt;br /&gt;
		prefix = &#039;//doi.org/&#039;,&lt;br /&gt;
		COinS = &#039;pre&#039;,															-- use prefix value&lt;br /&gt;
		access = &#039;free&#039;,														-- free to read&lt;br /&gt;
		encode = true,&lt;br /&gt;
		separator = &#039;&amp;amp;nbsp;&#039;,&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;CITESEERX&#039;] = {&lt;br /&gt;
		parameters = {&#039;citeseerx&#039;},&lt;br /&gt;
		link = &#039;CiteSeerX&#039;,&lt;br /&gt;
		redirect = &#039;CiteSeerX (identifier)&#039;,&lt;br /&gt;
		q = &#039;Q2715061&#039;,&lt;br /&gt;
		label = &#039;CiteSeerX&#039;,&lt;br /&gt;
		prefix = &#039;//citeseerx.ist.psu.edu/viewdoc/summary?doi=&#039;,&lt;br /&gt;
		COinS =  &#039;pre&#039;,															-- use prefix value&lt;br /&gt;
		access = &#039;free&#039;,														-- free to read&lt;br /&gt;
		encode = true,&lt;br /&gt;
		separator = &#039;&amp;amp;nbsp;&#039;,&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;DOI&#039;] = {																	-- Used by InternetArchiveBot&lt;br /&gt;
		parameters = { &#039;doi&#039;, &#039;DOI&#039;},&lt;br /&gt;
		link = &#039;Digital object identifier&#039;,&lt;br /&gt;
		redirect = &#039;doi (identifier)&#039;,&lt;br /&gt;
		q = &#039;Q25670&#039;,&lt;br /&gt;
		label = &#039;doi&#039;,&lt;br /&gt;
		prefix = &#039;//doi.org/&#039;,&lt;br /&gt;
		COinS = &#039;info:doi&#039;,&lt;br /&gt;
		separator = &#039;:&#039;,&lt;br /&gt;
		encode = true,&lt;br /&gt;
		custom_access = &#039;doi-access&#039;,&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;EISSN&#039;] = {&lt;br /&gt;
		parameters = {&#039;eissn&#039;, &#039;EISSN&#039;},&lt;br /&gt;
		link = &#039;International Standard Serial Number#Electronic ISSN&#039;,&lt;br /&gt;
		redirect = &#039;eISSN (identifier)&#039;,&lt;br /&gt;
		q = &#039;Q46339674&#039;,&lt;br /&gt;
		label = &#039;eISSN&#039;,&lt;br /&gt;
		prefix = &#039;//www.worldcat.org/issn/&#039;,&lt;br /&gt;
		COinS = &#039;rft.eissn&#039;,&lt;br /&gt;
		encode = false,&lt;br /&gt;
		separator = &#039;&amp;amp;nbsp;&#039;,&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;HDL&#039;] = {&lt;br /&gt;
		parameters = { &#039;hdl&#039;, &#039;HDL&#039; },&lt;br /&gt;
		link = &#039;Handle System&#039;,&lt;br /&gt;
		redirect = &#039;hdl (identifier)&#039;,&lt;br /&gt;
		q = &#039;Q3126718&#039;,&lt;br /&gt;
		label = &#039;hdl&#039;,&lt;br /&gt;
		prefix = &#039;//hdl.handle.net/&#039;,&lt;br /&gt;
		COinS = &#039;info:hdl&#039;,&lt;br /&gt;
		separator = &#039;:&#039;,&lt;br /&gt;
		encode = true,&lt;br /&gt;
		custom_access = &#039;hdl-access&#039;,&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;ISBN&#039;] = {																-- Used by InternetArchiveBot&lt;br /&gt;
		parameters = {&#039;isbn&#039;, &#039;ISBN&#039;},&lt;br /&gt;
		link = &#039;International Standard Book Number&#039;,&lt;br /&gt;
		redirect = &#039;ISBN (identifier)&#039;,&lt;br /&gt;
		q = &#039;Q33057&#039;,&lt;br /&gt;
		label = &#039;ISBN&#039;,&lt;br /&gt;
		prefix = &#039;Special:BookSources/&#039;,&lt;br /&gt;
		COinS = &#039;rft.isbn&#039;,&lt;br /&gt;
		separator = &#039;&amp;amp;nbsp;&#039;,&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;ISMN&#039;] = {&lt;br /&gt;
		parameters = {&#039;ismn&#039;, &#039;ISMN&#039;},&lt;br /&gt;
		link = &#039;International Standard Music Number&#039;,&lt;br /&gt;
		redirect = &#039;ISMN (identifier)&#039;,&lt;br /&gt;
		q = &#039;Q1666938&#039;,&lt;br /&gt;
		label = &#039;ISMN&#039;,&lt;br /&gt;
		prefix = &#039;&#039;,															-- not currently used;&lt;br /&gt;
		COinS = nil,															-- nil because we can&#039;t use pre or rft or info:&lt;br /&gt;
		separator = &#039;&amp;amp;nbsp;&#039;,&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;ISSN&#039;] = {&lt;br /&gt;
		parameters = {&#039;issn&#039;, &#039;ISSN&#039;},&lt;br /&gt;
		link = &#039;International Standard Serial Number&#039;,&lt;br /&gt;
		redirect = &#039;ISSN (identifier)&#039;,&lt;br /&gt;
		q = &#039;Q131276&#039;,&lt;br /&gt;
		label = &#039;ISSN&#039;,&lt;br /&gt;
		prefix = &#039;//www.worldcat.org/issn/&#039;,&lt;br /&gt;
		COinS = &#039;rft.issn&#039;,&lt;br /&gt;
		encode = false,&lt;br /&gt;
		separator = &#039;&amp;amp;nbsp;&#039;,&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;JFM&#039;] = {&lt;br /&gt;
		parameters = {&#039;jfm&#039;, &#039;JFM&#039;},&lt;br /&gt;
		link = &#039;Jahrbuch über die Fortschritte der Mathematik&#039;,&lt;br /&gt;
		redirect = &#039;JFM (identifier)&#039;,&lt;br /&gt;
		q = &#039;&#039;,&lt;br /&gt;
		label = &#039;JFM&#039;,&lt;br /&gt;
		prefix = &#039;//zbmath.org/?format=complete&amp;amp;q=an:&#039;,&lt;br /&gt;
		COinS = &#039;pre&#039;,															-- use prefix value&lt;br /&gt;
		encode = true,&lt;br /&gt;
		separator = &#039;&amp;amp;nbsp;&#039;,&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;JSTOR&#039;] = {&lt;br /&gt;
		parameters = {&#039;jstor&#039;, &#039;JSTOR&#039;},&lt;br /&gt;
		link = &#039;JSTOR&#039;,&lt;br /&gt;
		redirect = &#039;JSTOR (identifier)&#039;,&lt;br /&gt;
		q = &#039;Q1420342&#039;,&lt;br /&gt;
		label = &#039;JSTOR&#039;,&lt;br /&gt;
		prefix = &#039;//www.jstor.org/stable/&#039;, 									-- protocol-relative tested 2013-09-04&lt;br /&gt;
		COinS = &#039;pre&#039;,															-- use prefix value&lt;br /&gt;
		encode = false,&lt;br /&gt;
		separator = &#039;&amp;amp;nbsp;&#039;,&lt;br /&gt;
		custom_access = &#039;jstor-access&#039;,&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;LCCN&#039;] = {&lt;br /&gt;
		parameters = {&#039;lccn&#039;, &#039;LCCN&#039;},&lt;br /&gt;
		link = &#039;Library of Congress Control Number&#039;,&lt;br /&gt;
		redirect = &#039;LCCN (identifier)&#039;,&lt;br /&gt;
		q = &#039;Q620946&#039;,&lt;br /&gt;
		label = &#039;LCCN&#039;,&lt;br /&gt;
		prefix = &#039;//lccn.loc.gov/&#039;, 											-- protocol-relative tested 2015-12-28&lt;br /&gt;
		COinS = &#039;info:lccn&#039;,&lt;br /&gt;
		encode = false,&lt;br /&gt;
		separator = &#039;&amp;amp;nbsp;&#039;,&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;MR&#039;] = {&lt;br /&gt;
		parameters = {&#039;mr&#039;, &#039;MR&#039;},&lt;br /&gt;
		link = &#039;Mathematical Reviews&#039;,&lt;br /&gt;
		redirect = &#039;MR (identifier)&#039;,&lt;br /&gt;
		q = &#039;Q211172&#039;,&lt;br /&gt;
		label = &#039;MR&#039;,&lt;br /&gt;
		prefix = &#039;//www.ams.org/mathscinet-getitem?mr=&#039;, 						-- protocol-relative tested 2013-09-04&lt;br /&gt;
		COinS = &#039;pre&#039;,															-- use prefix value&lt;br /&gt;
		encode = true,&lt;br /&gt;
		separator = &#039;&amp;amp;nbsp;&#039;,&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;OCLC&#039;] = {&lt;br /&gt;
		parameters = {&#039;oclc&#039;, &#039;OCLC&#039;},&lt;br /&gt;
		link = &#039;OCLC&#039;,&lt;br /&gt;
		redirect = &#039;OCLC (identifier)&#039;,&lt;br /&gt;
		q = &#039;Q190593&#039;,&lt;br /&gt;
		label = &#039;OCLC&#039;,&lt;br /&gt;
		prefix = &#039;//www.worldcat.org/oclc/&#039;,&lt;br /&gt;
		COinS = &#039;info:oclcnum&#039;,&lt;br /&gt;
		encode = true,&lt;br /&gt;
		separator = &#039;&amp;amp;nbsp;&#039;,&lt;br /&gt;
		id_limit = 9999999999,													-- 10-digits&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;OL&#039;] = {&lt;br /&gt;
		parameters = { &#039;ol&#039;, &#039;OL&#039; },&lt;br /&gt;
		link = &#039;Open Library&#039;,&lt;br /&gt;
		redirect = &#039;OL (identifier)&#039;,&lt;br /&gt;
		q = &#039;Q1201876&#039;,&lt;br /&gt;
		label = &#039;OL&#039;,&lt;br /&gt;
		prefix = &#039;//openlibrary.org/&#039;,&lt;br /&gt;
		COinS = &#039;url&#039;,&lt;br /&gt;
		separator = &#039;&amp;amp;nbsp;&#039;,&lt;br /&gt;
		encode = true,&lt;br /&gt;
		custom_access = &#039;ol-access&#039;,&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;OSTI&#039;] = {&lt;br /&gt;
		parameters = {&#039;osti&#039;, &#039;OSTI&#039;},&lt;br /&gt;
		link = &#039;Office of Scientific and Technical Information&#039;,&lt;br /&gt;
		redirect = &#039;OSTI (identifier)&#039;,&lt;br /&gt;
		q = &#039;Q2015776&#039;,&lt;br /&gt;
		label = &#039;OSTI&#039;,&lt;br /&gt;
		prefix = &#039;//www.osti.gov/biblio/&#039;,										-- protocol-relative tested 2018-09-12&lt;br /&gt;
		COinS = &#039;pre&#039;,															-- use prefix value&lt;br /&gt;
		encode = true,&lt;br /&gt;
		separator = &#039;&amp;amp;nbsp;&#039;,&lt;br /&gt;
		id_limit = 23010000,&lt;br /&gt;
		custom_access = &#039;osti-access&#039;,&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;PMC&#039;] = {&lt;br /&gt;
		parameters = {&#039;pmc&#039;, &#039;PMC&#039;},&lt;br /&gt;
		link = &#039;PubMed Central&#039;,&lt;br /&gt;
		redirect = &#039;PMC (identifier)&#039;,&lt;br /&gt;
		q = &#039;Q229883&#039;,&lt;br /&gt;
		label = &#039;PMC&#039;,&lt;br /&gt;
		prefix = &#039;//www.ncbi.nlm.nih.gov/pmc/articles/PMC&#039;,&lt;br /&gt;
		suffix = &#039;&#039;,&lt;br /&gt;
		COinS = &#039;pre&#039;,															-- use prefix value&lt;br /&gt;
		encode = true,&lt;br /&gt;
		separator = &#039;&amp;amp;nbsp;&#039;,&lt;br /&gt;
		id_limit = 9500000,&lt;br /&gt;
		access = &#039;free&#039;,														-- free to read&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;PMID&#039;] = {&lt;br /&gt;
		parameters = {&#039;pmid&#039;, &#039;PMID&#039;},&lt;br /&gt;
		link = &#039;PubMed Identifier&#039;,&lt;br /&gt;
		redirect = &#039;PMID (identifier)&#039;,&lt;br /&gt;
		q = &#039;Q2082879&#039;,&lt;br /&gt;
		label = &#039;PMID&#039;,&lt;br /&gt;
		prefix = &#039;//pubmed.ncbi.nlm.nih.gov/&#039;,&lt;br /&gt;
		COinS = &#039;info:pmid&#039;,&lt;br /&gt;
		encode = false,&lt;br /&gt;
		separator = &#039;&amp;amp;nbsp;&#039;,&lt;br /&gt;
		id_limit = 36400000,&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;RFC&#039;] = {&lt;br /&gt;
		parameters = {&#039;rfc&#039;, &#039;RFC&#039;},&lt;br /&gt;
		link = &#039;Request for Comments&#039;,&lt;br /&gt;
		redirect = &#039;RFC (identifier)&#039;,&lt;br /&gt;
		q = &#039;Q212971&#039;,&lt;br /&gt;
		label = &#039;RFC&#039;,&lt;br /&gt;
		prefix = &#039;//tools.ietf.org/html/rfc&#039;,&lt;br /&gt;
		COinS = &#039;pre&#039;,															-- use prefix value&lt;br /&gt;
		encode = false,&lt;br /&gt;
		separator = &#039;&amp;amp;nbsp;&#039;,&lt;br /&gt;
		id_limit = 9300,&lt;br /&gt;
		access = &#039;free&#039;,														-- free to read&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;SBN&#039;] = {&lt;br /&gt;
		parameters = {&#039;sbn&#039;, &#039;SBN&#039;},&lt;br /&gt;
		link = &#039;Standard Book Number&#039;,											-- redirect to International_Standard_Book_Number#History&lt;br /&gt;
		redirect = &#039;SBN (identifier)&#039;,&lt;br /&gt;
		label = &#039;SBN&#039;,&lt;br /&gt;
		prefix = &#039;Special:BookSources/0-&#039;,										-- prefix has leading zero necessary to make 9-digit sbn a 10-digit isbn&lt;br /&gt;
		COinS = nil,															-- nil because we can&#039;t use pre or rft or info:&lt;br /&gt;
		separator = &#039;&amp;amp;nbsp;&#039;,&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;SSRN&#039;] = {&lt;br /&gt;
		parameters = {&#039;ssrn&#039;, &#039;SSRN&#039;},&lt;br /&gt;
		link = &#039;Social Science Research Network&#039;,&lt;br /&gt;
		redirect = &#039;SSRN (identifier)&#039;,&lt;br /&gt;
		q = &#039;Q7550801&#039;,&lt;br /&gt;
		label = &#039;SSRN&#039;,&lt;br /&gt;
		prefix = &#039;//ssrn.com/abstract=&#039;, 										-- protocol-relative tested 2013-09-04&lt;br /&gt;
		COinS = &#039;pre&#039;,															-- use prefix value&lt;br /&gt;
		encode = true,&lt;br /&gt;
		separator = &#039;&amp;amp;nbsp;&#039;,&lt;br /&gt;
		id_limit = 4200000,&lt;br /&gt;
		custom_access = &#039;ssrn-access&#039;,&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;S2CID&#039;] = {&lt;br /&gt;
		parameters = {&#039;s2cid&#039;, &#039;S2CID&#039;},&lt;br /&gt;
		link = &#039;Semantic Scholar&#039;,&lt;br /&gt;
		redirect = &#039;S2CID (identifier)&#039;,&lt;br /&gt;
		q = &#039;Q22908627&#039;,&lt;br /&gt;
		label = &#039;S2CID&#039;,&lt;br /&gt;
		prefix = &#039;https://api.semanticscholar.org/CorpusID:&#039;,&lt;br /&gt;
		COinS = &#039;pre&#039;,															-- use prefix value&lt;br /&gt;
		encode = false,&lt;br /&gt;
		separator = &#039;&amp;amp;nbsp;&#039;,&lt;br /&gt;
		id_limit = 254000000,&lt;br /&gt;
		custom_access = &#039;s2cid-access&#039;,&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;USENETID&#039;] = {&lt;br /&gt;
		parameters = {&#039;message-id&#039;},&lt;br /&gt;
		link = &#039;Usenet&#039;,&lt;br /&gt;
		redirect = &#039;Usenet (identifier)&#039;,&lt;br /&gt;
		q = &#039;Q193162&#039;,&lt;br /&gt;
		label = &#039;Usenet:&#039;,&lt;br /&gt;
		prefix = &#039;news:&#039;,&lt;br /&gt;
		encode = false,&lt;br /&gt;
		COinS = &#039;pre&#039;,															-- use prefix value&lt;br /&gt;
		separator = &#039;&amp;amp;nbsp;&#039;,&lt;br /&gt;
		},&lt;br /&gt;
	[&#039;ZBL&#039;] = {&lt;br /&gt;
		parameters = {&#039;zbl&#039;, &#039;ZBL&#039; },&lt;br /&gt;
		link = &#039;Zentralblatt MATH&#039;,&lt;br /&gt;
		redirect = &#039;Zbl (identifier)&#039;,&lt;br /&gt;
		q = &#039;Q190269&#039;,&lt;br /&gt;
		label = &#039;Zbl&#039;,&lt;br /&gt;
		prefix = &#039;//zbmath.org/?format=complete&amp;amp;q=an:&#039;,&lt;br /&gt;
		COinS = &#039;pre&#039;,															-- use prefix value&lt;br /&gt;
		encode = true,&lt;br /&gt;
		separator = &#039;&amp;amp;nbsp;&#039;,&lt;br /&gt;
		},&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; E X P O R T S &amp;gt;---------------------------------&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
return 	{&lt;br /&gt;
	use_identifier_redirects = true,											-- when true use redirect name for identifier label links; always true at en.wiki&lt;br /&gt;
	local_lang_cat_enable = false;												-- when true categorizes pages where |language=&amp;lt;local wiki&#039;s language&amp;gt;; always false at en.wiki&lt;br /&gt;
	date_name_auto_xlate_enable = false;										-- when true translates English month-names to the local-wiki&#039;s language month names; always false at en.wiki&lt;br /&gt;
	date_digit_auto_xlate_enable = false;										-- when true translates Western date digit to the local-wiki&#039;s language digits (date_names[&#039;local_digits&#039;]); always false at en.wiki&lt;br /&gt;
	&lt;br /&gt;
	global_df = get_date_format (),												-- tables and variables created when this module is loaded&lt;br /&gt;
	punct_skip = build_skip_table (punct_skip, punct_meta_params),&lt;br /&gt;
	url_skip = build_skip_table (url_skip, url_meta_params),&lt;br /&gt;
&lt;br /&gt;
	aliases = aliases,&lt;br /&gt;
	special_case_translation = special_case_translation,&lt;br /&gt;
	date_names = date_names,&lt;br /&gt;
	err_msg_supl = err_msg_supl,&lt;br /&gt;
	error_conditions = error_conditions,&lt;br /&gt;
	editor_markup_patterns = editor_markup_patterns,&lt;br /&gt;
	et_al_patterns = et_al_patterns,&lt;br /&gt;
	id_handlers = id_handlers,&lt;br /&gt;
	keywords_lists = keywords_lists,&lt;br /&gt;
	keywords_xlate = keywords_xlate,&lt;br /&gt;
	stripmarkers=stripmarkers,&lt;br /&gt;
	invisible_chars = invisible_chars,&lt;br /&gt;
	invisible_defs = invisible_defs,&lt;br /&gt;
	indic_script = indic_script,&lt;br /&gt;
	emoji = emoji,&lt;br /&gt;
	maint_cats = maint_cats,&lt;br /&gt;
	messages = messages,&lt;br /&gt;
	presentation = presentation,&lt;br /&gt;
	prop_cats = prop_cats,&lt;br /&gt;
	script_lang_codes = script_lang_codes,&lt;br /&gt;
	lang_code_remap = lang_code_remap,&lt;br /&gt;
	lang_name_remap = lang_name_remap,&lt;br /&gt;
	this_wiki_code = this_wiki_code,&lt;br /&gt;
	title_types = title_types,&lt;br /&gt;
	uncategorized_namespaces = uncategorized_namespaces,&lt;br /&gt;
	uncategorized_subpages = uncategorized_subpages,&lt;br /&gt;
	templates_using_volume = templates_using_volume,&lt;br /&gt;
	templates_using_issue = templates_using_issue,&lt;br /&gt;
	templates_not_using_page = templates_not_using_page,&lt;br /&gt;
	vol_iss_pg_patterns = vol_iss_pg_patterns,&lt;br /&gt;
	&lt;br /&gt;
	inter_wiki_map = inter_wiki_map,&lt;br /&gt;
	mw_languages_by_tag_t = mw_languages_by_tag_t,&lt;br /&gt;
	mw_languages_by_name_t = mw_languages_by_name_t,&lt;br /&gt;
	citation_class_map_t = citation_class_map_t,&lt;br /&gt;
&lt;br /&gt;
	citation_issue_t = citation_issue_t,&lt;br /&gt;
	citation_no_volume_t = citation_no_volume_t,&lt;br /&gt;
	}&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Modul:Citation/CS1/COinS&amp;diff=1519</id>
		<title>Modul:Citation/CS1/COinS</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Modul:Citation/CS1/COinS&amp;diff=1519"/>
		<updated>2022-08-12T16:59:11Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--[[--------------------------&amp;lt; F O R W A R D   D E C L A R A T I O N S &amp;gt;--------------------------------------&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local has_accept_as_written, is_set, in_array, remove_wiki_link, strip_apostrophe_markup;	-- functions in Module:Citation/CS1/Utilities&lt;br /&gt;
&lt;br /&gt;
local cfg;																		-- table of configuration tables that are defined in Module:Citation/CS1/Configuration&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; M A K E _ C O I N S _ T I T L E &amp;gt;----------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Makes a title for COinS from Title and / or ScriptTitle (or any other name-script pairs)&lt;br /&gt;
&lt;br /&gt;
Apostrophe markup (bold, italics) is stripped from each value so that the COinS metadata isn&#039;t corrupted with strings&lt;br /&gt;
of %27%27...&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function make_coins_title (title, script)&lt;br /&gt;
	title = has_accept_as_written (title);&lt;br /&gt;
	if is_set (title) then&lt;br /&gt;
		title = strip_apostrophe_markup (title);								-- strip any apostrophe markup&lt;br /&gt;
	else&lt;br /&gt;
		title = &#039;&#039;;																-- if not set, make sure title is an empty string&lt;br /&gt;
	end&lt;br /&gt;
	if is_set (script) then&lt;br /&gt;
		script = script:gsub (&#039;^%l%l%s*:%s*&#039;, &#039;&#039;);								-- remove language prefix if present (script value may now be empty string)&lt;br /&gt;
		script = strip_apostrophe_markup (script);								-- strip any apostrophe markup&lt;br /&gt;
	else&lt;br /&gt;
		script = &#039;&#039;;															-- if not set, make sure script is an empty string&lt;br /&gt;
	end&lt;br /&gt;
	if is_set (title) and is_set (script) then&lt;br /&gt;
		script = &#039; &#039; .. script;													-- add a space before we concatenate&lt;br /&gt;
	end&lt;br /&gt;
	return title .. script;														-- return the concatenation&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; E S C A P E _ L U A _ M A G I C _ C H A R S &amp;gt;----------------------------------&lt;br /&gt;
&lt;br /&gt;
Returns a string where all of Lua&#039;s magic characters have been escaped.  This is important because functions like&lt;br /&gt;
string.gsub() treat their pattern and replace strings as patterns, not literal strings.&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function escape_lua_magic_chars (argument)&lt;br /&gt;
	argument = argument:gsub(&amp;quot;%%&amp;quot;, &amp;quot;%%%%&amp;quot;);										-- replace % with %%&lt;br /&gt;
	argument = argument:gsub(&amp;quot;([%^%$%(%)%.%[%]%*%+%-%?])&amp;quot;, &amp;quot;%%%1&amp;quot;);				-- replace all other Lua magic pattern characters&lt;br /&gt;
	return argument;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; G E T _ C O I N S _ P A G E S &amp;gt;------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Extract page numbers from external wikilinks in any of the |page=, |pages=, or |at= parameters for use in COinS.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function get_coins_pages (pages)&lt;br /&gt;
	local pattern;&lt;br /&gt;
	if not is_set (pages) then return pages; end								-- if no page numbers then we&#039;re done&lt;br /&gt;
	&lt;br /&gt;
	while true do&lt;br /&gt;
		pattern = pages:match(&amp;quot;%[(%w*:?//[^ ]+%s+)[%w%d].*%]&amp;quot;);					-- pattern is the opening bracket, the URL and following space(s): &amp;quot;[url &amp;quot;&lt;br /&gt;
		if nil == pattern then break; end										-- no more URLs&lt;br /&gt;
		pattern = escape_lua_magic_chars (pattern);								-- pattern is not a literal string; escape Lua&#039;s magic pattern characters&lt;br /&gt;
		pages = pages:gsub(pattern, &amp;quot;&amp;quot;);										-- remove as many instances of pattern as possible&lt;br /&gt;
	end&lt;br /&gt;
	pages = pages:gsub(&amp;quot;[%[%]]&amp;quot;, &amp;quot;&amp;quot;);											-- remove the brackets&lt;br /&gt;
	pages = pages:gsub(&amp;quot;–&amp;quot;, &amp;quot;-&amp;quot; );												-- replace endashes with hyphens&lt;br /&gt;
	pages = pages:gsub(&amp;quot;&amp;amp;%w+;&amp;quot;, &amp;quot;-&amp;quot; );											-- and replace HTML entities (&amp;amp;ndash; etc.) with hyphens; do we need to replace numerical entities like &amp;amp;#32; and the like?&lt;br /&gt;
	return pages;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[=[-------------------------&amp;lt; C O I N S _ R E P L A C E _ M A T H _ S T R I P M A R K E R &amp;gt;------------------&lt;br /&gt;
&lt;br /&gt;
There are three options for math markup rendering that depend on the editor&#039;s math preference settings.  These&lt;br /&gt;
settings are at [[Special:Preferences#mw-prefsection-rendering]] and are&lt;br /&gt;
	PNG images&lt;br /&gt;
	TeX source&lt;br /&gt;
	MathML with SVG or PNG fallback&lt;br /&gt;
&lt;br /&gt;
All three are heavy with HTML and CSS which doesn&#039;t belong in the metadata.&lt;br /&gt;
&lt;br /&gt;
Without this function, the metadata saved in the raw wikitext contained the rendering determined by the settings&lt;br /&gt;
of the last editor to save the page.&lt;br /&gt;
&lt;br /&gt;
This function gets the rendered form of an equation according to the editor&#039;s preference before the page is saved.  It&lt;br /&gt;
then searches the rendering for the text equivalent of the rendered equation and replaces the rendering with that so&lt;br /&gt;
that the page is saved without extraneous HTML/CSS markup and with a reasonably readable text form of the equation.&lt;br /&gt;
&lt;br /&gt;
When a replacement is made, this function returns true and the value with replacement; otherwise false and the initial&lt;br /&gt;
value.  To replace multipe equations it is necessary to call this function from within a loop.&lt;br /&gt;
&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local function coins_replace_math_stripmarker (value)&lt;br /&gt;
	local stripmarker = cfg.stripmarkers[&#039;math&#039;];&lt;br /&gt;
	local rendering = value:match (stripmarker);								-- is there a math stripmarker&lt;br /&gt;
&lt;br /&gt;
	if not rendering then														-- when value doesn&#039;t have a math stripmarker, abandon this test&lt;br /&gt;
		return false, value;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	rendering = mw.text.unstripNoWiki (rendering);								-- convert stripmarker into rendered value (or nil? &#039;&#039;? when math render error)&lt;br /&gt;
	&lt;br /&gt;
	if rendering:match (&#039;alt=&amp;quot;[^&amp;quot;]+&amp;quot;&#039;) then										-- if PNG math option&lt;br /&gt;
		rendering = rendering:match (&#039;alt=&amp;quot;([^&amp;quot;]+)&amp;quot;&#039;);							-- extract just the math text&lt;br /&gt;
	elseif rendering:match (&#039;$%s+.+%s+%$&#039;) then									-- if TeX math option; $ is legit character that is escapes as \$&lt;br /&gt;
		rendering = rendering:match (&#039;$%s+(.+)%s+%$&#039;)							-- extract just the math text&lt;br /&gt;
	elseif rendering:match (&#039;&amp;lt;annotation[^&amp;gt;]+&amp;gt;.+&amp;lt;/annotation&amp;gt;&#039;) then			-- if MathML math option&lt;br /&gt;
		rendering = rendering:match (&#039;&amp;lt;annotation[^&amp;gt;]+&amp;gt;(.+)&amp;lt;/annotation&amp;gt;&#039;)		-- extract just the math text&lt;br /&gt;
	else&lt;br /&gt;
		return false, value;													-- had math stripmarker but not one of the three defined forms&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return true, value:gsub (stripmarker, rendering, 1);&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; C O I N S _ C L E A N U P &amp;gt;----------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Cleanup parameter values for the metadata by removing or replacing invisible characters and certain HTML entities.&lt;br /&gt;
&lt;br /&gt;
2015-12-10: there is a bug in mw.text.unstripNoWiki ().  It replaces math stripmarkers with the appropriate content&lt;br /&gt;
when it shouldn&#039;t.  See https://phabricator.wikimedia.org/T121085 and Wikipedia_talk:Lua#stripmarkers_and_mw.text.unstripNoWiki.28.29&lt;br /&gt;
&lt;br /&gt;
TODO: move the replacement patterns and replacement values into a table in /Configuration similar to the invisible&lt;br /&gt;
characters table?&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function coins_cleanup (value)&lt;br /&gt;
	local replaced = true;														-- default state to get the do loop running&lt;br /&gt;
&lt;br /&gt;
	while replaced do															-- loop until all math stripmarkers replaced&lt;br /&gt;
		replaced, value = coins_replace_math_stripmarker (value);				-- replace math stripmarker with text representation of the equation&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	value = value:gsub (cfg.stripmarkers[&#039;math&#039;], &amp;quot;MATH RENDER ERROR&amp;quot;);			-- one or more couldn&#039;t be replaced; insert vague error message&lt;br /&gt;
	&lt;br /&gt;
	value = mw.text.unstripNoWiki (value);										-- replace nowiki stripmarkers with their content&lt;br /&gt;
	value = value:gsub (&#039;&amp;lt;span class=&amp;quot;nowrap&amp;quot; style=&amp;quot;padding%-left:0%.1em;&amp;quot;&amp;gt;&amp;amp;#39;(s?)&amp;lt;/span&amp;gt;&#039;, &amp;quot;&#039;%1&amp;quot;);	-- replace {{&#039;}} or {{&#039;s}} with simple apostrophe or apostrophe-s&lt;br /&gt;
	value = value:gsub (&#039;&amp;amp;nbsp;&#039;, &#039; &#039;);											-- replace &amp;amp;nbsp; entity with plain space&lt;br /&gt;
	value = value:gsub (&#039;\226\128\138&#039;, &#039; &#039;);									-- replace hair space with plain space&lt;br /&gt;
	if not mw.ustring.find (value, cfg.indic_script) then						-- don&#039;t remove zero-width joiner characters from indic script&lt;br /&gt;
		value = value:gsub (&#039;&amp;amp;zwj;&#039;, &#039;&#039;);										-- remove &amp;amp;zwj; entities&lt;br /&gt;
		value = mw.ustring.gsub (value, &#039;[\226\128\141\226\128\139\194\173]&#039;, &#039;&#039;);	-- remove zero-width joiner, zero-width space, soft hyphen&lt;br /&gt;
	end&lt;br /&gt;
	value = value:gsub (&#039;[\009\010\013 ]+&#039;, &#039; &#039;);								-- replace horizontal tab, line feed, carriage return with plain space&lt;br /&gt;
	return value;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; C O I N S &amp;gt;--------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
COinS metadata (see &amp;lt;http://ocoins.info/&amp;gt;) allows automated tools to parse the citation information.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function COinS(data, class)&lt;br /&gt;
	if &#039;table&#039; ~= type(data) or nil == next(data) then&lt;br /&gt;
		return &#039;&#039;;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	for k, v in pairs (data) do													-- spin through all of the metadata parameter values&lt;br /&gt;
		if &#039;ID_list&#039; ~= k and &#039;Authors&#039; ~= k then								-- except the ID_list and Author tables (author nowiki stripmarker done when Author table processed)&lt;br /&gt;
			data[k] = coins_cleanup (v);&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local ctx_ver = &amp;quot;Z39.88-2004&amp;quot;;&lt;br /&gt;
	&lt;br /&gt;
	-- treat table strictly as an array with only set values.&lt;br /&gt;
	local OCinSoutput = setmetatable( {}, {&lt;br /&gt;
		__newindex = function(self, key, value)&lt;br /&gt;
			if is_set(value) then&lt;br /&gt;
				rawset( self, #self+1, table.concat{ key, &#039;=&#039;, mw.uri.encode( remove_wiki_link( value ) ) } );&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	});&lt;br /&gt;
	&lt;br /&gt;
	if in_array (class, {&#039;arxiv&#039;, &#039;biorxiv&#039;, &#039;citeseerx&#039;, &#039;ssrn&#039;, &#039;journal&#039;, &#039;news&#039;, &#039;magazine&#039;}) or (in_array (class, {&#039;conference&#039;, &#039;interview&#039;, &#039;map&#039;, &#039;press release&#039;, &#039;web&#039;}) and is_set(data.Periodical)) or &lt;br /&gt;
		(&#039;citation&#039; == class and is_set(data.Periodical) and not is_set (data.Encyclopedia)) then&lt;br /&gt;
			OCinSoutput.rft_val_fmt = &amp;quot;info:ofi/fmt:kev:mtx:journal&amp;quot;;			-- journal metadata identifier&lt;br /&gt;
			if in_array (class, {&#039;arxiv&#039;, &#039;biorxiv&#039;, &#039;citeseerx&#039;, &#039;ssrn&#039;}) then	-- set genre according to the type of citation template we are rendering&lt;br /&gt;
				OCinSoutput[&amp;quot;rft.genre&amp;quot;] = &amp;quot;preprint&amp;quot;;							-- cite arxiv, cite biorxiv, cite citeseerx, cite ssrn&lt;br /&gt;
			elseif &#039;conference&#039; == class then&lt;br /&gt;
				OCinSoutput[&amp;quot;rft.genre&amp;quot;] = &amp;quot;conference&amp;quot;;						-- cite conference (when Periodical set)&lt;br /&gt;
			elseif &#039;web&#039; == class then&lt;br /&gt;
				OCinSoutput[&amp;quot;rft.genre&amp;quot;] = &amp;quot;unknown&amp;quot;;							-- cite web (when Periodical set)&lt;br /&gt;
			else&lt;br /&gt;
				OCinSoutput[&amp;quot;rft.genre&amp;quot;] = &amp;quot;article&amp;quot;;							-- journal and other &#039;periodical&#039; articles&lt;br /&gt;
			end&lt;br /&gt;
			OCinSoutput[&amp;quot;rft.jtitle&amp;quot;] = data.Periodical;						-- journal only&lt;br /&gt;
			OCinSoutput[&amp;quot;rft.atitle&amp;quot;] = data.Title;								-- &#039;periodical&#039; article titles&lt;br /&gt;
&lt;br /&gt;
																				-- these used only for periodicals&lt;br /&gt;
			OCinSoutput[&amp;quot;rft.ssn&amp;quot;] = data.Season;								-- keywords: winter, spring, summer, fall&lt;br /&gt;
			OCinSoutput[&amp;quot;rft.quarter&amp;quot;] = data.Quarter;							-- single digits 1-&amp;gt;first quarter, etc.&lt;br /&gt;
			OCinSoutput[&amp;quot;rft.chron&amp;quot;] = data.Chron;								-- free-form date components&lt;br /&gt;
			OCinSoutput[&amp;quot;rft.volume&amp;quot;] = data.Volume;							-- does not apply to books&lt;br /&gt;
			OCinSoutput[&amp;quot;rft.issue&amp;quot;] = data.Issue;&lt;br /&gt;
			OCinSoutput[&amp;quot;rft.pages&amp;quot;] = data.Pages;								-- also used in book metadata&lt;br /&gt;
&lt;br /&gt;
	elseif &#039;thesis&#039; ~= class then												-- all others except cite thesis are treated as &#039;book&#039; metadata; genre distinguishes&lt;br /&gt;
		OCinSoutput.rft_val_fmt = &amp;quot;info:ofi/fmt:kev:mtx:book&amp;quot;;					-- book metadata identifier&lt;br /&gt;
		if &#039;report&#039; == class or &#039;techreport&#039; == class then						-- cite report and cite techreport&lt;br /&gt;
			OCinSoutput[&amp;quot;rft.genre&amp;quot;] = &amp;quot;report&amp;quot;;&lt;br /&gt;
		elseif &#039;conference&#039; == class then										-- cite conference when Periodical not set&lt;br /&gt;
			OCinSoutput[&amp;quot;rft.genre&amp;quot;] = &amp;quot;conference&amp;quot;;&lt;br /&gt;
			OCinSoutput[&amp;quot;rft.atitle&amp;quot;] = data.Chapter;							-- conference paper as chapter in proceedings (book)&lt;br /&gt;
		elseif in_array (class, {&#039;book&#039;, &#039;citation&#039;, &#039;encyclopaedia&#039;, &#039;interview&#039;, &#039;map&#039;}) then&lt;br /&gt;
			if is_set (data.Chapter) then&lt;br /&gt;
				OCinSoutput[&amp;quot;rft.genre&amp;quot;] = &amp;quot;bookitem&amp;quot;;&lt;br /&gt;
				OCinSoutput[&amp;quot;rft.atitle&amp;quot;] = data.Chapter;						-- book chapter, encyclopedia article, interview in a book, or map title&lt;br /&gt;
			else&lt;br /&gt;
				if &#039;map&#039; == class or &#039;interview&#039; == class then&lt;br /&gt;
					OCinSoutput[&amp;quot;rft.genre&amp;quot;] = &#039;unknown&#039;;						-- standalone map or interview&lt;br /&gt;
				else&lt;br /&gt;
					OCinSoutput[&amp;quot;rft.genre&amp;quot;] = &#039;book&#039;;							-- book and encyclopedia&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		else	-- {&#039;audio-visual&#039;, &#039;AV-media-notes&#039;, &#039;DVD-notes&#039;, &#039;episode&#039;, &#039;interview&#039;, &#039;mailinglist&#039;, &#039;map&#039;, &#039;newsgroup&#039;, &#039;podcast&#039;, &#039;press release&#039;, &#039;serial&#039;, &#039;sign&#039;, &#039;speech&#039;, &#039;web&#039;}&lt;br /&gt;
			OCinSoutput[&amp;quot;rft.genre&amp;quot;] = &amp;quot;unknown&amp;quot;;&lt;br /&gt;
		end&lt;br /&gt;
		OCinSoutput[&amp;quot;rft.btitle&amp;quot;] = data.Title;									-- book only&lt;br /&gt;
		OCinSoutput[&amp;quot;rft.place&amp;quot;] = data.PublicationPlace;						-- book only&lt;br /&gt;
		OCinSoutput[&amp;quot;rft.series&amp;quot;] = data.Series;								-- book only&lt;br /&gt;
		OCinSoutput[&amp;quot;rft.pages&amp;quot;] = data.Pages;									-- book, journal&lt;br /&gt;
		OCinSoutput[&amp;quot;rft.edition&amp;quot;] = data.Edition;								-- book only&lt;br /&gt;
		OCinSoutput[&amp;quot;rft.pub&amp;quot;] = data.PublisherName;							-- book and dissertation&lt;br /&gt;
		&lt;br /&gt;
	else																		-- cite thesis&lt;br /&gt;
		OCinSoutput.rft_val_fmt = &amp;quot;info:ofi/fmt:kev:mtx:dissertation&amp;quot;;			-- dissertation metadata identifier&lt;br /&gt;
		OCinSoutput[&amp;quot;rft.title&amp;quot;] = data.Title;									-- dissertation (also patent but that is not yet supported)&lt;br /&gt;
		OCinSoutput[&amp;quot;rft.degree&amp;quot;] = data.Degree;								-- dissertation only&lt;br /&gt;
		OCinSoutput[&#039;rft.inst&#039;] = data.PublisherName;							-- book and dissertation&lt;br /&gt;
	end&lt;br /&gt;
	-- NB. Not currently supported are &amp;quot;info:ofi/fmt:kev:mtx:patent&amp;quot;, &amp;quot;info:ofi/fmt:kev:mtx:dc&amp;quot;, &amp;quot;info:ofi/fmt:kev:mtx:sch_svc&amp;quot;, &amp;quot;info:ofi/fmt:kev:mtx:ctx&amp;quot;&lt;br /&gt;
																				-- and now common parameters (as much as possible)&lt;br /&gt;
	OCinSoutput[&amp;quot;rft.date&amp;quot;] = data.Date;										-- book, journal, dissertation&lt;br /&gt;
&lt;br /&gt;
	for k, v in pairs( data.ID_list ) do										-- what to do about these? For now assume that they are common to all?&lt;br /&gt;
		if k == &#039;ISBN&#039; then v = v:gsub( &amp;quot;[^-0-9X]&amp;quot;, &amp;quot;&amp;quot; ); end&lt;br /&gt;
		local id = cfg.id_handlers[k].COinS;&lt;br /&gt;
		if string.sub( id or &amp;quot;&amp;quot;, 1, 4 ) == &#039;info&#039; then							-- for ids that are in the info:registry&lt;br /&gt;
			OCinSoutput[&amp;quot;rft_id&amp;quot;] = table.concat{ id, &amp;quot;/&amp;quot;, v };&lt;br /&gt;
		elseif string.sub (id or &amp;quot;&amp;quot;, 1, 3 ) == &#039;rft&#039; then						-- for isbn, issn, eissn, etc. that have defined COinS keywords&lt;br /&gt;
			OCinSoutput[ id ] = v;&lt;br /&gt;
		elseif &#039;url&#039; == id then													-- for urls that are assembled in ~/Identifiers; |asin= and |ol=&lt;br /&gt;
			OCinSoutput[&amp;quot;rft_id&amp;quot;] = table.concat ({data.ID_list[k], &amp;quot;#id-name=&amp;quot;, cfg.id_handlers[k].label});&lt;br /&gt;
		elseif id then															-- when cfg.id_handlers[k].COinS is not nil so urls created here&lt;br /&gt;
			OCinSoutput[&amp;quot;rft_id&amp;quot;] = table.concat{ cfg.id_handlers[k].prefix, v, cfg.id_handlers[k].suffix or &#039;&#039;, &amp;quot;#id-name=&amp;quot;, cfg.id_handlers[k].label };	-- others; provide a URL and indicate identifier name as #fragment (human-readable, but transparent to browsers)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local last, first;&lt;br /&gt;
	for k, v in ipairs( data.Authors ) do&lt;br /&gt;
		last, first = coins_cleanup (v.last), coins_cleanup (v.first or &#039;&#039;);	-- replace any nowiki stripmarkers, non-printing or invisible characters&lt;br /&gt;
		if k == 1 then															-- for the first author name only&lt;br /&gt;
			if is_set(last) and is_set(first) then								-- set these COinS values if |first= and |last= specify the first author name&lt;br /&gt;
				OCinSoutput[&amp;quot;rft.aulast&amp;quot;] = last;								-- book, journal, dissertation&lt;br /&gt;
				OCinSoutput[&amp;quot;rft.aufirst&amp;quot;] = first;								-- book, journal, dissertation&lt;br /&gt;
			elseif is_set(last) then &lt;br /&gt;
				OCinSoutput[&amp;quot;rft.au&amp;quot;] = last;									-- book, journal, dissertation -- otherwise use this form for the first name&lt;br /&gt;
			end&lt;br /&gt;
		else																	-- for all other authors&lt;br /&gt;
			if is_set(last) and is_set(first) then&lt;br /&gt;
				OCinSoutput[&amp;quot;rft.au&amp;quot;] = table.concat{ last, &amp;quot;, &amp;quot;, first };		-- book, journal, dissertation&lt;br /&gt;
			elseif is_set(last) then&lt;br /&gt;
				OCinSoutput[&amp;quot;rft.au&amp;quot;] = last;									-- book, journal, dissertation&lt;br /&gt;
			end&lt;br /&gt;
			-- TODO: At present we do not report &amp;quot;et al.&amp;quot;. Add anything special if this condition applies?&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	OCinSoutput.rft_id = data.URL;&lt;br /&gt;
	OCinSoutput.rfr_id = table.concat{ &amp;quot;info:sid/&amp;quot;, mw.site.server:match( &amp;quot;[^/]*$&amp;quot; ), &amp;quot;:&amp;quot;, data.RawPage };&lt;br /&gt;
&lt;br /&gt;
	-- TODO: Add optional extra info:&lt;br /&gt;
	-- rfr_dat=#REVISION&amp;lt;version&amp;gt; (referrer private data)&lt;br /&gt;
	-- ctx_id=&amp;lt;data.RawPage&amp;gt;#&amp;lt;ref&amp;gt; (identifier for the context object)&lt;br /&gt;
	-- ctx_tim=&amp;lt;ts&amp;gt; (timestamp in format yyyy-mm-ddThh:mm:ssTZD or yyyy-mm-dd)&lt;br /&gt;
	-- ctx_enc=info:ofi/enc:UTF-8 (character encoding)&lt;br /&gt;
	&lt;br /&gt;
	OCinSoutput = setmetatable( OCinSoutput, nil );&lt;br /&gt;
&lt;br /&gt;
	-- sort with version string always first, and combine.&lt;br /&gt;
	-- table.sort( OCinSoutput );&lt;br /&gt;
	table.insert( OCinSoutput, 1, &amp;quot;ctx_ver=&amp;quot; .. ctx_ver ); -- such as &amp;quot;Z39.88-2004&amp;quot;&lt;br /&gt;
	return table.concat(OCinSoutput, &amp;quot;&amp;amp;&amp;quot;);&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S E T _ S E L E C T E D _ M O D U L E S &amp;gt;--------------------------------------&lt;br /&gt;
&lt;br /&gt;
Sets local cfg table and imported functions table to same (live or sandbox) as that used by the other modules.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function set_selected_modules (cfg_table_ptr, utilities_page_ptr)&lt;br /&gt;
	cfg = cfg_table_ptr;&lt;br /&gt;
&lt;br /&gt;
	has_accept_as_written = utilities_page_ptr.has_accept_as_written;			-- import functions from selected Module:Citation/CS1/Utilities module&lt;br /&gt;
	is_set = utilities_page_ptr.is_set;&lt;br /&gt;
	in_array = utilities_page_ptr.in_array;&lt;br /&gt;
	remove_wiki_link = utilities_page_ptr.remove_wiki_link;&lt;br /&gt;
	strip_apostrophe_markup = utilities_page_ptr.strip_apostrophe_markup;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; E X P O R T E D   F U N C T I O N S &amp;gt;------------------------------------------&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
return {&lt;br /&gt;
	make_coins_title = make_coins_title,&lt;br /&gt;
	get_coins_pages = get_coins_pages,&lt;br /&gt;
	COinS = COinS,&lt;br /&gt;
	set_selected_modules = set_selected_modules,&lt;br /&gt;
	}&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Modul:Citation/CS1&amp;diff=1517</id>
		<title>Modul:Citation/CS1</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Modul:Citation/CS1&amp;diff=1517"/>
		<updated>2022-08-12T16:59:11Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;require (&#039;Module:No globals&#039;);&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; F O R W A R D   D E C L A R A T I O N S &amp;gt;--------------------------------------&lt;br /&gt;
&lt;br /&gt;
each of these counts against the Lua upvalue limit&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local validation;																-- functions in Module:Citation/CS1/Date_validation&lt;br /&gt;
&lt;br /&gt;
local utilities;																-- functions in Module:Citation/CS1/Utilities&lt;br /&gt;
local z ={};																	-- table of tables in Module:Citation/CS1/Utilities&lt;br /&gt;
&lt;br /&gt;
local identifiers;																-- functions and tables in Module:Citation/CS1/Identifiers&lt;br /&gt;
local metadata;																	-- functions in Module:Citation/CS1/COinS&lt;br /&gt;
local cfg = {};																	-- table of configuration tables that are defined in Module:Citation/CS1/Configuration&lt;br /&gt;
local whitelist = {};															-- table of tables listing valid template parameter names; defined in Module:Citation/CS1/Whitelist&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[------------------&amp;lt; P A G E   S C O P E   V A R I A B L E S &amp;gt;---------------&lt;br /&gt;
&lt;br /&gt;
declare variables here that have page-wide scope that are not brought in from&lt;br /&gt;
other modules; that are created here and used here&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local added_deprecated_cat;														-- Boolean flag so that the category is added only once&lt;br /&gt;
local added_vanc_errs;															-- Boolean flag so we only emit one Vancouver error / category&lt;br /&gt;
local added_generic_name_errs;													-- Boolean flag so we only emit one generic name error / category and stop testing names once an error is encountered&lt;br /&gt;
local Frame;																	-- holds the module&#039;s frame table&lt;br /&gt;
local is_preview_mode;															-- true when article is in preview mode; false when using &#039;Preview page with this template&#039; (previewing the module)&lt;br /&gt;
local is_sandbox;																-- true when using sandbox modules to render citation&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; F I R S T _ S E T &amp;gt;------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Locates and returns the first set value in a table of values where the order established in the table,&lt;br /&gt;
left-to-right (or top-to-bottom), is the order in which the values are evaluated.  Returns nil if none are set.&lt;br /&gt;
&lt;br /&gt;
This version replaces the original &#039;for _, val in pairs do&#039; and a similar version that used ipairs.  With the pairs&lt;br /&gt;
version the order of evaluation could not be guaranteed.  With the ipairs version, a nil value would terminate&lt;br /&gt;
the for-loop before it reached the actual end of the list.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function first_set (list, count)&lt;br /&gt;
	local i = 1;&lt;br /&gt;
	while i &amp;lt;= count do															-- loop through all items in list&lt;br /&gt;
		if utilities.is_set( list[i] ) then&lt;br /&gt;
			return list[i];														-- return the first set list member&lt;br /&gt;
		end&lt;br /&gt;
		i = i + 1;																-- point to next&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; A D D _ V A N C _ E R R O R &amp;gt;----------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Adds a single Vancouver system error message to the template&#039;s output regardless of how many error actually exist.&lt;br /&gt;
To prevent duplication, added_vanc_errs is nil until an error message is emitted.&lt;br /&gt;
&lt;br /&gt;
added_vanc_errs is a Boolean declared in page scope variables above&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function add_vanc_error (source, position)&lt;br /&gt;
	if added_vanc_errs then return end&lt;br /&gt;
		&lt;br /&gt;
	added_vanc_errs = true;														-- note that we&#039;ve added this category&lt;br /&gt;
	utilities.set_message (&#039;err_vancouver&#039;, {source, position});&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; I S _ S C H E M E &amp;gt;------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
does this thing that purports to be a URI scheme seem to be a valid scheme?  The scheme is checked to see if it&lt;br /&gt;
is in agreement with http://tools.ietf.org/html/std66#section-3.1 which says:&lt;br /&gt;
	Scheme names consist of a sequence of characters beginning with a&lt;br /&gt;
   letter and followed by any combination of letters, digits, plus&lt;br /&gt;
   (&amp;quot;+&amp;quot;), period (&amp;quot;.&amp;quot;), or hyphen (&amp;quot;-&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
returns true if it does, else false&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function is_scheme (scheme)&lt;br /&gt;
	return scheme and scheme:match (&#039;^%a[%a%d%+%.%-]*:&#039;);						-- true if scheme is set and matches the pattern&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[=[-------------------------&amp;lt; I S _ D O M A I N _ N A M E &amp;gt;--------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Does this thing that purports to be a domain name seem to be a valid domain name?&lt;br /&gt;
&lt;br /&gt;
Syntax defined here: http://tools.ietf.org/html/rfc1034#section-3.5&lt;br /&gt;
BNF defined here: https://tools.ietf.org/html/rfc4234&lt;br /&gt;
Single character names are generally reserved; see https://tools.ietf.org/html/draft-ietf-dnsind-iana-dns-01#page-15;&lt;br /&gt;
	see also [[Single-letter second-level domain]]&lt;br /&gt;
list of TLDs: https://www.iana.org/domains/root/db&lt;br /&gt;
&lt;br /&gt;
RFC 952 (modified by RFC 1123) requires the first and last character of a hostname to be a letter or a digit.  Between&lt;br /&gt;
the first and last characters the name may use letters, digits, and the hyphen.&lt;br /&gt;
&lt;br /&gt;
Also allowed are IPv4 addresses. IPv6 not supported&lt;br /&gt;
&lt;br /&gt;
domain is expected to be stripped of any path so that the last character in the last character of the TLD.  tld&lt;br /&gt;
is two or more alpha characters.  Any preceding &#039;//&#039; (from splitting a URL with a scheme) will be stripped&lt;br /&gt;
here.  Perhaps not necessary but retained in case it is necessary for IPv4 dot decimal.&lt;br /&gt;
&lt;br /&gt;
There are several tests:&lt;br /&gt;
	the first character of the whole domain name including subdomains must be a letter or a digit&lt;br /&gt;
	internationalized domain name (ASCII characters with .xn-- ASCII Compatible Encoding (ACE) prefix xn-- in the TLD) see https://tools.ietf.org/html/rfc3490&lt;br /&gt;
	single-letter/digit second-level domains in the .org, .cash, and .today TLDs&lt;br /&gt;
	q, x, and z SL domains in the .com TLD&lt;br /&gt;
	i and q SL domains in the .net TLD&lt;br /&gt;
	single-letter SL domains in the ccTLDs (where the ccTLD is two letters)&lt;br /&gt;
	two-character SL domains in gTLDs (where the gTLD is two or more letters)&lt;br /&gt;
	three-plus-character SL domains in gTLDs (where the gTLD is two or more letters)&lt;br /&gt;
	IPv4 dot-decimal address format; TLD not allowed&lt;br /&gt;
&lt;br /&gt;
returns true if domain appears to be a proper name and TLD or IPv4 address, else false&lt;br /&gt;
&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local function is_domain_name (domain)&lt;br /&gt;
	if not domain then&lt;br /&gt;
		return false;															-- if not set, abandon&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	domain = domain:gsub (&#039;^//&#039;, &#039;&#039;);											-- strip &#039;//&#039; from domain name if present; done here so we only have to do it once&lt;br /&gt;
	&lt;br /&gt;
	if not domain:match (&#039;^[%w]&#039;) then											-- first character must be letter or digit&lt;br /&gt;
		return false;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if domain:match (&#039;^%a+:&#039;) then												-- hack to detect things that look like s:Page:Title where Page: is namespace at Wikisource&lt;br /&gt;
		return false;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local patterns = {															-- patterns that look like URLs&lt;br /&gt;
		&#039;%f[%w][%w][%w%-]+[%w]%.%a%a+$&#039;,										-- three or more character hostname.hostname or hostname.tld&lt;br /&gt;
		&#039;%f[%w][%w][%w%-]+[%w]%.xn%-%-[%w]+$&#039;,									-- internationalized domain name with ACE prefix&lt;br /&gt;
		&#039;%f[%a][qxz]%.com$&#039;,													-- assigned one character .com hostname (x.com times out 2015-12-10)&lt;br /&gt;
		&#039;%f[%a][iq]%.net$&#039;,														-- assigned one character .net hostname (q.net registered but not active 2015-12-10)&lt;br /&gt;
		&#039;%f[%w][%w]%.%a%a$&#039;,													-- one character hostname and ccTLD (2 chars)&lt;br /&gt;
		&#039;%f[%w][%w][%w]%.%a%a+$&#039;,												-- two character hostname and TLD&lt;br /&gt;
		&#039;^%d%d?%d?%.%d%d?%d?%.%d%d?%d?%.%d%d?%d?&#039;,								-- IPv4 address&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
	for _, pattern in ipairs (patterns) do										-- loop through the patterns list&lt;br /&gt;
		if domain:match (pattern) then&lt;br /&gt;
			return true;														-- if a match then we think that this thing that purports to be a URL is a URL&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	for _, d in ipairs ({&#039;cash&#039;, &#039;company&#039;, &#039;today&#039;, &#039;org&#039;}) do					-- look for single letter second level domain names for these top level domains&lt;br /&gt;
		if domain:match (&#039;%f[%w][%w]%.&#039; .. d) then&lt;br /&gt;
			return true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return false;																-- no matches, we don&#039;t know what this thing is&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; I S _ U R L &amp;gt;------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
returns true if the scheme and domain parts of a URL appear to be a valid URL; else false.&lt;br /&gt;
&lt;br /&gt;
This function is the last step in the validation process.  This function is separate because there are cases that&lt;br /&gt;
are not covered by split_url(), for example is_parameter_ext_wikilink() which is looking for bracketted external&lt;br /&gt;
wikilinks.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function is_url (scheme, domain)&lt;br /&gt;
	if utilities.is_set (scheme) then											-- if scheme is set check it and domain&lt;br /&gt;
		return is_scheme (scheme) and is_domain_name (domain);&lt;br /&gt;
	else&lt;br /&gt;
		return is_domain_name (domain);											-- scheme not set when URL is protocol-relative&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S P L I T _ U R L &amp;gt;------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Split a URL into a scheme, authority indicator, and domain.&lt;br /&gt;
&lt;br /&gt;
First remove Fully Qualified Domain Name terminator (a dot following TLD) (if any) and any path(/), query(?) or fragment(#).&lt;br /&gt;
&lt;br /&gt;
If protocol-relative URL, return nil scheme and domain else return nil for both scheme and domain.&lt;br /&gt;
&lt;br /&gt;
When not protocol-relative, get scheme, authority indicator, and domain.  If there is an authority indicator (one&lt;br /&gt;
or more &#039;/&#039; characters immediately following the scheme&#039;s colon), make sure that there are only 2.&lt;br /&gt;
&lt;br /&gt;
Any URL that does not have news: scheme must have authority indicator (//).  TODO: are there other common schemes&lt;br /&gt;
like news: that don&#039;t use authority indicator?&lt;br /&gt;
&lt;br /&gt;
Strip off any port and path;&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function split_url (url_str)&lt;br /&gt;
	local scheme, authority, domain;&lt;br /&gt;
	&lt;br /&gt;
	url_str = url_str:gsub (&#039;([%a%d])%.?[/%?#].*$&#039;, &#039;%1&#039;);						-- strip FQDN terminator and path(/), query(?), fragment (#) (the capture prevents false replacement of &#039;//&#039;)&lt;br /&gt;
&lt;br /&gt;
	if url_str:match (&#039;^//%S*&#039;) then											-- if there is what appears to be a protocol-relative URL&lt;br /&gt;
		domain = url_str:match (&#039;^//(%S*)&#039;)&lt;br /&gt;
	elseif url_str:match (&#039;%S-:/*%S+&#039;) then										-- if there is what appears to be a scheme, optional authority indicator, and domain name&lt;br /&gt;
		scheme, authority, domain = url_str:match (&#039;(%S-:)(/*)(%S+)&#039;);			-- extract the scheme, authority indicator, and domain portions&lt;br /&gt;
		if utilities.is_set (authority) then&lt;br /&gt;
			authority = authority:gsub (&#039;//&#039;, &#039;&#039;, 1);							-- replace place 1 pair of &#039;/&#039; with nothing;&lt;br /&gt;
			if utilities.is_set(authority) then									-- if anything left (1 or 3+ &#039;/&#039; where authority should be) then&lt;br /&gt;
				return scheme;													-- return scheme only making domain nil which will cause an error message&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			if not scheme:match (&#039;^news:&#039;) then									-- except for news:..., MediaWiki won&#039;t link URLs that do not have authority indicator; TODO: a better way to do this test?&lt;br /&gt;
				return scheme;													-- return scheme only making domain nil which will cause an error message&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		domain = domain:gsub (&#039;(%a):%d+&#039;, &#039;%1&#039;);								-- strip port number if present&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return scheme, domain;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; L I N K _ P A R A M _ O K &amp;gt;---------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
checks the content of |title-link=, |series-link=, |author-link=, etc. for properly formatted content: no wikilinks, no URLs&lt;br /&gt;
&lt;br /&gt;
Link parameters are to hold the title of a Wikipedia article, so none of the WP:TITLESPECIALCHARACTERS are allowed:&lt;br /&gt;
	# &amp;lt; &amp;gt; [ ] | { } _&lt;br /&gt;
except the underscore which is used as a space in wiki URLs and # which is used for section links&lt;br /&gt;
&lt;br /&gt;
returns false when the value contains any of these characters.&lt;br /&gt;
&lt;br /&gt;
When there are no illegal characters, this function returns TRUE if value DOES NOT appear to be a valid URL (the&lt;br /&gt;
|&amp;lt;param&amp;gt;-link= parameter is ok); else false when value appears to be a valid URL (the |&amp;lt;param&amp;gt;-link= parameter is NOT ok).&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function link_param_ok (value)&lt;br /&gt;
	local scheme, domain;&lt;br /&gt;
	if value:find (&#039;[&amp;lt;&amp;gt;%[%]|{}]&#039;) then											-- if any prohibited characters&lt;br /&gt;
		return false;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	scheme, domain = split_url (value);											-- get scheme or nil and domain or nil from URL; &lt;br /&gt;
	return not is_url (scheme, domain);											-- return true if value DOES NOT appear to be a valid URL&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; L I N K _ T I T L E _ O K &amp;gt;---------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Use link_param_ok() to validate |&amp;lt;param&amp;gt;-link= value and its matching |&amp;lt;title&amp;gt;= value.&lt;br /&gt;
&lt;br /&gt;
|&amp;lt;title&amp;gt;= may be wiki-linked but not when |&amp;lt;param&amp;gt;-link= has a value.  This function emits an error message when&lt;br /&gt;
that condition exists&lt;br /&gt;
&lt;br /&gt;
check &amp;lt;link&amp;gt; for inter-language interwiki-link prefix.  prefix must be a MediaWiki-recognized language&lt;br /&gt;
code and must begin with a colon.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function link_title_ok (link, lorig, title, torig)&lt;br /&gt;
local orig;&lt;br /&gt;
	if utilities.is_set (link) then 											-- don&#039;t bother if &amp;lt;param&amp;gt;-link doesn&#039;t have a value&lt;br /&gt;
		if not link_param_ok (link) then										-- check |&amp;lt;param&amp;gt;-link= markup&lt;br /&gt;
			orig = lorig;														-- identify the failing link parameter&lt;br /&gt;
		elseif title:find (&#039;%[%[&#039;) then											-- check |title= for wikilink markup&lt;br /&gt;
			orig = torig;														-- identify the failing |title= parameter&lt;br /&gt;
		elseif link:match (&#039;^%a+:&#039;) then										-- if the link is what looks like an interwiki&lt;br /&gt;
			local prefix = link:match (&#039;^(%a+):&#039;):lower();						-- get the interwiki prefix&lt;br /&gt;
&lt;br /&gt;
			if cfg.inter_wiki_map[prefix] then									-- if prefix is in the map, must have preceding colon&lt;br /&gt;
				orig = lorig;													-- flag as error&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if utilities.is_set (orig) then&lt;br /&gt;
		link = &#039;&#039;;																-- unset&lt;br /&gt;
		utilities.set_message (&#039;err_bad_paramlink&#039;, orig);						-- URL or wikilink in |title= with |title-link=;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return link;																-- link if ok, empty string else&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; C H E C K _ U R L &amp;gt;------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Determines whether a URL string appears to be valid.&lt;br /&gt;
&lt;br /&gt;
First we test for space characters.  If any are found, return false.  Then split the URL into scheme and domain&lt;br /&gt;
portions, or for protocol-relative (//example.com) URLs, just the domain.  Use is_url() to validate the two&lt;br /&gt;
portions of the URL.  If both are valid, or for protocol-relative if domain is valid, return true, else false.&lt;br /&gt;
&lt;br /&gt;
Because it is different from a standard URL, and because this module used external_link() to make external links&lt;br /&gt;
that work for standard and news: links, we validate newsgroup names here.  The specification for a newsgroup name&lt;br /&gt;
is at https://tools.ietf.org/html/rfc5536#section-3.1.4&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function check_url( url_str )&lt;br /&gt;
	if nil == url_str:match (&amp;quot;^%S+$&amp;quot;) then										-- if there are any spaces in |url=value it can&#039;t be a proper URL&lt;br /&gt;
		return false;&lt;br /&gt;
	end&lt;br /&gt;
	local scheme, domain;&lt;br /&gt;
&lt;br /&gt;
	scheme, domain = split_url (url_str);										-- get scheme or nil and domain or nil from URL;&lt;br /&gt;
	&lt;br /&gt;
	if &#039;news:&#039; == scheme then													-- special case for newsgroups&lt;br /&gt;
		return domain:match(&#039;^[%a%d%+%-_]+%.[%a%d%+%-_%.]*[%a%d%+%-_]$&#039;);&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return is_url (scheme, domain);												-- return true if value appears to be a valid URL&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[=[-------------------------&amp;lt; I S _ P A R A M E T E R _ E X T _ W I K I L I N K &amp;gt;----------------------------&lt;br /&gt;
&lt;br /&gt;
Return true if a parameter value has a string that begins and ends with square brackets [ and ] and the first&lt;br /&gt;
non-space characters following the opening bracket appear to be a URL.  The test will also find external wikilinks&lt;br /&gt;
that use protocol-relative URLs. Also finds bare URLs.&lt;br /&gt;
&lt;br /&gt;
The frontier pattern prevents a match on interwiki-links which are similar to scheme:path URLs.  The tests that&lt;br /&gt;
find bracketed URLs are required because the parameters that call this test (currently |title=, |chapter=, |work=,&lt;br /&gt;
and |publisher=) may have wikilinks and there are articles or redirects like &#039;//Hus&#039; so, while uncommon, |title=[[//Hus]]&lt;br /&gt;
is possible as might be [[en://Hus]].&lt;br /&gt;
&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local function is_parameter_ext_wikilink (value)&lt;br /&gt;
local scheme, domain;&lt;br /&gt;
&lt;br /&gt;
	if value:match (&#039;%f[%[]%[%a%S*:%S+.*%]&#039;) then								-- if ext. wikilink with scheme and domain: [xxxx://yyyyy.zzz]&lt;br /&gt;
		scheme, domain = split_url (value:match (&#039;%f[%[]%[(%a%S*:%S+).*%]&#039;));&lt;br /&gt;
	elseif value:match (&#039;%f[%[]%[//%S+.*%]&#039;) then								-- if protocol-relative ext. wikilink: [//yyyyy.zzz]&lt;br /&gt;
		scheme, domain = split_url (value:match (&#039;%f[%[]%[(//%S+).*%]&#039;));&lt;br /&gt;
	elseif value:match (&#039;%a%S*:%S+&#039;) then										-- if bare URL with scheme; may have leading or trailing plain text&lt;br /&gt;
		scheme, domain = split_url (value:match (&#039;(%a%S*:%S+)&#039;));&lt;br /&gt;
	elseif value:match (&#039;//%S+&#039;) then											-- if protocol-relative bare URL: //yyyyy.zzz; may have leading or trailing plain text&lt;br /&gt;
		scheme, domain = split_url (value:match (&#039;(//%S+)&#039;));					-- what is left should be the domain&lt;br /&gt;
	else&lt;br /&gt;
		return false;															-- didn&#039;t find anything that is obviously a URL&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return is_url (scheme, domain);												-- return true if value appears to be a valid URL&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[-------------------------&amp;lt; C H E C K _ F O R _ U R L &amp;gt;-----------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
loop through a list of parameters and their values.  Look at the value and if it has an external link, emit an error message.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function check_for_url (parameter_list, error_list)&lt;br /&gt;
	for k, v in pairs (parameter_list) do										-- for each parameter in the list&lt;br /&gt;
		if is_parameter_ext_wikilink (v) then									-- look at the value; if there is a URL add an error message&lt;br /&gt;
			table.insert (error_list, utilities.wrap_style (&#039;parameter&#039;, k));&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S A F E _ F O R _ U R L &amp;gt;------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Escape sequences for content that will be used for URL descriptions&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function safe_for_url( str )&lt;br /&gt;
	if str:match( &amp;quot;%[%[.-%]%]&amp;quot; ) ~= nil then &lt;br /&gt;
		utilities.set_message (&#039;err_wikilink_in_url&#039;, {});&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return str:gsub( &#039;[%[%]\n]&#039;, {	&lt;br /&gt;
		[&#039;[&#039;] = &#039;&amp;amp;#91;&#039;,&lt;br /&gt;
		[&#039;]&#039;] = &#039;&amp;amp;#93;&#039;,&lt;br /&gt;
		[&#039;\n&#039;] = &#039; &#039; } );&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; E X T E R N A L _ L I N K &amp;gt;----------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Format an external link with error checking&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function external_link (URL, label, source, access)&lt;br /&gt;
	local err_msg = &#039;&#039;;&lt;br /&gt;
	local domain;&lt;br /&gt;
	local path;&lt;br /&gt;
	local base_url;&lt;br /&gt;
&lt;br /&gt;
	if not utilities.is_set (label) then&lt;br /&gt;
		label = URL;&lt;br /&gt;
		if utilities.is_set (source) then&lt;br /&gt;
			utilities.set_message (&#039;err_bare_url_missing_title&#039;, {utilities.wrap_style (&#039;parameter&#039;, source)});&lt;br /&gt;
		else&lt;br /&gt;
			error (cfg.messages[&amp;quot;bare_url_no_origin&amp;quot;]);&lt;br /&gt;
		end			&lt;br /&gt;
	end&lt;br /&gt;
	if not check_url (URL) then&lt;br /&gt;
		utilities.set_message (&#039;err_bad_url&#039;, {utilities.wrap_style (&#039;parameter&#039;, source)});&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	domain, path = URL:match (&#039;^([/%.%-%+:%a%d]+)([/%?#].*)$&#039;);					-- split the URL into scheme plus domain and path&lt;br /&gt;
	if path then																-- if there is a path portion&lt;br /&gt;
		path = path:gsub (&#039;[%[%]]&#039;, {[&#039;[&#039;] = &#039;%5b&#039;, [&#039;]&#039;] = &#039;%5d&#039;});			-- replace &#039;[&#039; and &#039;]&#039; with their percent-encoded values&lt;br /&gt;
		URL = table.concat ({domain, path});									-- and reassemble&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	base_url = table.concat ({ &amp;quot;[&amp;quot;, URL, &amp;quot; &amp;quot;, safe_for_url (label), &amp;quot;]&amp;quot; });		-- assemble a wiki-markup URL&lt;br /&gt;
&lt;br /&gt;
	if utilities.is_set (access) then											-- access level (subscription, registration, limited)&lt;br /&gt;
		base_url = utilities.substitute (cfg.presentation[&#039;ext-link-access-signal&#039;], {cfg.presentation[access].class, cfg.presentation[access].title, base_url});	-- add the appropriate icon&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return base_url;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; D E P R E C A T E D _ P A R A M E T E R &amp;gt;--------------------------------------&lt;br /&gt;
&lt;br /&gt;
Categorize and emit an error message when the citation contains one or more deprecated parameters.  The function includes the&lt;br /&gt;
offending parameter name to the error message.  Only one error message is emitted regardless of the number of deprecated&lt;br /&gt;
parameters in the citation.&lt;br /&gt;
&lt;br /&gt;
added_deprecated_cat is a Boolean declared in page scope variables above&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function deprecated_parameter(name)&lt;br /&gt;
	if not added_deprecated_cat then&lt;br /&gt;
		added_deprecated_cat = true;											-- note that we&#039;ve added this category&lt;br /&gt;
		utilities.set_message (&#039;err_deprecated_params&#039;, {name});				-- add error message&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[=[-------------------------&amp;lt; K E R N _ Q U O T E S &amp;gt;--------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Apply kerning to open the space between the quote mark provided by the module and a leading or trailing quote&lt;br /&gt;
mark contained in a |title= or |chapter= parameter&#039;s value.&lt;br /&gt;
&lt;br /&gt;
This function will positive kern either single or double quotes:&lt;br /&gt;
	&amp;quot;&#039;Unkerned title with leading and trailing single quote marks&#039;&amp;quot;&lt;br /&gt;
	&amp;quot; &#039;Kerned title with leading and trailing single quote marks&#039; &amp;quot; (in real life the kerning isn&#039;t as wide as this example)&lt;br /&gt;
Double single quotes (italic or bold wiki-markup) are not kerned.&lt;br /&gt;
&lt;br /&gt;
Replaces Unicode quote marks in plain text or in the label portion of a [[L|D]] style wikilink with typewriter&lt;br /&gt;
quote marks regardless of the need for kerning.  Unicode quote marks are not replaced in simple [[D]] wikilinks.&lt;br /&gt;
&lt;br /&gt;
Call this function for chapter titles, for website titles, etc.; not for book titles.&lt;br /&gt;
&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local function kern_quotes (str)&lt;br /&gt;
	local cap = &#039;&#039;;&lt;br /&gt;
	local wl_type, label, link;&lt;br /&gt;
&lt;br /&gt;
	wl_type, label, link = utilities.is_wikilink (str);							-- wl_type is: 0, no wl (text in label variable); 1, [[D]]; 2, [[L|D]]&lt;br /&gt;
	&lt;br /&gt;
	if 1 == wl_type then														-- [[D]] simple wikilink with or without quote marks&lt;br /&gt;
		if mw.ustring.match (str, &#039;%[%[[\&amp;quot;“”\&#039;‘’].+[\&amp;quot;“”\&#039;‘’]%]%]&#039;) then		-- leading and trailing quote marks&lt;br /&gt;
			str = utilities.substitute (cfg.presentation[&#039;kern-left&#039;], str);&lt;br /&gt;
			str = utilities.substitute (cfg.presentation[&#039;kern-right&#039;], str);&lt;br /&gt;
		elseif mw.ustring.match (str, &#039;%[%[[\&amp;quot;“”\&#039;‘’].+%]%]&#039;)	then			-- leading quote marks&lt;br /&gt;
			str = utilities.substitute (cfg.presentation[&#039;kern-left&#039;], str);&lt;br /&gt;
		elseif mw.ustring.match (str, &#039;%[%[.+[\&amp;quot;“”\&#039;‘’]%]%]&#039;) then				-- trailing quote marks&lt;br /&gt;
			str = utilities.substitute (cfg.presentation[&#039;kern-right&#039;], str);&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
	else																		-- plain text or [[L|D]]; text in label variable&lt;br /&gt;
		label = mw.ustring.gsub (label, &#039;[“”]&#039;, &#039;\&amp;quot;&#039;);							-- replace “” (U+201C &amp;amp; U+201D) with &amp;quot; (typewriter double quote mark)&lt;br /&gt;
		label = mw.ustring.gsub (label, &#039;[‘’]&#039;, &#039;\&#039;&#039;);							-- replace ‘’ (U+2018 &amp;amp; U+2019) with &#039; (typewriter single quote mark)&lt;br /&gt;
&lt;br /&gt;
		cap = mw.ustring.match (label, &amp;quot;^([\&amp;quot;\&#039;][^\&#039;].+)&amp;quot;);						-- match leading double or single quote but not doubled single quotes (italic markup)&lt;br /&gt;
		if utilities.is_set (cap) then&lt;br /&gt;
			label = utilities.substitute (cfg.presentation[&#039;kern-left&#039;], cap);&lt;br /&gt;
		end&lt;br /&gt;
	&lt;br /&gt;
		cap = mw.ustring.match (label, &amp;quot;^(.+[^\&#039;][\&amp;quot;\&#039;])$&amp;quot;)						-- match trailing double or single quote but not doubled single quotes (italic markup)&lt;br /&gt;
		if utilities.is_set (cap) then&lt;br /&gt;
			label = utilities.substitute (cfg.presentation[&#039;kern-right&#039;], cap);&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		if 2 == wl_type then&lt;br /&gt;
			str = utilities.make_wikilink (link, label);						-- reassemble the wikilink&lt;br /&gt;
		else&lt;br /&gt;
			str = label;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return str;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; F O R M A T _ S C R I P T _ V A L U E &amp;gt;----------------------------------------&lt;br /&gt;
&lt;br /&gt;
|script-title= holds title parameters that are not written in Latin-based scripts: Chinese, Japanese, Arabic, Hebrew, etc. These scripts should&lt;br /&gt;
not be italicized and may be written right-to-left.  The value supplied by |script-title= is concatenated onto Title after Title has been wrapped&lt;br /&gt;
in italic markup.&lt;br /&gt;
&lt;br /&gt;
Regardless of language, all values provided by |script-title= are wrapped in &amp;lt;bdi&amp;gt;...&amp;lt;/bdi&amp;gt; tags to isolate RTL languages from the English left to right.&lt;br /&gt;
&lt;br /&gt;
|script-title= provides a unique feature.  The value in |script-title= may be prefixed with a two-character ISO 639-1 language code and a colon:&lt;br /&gt;
	|script-title=ja:*** *** (where * represents a Japanese character)&lt;br /&gt;
Spaces between the two-character code and the colon and the colon and the first script character are allowed:&lt;br /&gt;
	|script-title=ja : *** ***&lt;br /&gt;
	|script-title=ja: *** ***&lt;br /&gt;
	|script-title=ja :*** ***&lt;br /&gt;
Spaces preceding the prefix are allowed: |script-title = ja:*** ***&lt;br /&gt;
&lt;br /&gt;
The prefix is checked for validity.  If it is a valid ISO 639-1 language code, the lang attribute (lang=&amp;quot;ja&amp;quot;) is added to the &amp;lt;bdi&amp;gt; tag so that browsers can&lt;br /&gt;
know the language the tag contains.  This may help the browser render the script more correctly.  If the prefix is invalid, the lang attribute&lt;br /&gt;
is not added.  At this time there is no error message for this condition.&lt;br /&gt;
&lt;br /&gt;
Supports |script-title=, |script-chapter=, |script-&amp;lt;periodical&amp;gt;=&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function format_script_value (script_value, script_param)&lt;br /&gt;
	local lang=&#039;&#039;;																-- initialize to empty string&lt;br /&gt;
	local name;&lt;br /&gt;
	if script_value:match(&#039;^%l%l%l?%s*:&#039;) then									-- if first 3 or 4 non-space characters are script language prefix&lt;br /&gt;
		lang = script_value:match(&#039;^(%l%l%l?)%s*:%s*%S.*&#039;);						-- get the language prefix or nil if there is no script&lt;br /&gt;
		if not utilities.is_set (lang) then&lt;br /&gt;
			utilities.set_message (&#039;err_script_parameter&#039;, {script_param, cfg.err_msg_supl[&#039;missing title part&#039;]});		-- prefix without &#039;title&#039;; add error message&lt;br /&gt;
			return &#039;&#039;;															-- script_value was just the prefix so return empty string&lt;br /&gt;
		end&lt;br /&gt;
																				-- if we get this far we have prefix and script&lt;br /&gt;
		name = cfg.lang_code_remap[lang] or mw.language.fetchLanguageName( lang, cfg.this_wiki_code );	-- get language name so that we can use it to categorize&lt;br /&gt;
		if utilities.is_set (name) then											-- is prefix a proper ISO 639-1 language code?&lt;br /&gt;
			script_value = script_value:gsub (&#039;^%l+%s*:%s*&#039;, &#039;&#039;);				-- strip prefix from script&lt;br /&gt;
																				-- is prefix one of these language codes?&lt;br /&gt;
			if utilities.in_array (lang, cfg.script_lang_codes) then&lt;br /&gt;
				utilities.add_prop_cat (&#039;script&#039;, {name, lang})&lt;br /&gt;
			else&lt;br /&gt;
				utilities.set_message (&#039;err_script_parameter&#039;, {script_param, cfg.err_msg_supl[&#039;unknown language code&#039;]});	-- unknown script-language; add error message&lt;br /&gt;
			end&lt;br /&gt;
			lang = &#039; lang=&amp;quot;&#039; .. lang .. &#039;&amp;quot; &#039;;									-- convert prefix into a lang attribute&lt;br /&gt;
		else&lt;br /&gt;
			utilities.set_message (&#039;err_script_parameter&#039;, {script_param, cfg.err_msg_supl[&#039;invalid language code&#039;]});		-- invalid language code; add error message&lt;br /&gt;
			lang = &#039;&#039;;															-- invalid so set lang to empty string&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		utilities.set_message (&#039;err_script_parameter&#039;, {script_param, cfg.err_msg_supl[&#039;missing prefix&#039;]});				-- no language code prefix; add error message&lt;br /&gt;
	end&lt;br /&gt;
	script_value = utilities.substitute (cfg.presentation[&#039;bdi&#039;], {lang, script_value});	-- isolate in case script is RTL&lt;br /&gt;
&lt;br /&gt;
	return script_value;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S C R I P T _ C O N C A T E N A T E &amp;gt;------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Initially for |title= and |script-title=, this function concatenates those two parameter values after the script&lt;br /&gt;
value has been wrapped in &amp;lt;bdi&amp;gt; tags.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function script_concatenate (title, script, script_param)&lt;br /&gt;
	if utilities.is_set (script) then&lt;br /&gt;
		script = format_script_value (script, script_param);					-- &amp;lt;bdi&amp;gt; tags, lang attribute, categorization, etc.; returns empty string on error&lt;br /&gt;
		if utilities.is_set (script) then&lt;br /&gt;
			title = title .. &#039; &#039; .. script;										-- concatenate title and script title&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return title;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; W R A P _ M S G &amp;gt;--------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Applies additional message text to various parameter values. Supplied string is wrapped using a message_list&lt;br /&gt;
configuration taking one argument.  Supports lower case text for {{citation}} templates.  Additional text taken&lt;br /&gt;
from citation_config.messages - the reason this function is similar to but separate from wrap_style().&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function wrap_msg (key, str, lower)&lt;br /&gt;
	if not utilities.is_set ( str ) then&lt;br /&gt;
		return &amp;quot;&amp;quot;;&lt;br /&gt;
	end&lt;br /&gt;
	if true == lower then&lt;br /&gt;
		local msg;&lt;br /&gt;
		msg = cfg.messages[key]:lower();										-- set the message to lower case before &lt;br /&gt;
		return utilities.substitute ( msg, str );								-- including template text&lt;br /&gt;
	else&lt;br /&gt;
		return utilities.substitute ( cfg.messages[key], str );&lt;br /&gt;
	end		&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[----------------&amp;lt; W I K I S O U R C E _ U R L _ M A K E &amp;gt;-------------------&lt;br /&gt;
&lt;br /&gt;
Makes a Wikisource URL from Wikisource interwiki-link.  Returns the URL and appropriate&lt;br /&gt;
label; nil else.&lt;br /&gt;
&lt;br /&gt;
str is the value assigned to |chapter= (or aliases) or |title= or |title-link=&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function wikisource_url_make (str)&lt;br /&gt;
	local wl_type, D, L;&lt;br /&gt;
	local ws_url, ws_label;&lt;br /&gt;
	local wikisource_prefix = table.concat ({&#039;https://&#039;, cfg.this_wiki_code, &#039;.wikisource.org/wiki/&#039;});&lt;br /&gt;
&lt;br /&gt;
	wl_type, D, L = utilities.is_wikilink (str);								-- wl_type is 0 (not a wikilink), 1 (simple wikilink), 2 (complex wikilink)&lt;br /&gt;
&lt;br /&gt;
	if 0 == wl_type then														-- not a wikilink; might be from |title-link=&lt;br /&gt;
		str = D:match (&#039;^[Ww]ikisource:(.+)&#039;) or D:match (&#039;^[Ss]:(.+)&#039;);		-- article title from interwiki link with long-form or short-form namespace&lt;br /&gt;
		if utilities.is_set (str) then&lt;br /&gt;
			ws_url = table.concat ({											-- build a Wikisource URL&lt;br /&gt;
				wikisource_prefix,												-- prefix&lt;br /&gt;
				str,															-- article title&lt;br /&gt;
				});&lt;br /&gt;
			ws_label = str;														-- label for the URL&lt;br /&gt;
		end&lt;br /&gt;
	elseif 1 == wl_type then													-- simple wikilink: [[Wikisource:ws article]]&lt;br /&gt;
		str = D:match (&#039;^[Ww]ikisource:(.+)&#039;) or D:match (&#039;^[Ss]:(.+)&#039;);		-- article title from interwiki link with long-form or short-form namespace&lt;br /&gt;
		if utilities.is_set (str) then&lt;br /&gt;
			ws_url = table.concat ({											-- build a Wikisource URL&lt;br /&gt;
				wikisource_prefix,												-- prefix&lt;br /&gt;
				str,															-- article title&lt;br /&gt;
				});&lt;br /&gt;
			ws_label = str;														-- label for the URL&lt;br /&gt;
		end&lt;br /&gt;
	elseif 2 == wl_type then													-- non-so-simple wikilink: [[Wikisource:ws article|displayed text]] ([[L|D]])&lt;br /&gt;
		str = L:match (&#039;^[Ww]ikisource:(.+)&#039;) or L:match (&#039;^[Ss]:(.+)&#039;);		-- article title from interwiki link with long-form or short-form namespace&lt;br /&gt;
		if utilities.is_set (str) then&lt;br /&gt;
			ws_label = D;														-- get ws article name from display portion of interwiki link&lt;br /&gt;
			ws_url = table.concat ({											-- build a Wikisource URL&lt;br /&gt;
				wikisource_prefix,												-- prefix&lt;br /&gt;
				str,															-- article title without namespace from link portion of wikilink&lt;br /&gt;
				});&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if ws_url then&lt;br /&gt;
		ws_url = mw.uri.encode (ws_url, &#039;WIKI&#039;);								-- make a usable URL&lt;br /&gt;
		ws_url = ws_url:gsub (&#039;%%23&#039;, &#039;#&#039;);										-- undo percent-encoding of fragment marker&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return ws_url, ws_label, L or D;											-- return proper URL or nil and a label or nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[----------------&amp;lt; F O R M A T _ P E R I O D I C A L &amp;gt;-----------------------&lt;br /&gt;
&lt;br /&gt;
Format the three periodical parameters: |script-&amp;lt;periodical&amp;gt;=, |&amp;lt;periodical&amp;gt;=,&lt;br /&gt;
and |trans-&amp;lt;periodical&amp;gt;= into a single Periodical meta-parameter.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function format_periodical (script_periodical, script_periodical_source, periodical, trans_periodical)&lt;br /&gt;
&lt;br /&gt;
	if not utilities.is_set (periodical) then&lt;br /&gt;
		periodical = &#039;&#039;;														-- to be safe for concatenation&lt;br /&gt;
	else&lt;br /&gt;
		periodical = utilities.wrap_style (&#039;italic-title&#039;, periodical);			-- style &lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	periodical = script_concatenate (periodical, script_periodical, script_periodical_source);	-- &amp;lt;bdi&amp;gt; tags, lang attribute, categorization, etc.; must be done after title is wrapped&lt;br /&gt;
&lt;br /&gt;
	if utilities.is_set (trans_periodical) then&lt;br /&gt;
		trans_periodical = utilities.wrap_style (&#039;trans-italic-title&#039;, trans_periodical);&lt;br /&gt;
		if utilities.is_set (periodical) then&lt;br /&gt;
			periodical = periodical .. &#039; &#039; .. trans_periodical;&lt;br /&gt;
		else																	-- here when trans-periodical without periodical or script-periodical&lt;br /&gt;
			periodical = trans_periodical;&lt;br /&gt;
			utilities.set_message (&#039;err_trans_missing_title&#039;, {&#039;periodical&#039;});&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return periodical;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[------------------&amp;lt; F O R M A T _ C H A P T E R _ T I T L E &amp;gt;---------------&lt;br /&gt;
&lt;br /&gt;
Format the four chapter parameters: |script-chapter=, |chapter=, |trans-chapter=,&lt;br /&gt;
and |chapter-url= into a single chapter meta- parameter (chapter_url_source used&lt;br /&gt;
for error messages).&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function format_chapter_title (script_chapter, script_chapter_source, chapter, chapter_source, trans_chapter, trans_chapter_source, chapter_url, chapter_url_source, no_quotes, access)&lt;br /&gt;
	local ws_url, ws_label, L = wikisource_url_make (chapter);					-- make a wikisource URL and label from a wikisource interwiki link&lt;br /&gt;
	if ws_url then&lt;br /&gt;
		ws_label = ws_label:gsub (&#039;_&#039;, &#039; &#039;);									-- replace underscore separators with space characters&lt;br /&gt;
		chapter = ws_label;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if not utilities.is_set (chapter) then&lt;br /&gt;
		chapter = &#039;&#039;;															-- to be safe for concatenation&lt;br /&gt;
	else&lt;br /&gt;
		if false == no_quotes then&lt;br /&gt;
			chapter = kern_quotes (chapter);									-- if necessary, separate chapter title&#039;s leading and trailing quote marks from module provided quote marks&lt;br /&gt;
			chapter = utilities.wrap_style (&#039;quoted-title&#039;, chapter);&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	chapter = script_concatenate (chapter, script_chapter, script_chapter_source);	-- &amp;lt;bdi&amp;gt; tags, lang attribute, categorization, etc.; must be done after title is wrapped&lt;br /&gt;
&lt;br /&gt;
	if utilities.is_set (chapter_url) then&lt;br /&gt;
		chapter = external_link (chapter_url, chapter, chapter_url_source, access);	-- adds bare_url_missing_title error if appropriate&lt;br /&gt;
	elseif ws_url then&lt;br /&gt;
		chapter = external_link (ws_url, chapter .. &#039;&amp;amp;nbsp;&#039;, &#039;ws link in chapter&#039;);	-- adds bare_url_missing_title error if appropriate; space char to move icon away from chap text; TODO: better way to do this?&lt;br /&gt;
		chapter = utilities.substitute (cfg.presentation[&#039;interwiki-icon&#039;], {cfg.presentation[&#039;class-wikisource&#039;], L, chapter});				&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if utilities.is_set (trans_chapter) then&lt;br /&gt;
		trans_chapter = utilities.wrap_style (&#039;trans-quoted-title&#039;, trans_chapter);&lt;br /&gt;
		if utilities.is_set (chapter) then&lt;br /&gt;
			chapter = chapter .. &#039; &#039; .. trans_chapter;&lt;br /&gt;
		else																	-- here when trans_chapter without chapter or script-chapter&lt;br /&gt;
			chapter = trans_chapter;&lt;br /&gt;
			chapter_source = trans_chapter_source:match (&#039;trans%-?(.+)&#039;);		-- when no chapter, get matching name from trans-&amp;lt;param&amp;gt;&lt;br /&gt;
			utilities.set_message (&#039;err_trans_missing_title&#039;, {chapter_source});&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return chapter;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[----------------&amp;lt; H A S _ I N V I S I B L E _ C H A R S &amp;gt;-------------------&lt;br /&gt;
&lt;br /&gt;
This function searches a parameter&#039;s value for non-printable or invisible characters.&lt;br /&gt;
The search stops at the first match.&lt;br /&gt;
&lt;br /&gt;
This function will detect the visible replacement character when it is part of the Wikisource.&lt;br /&gt;
&lt;br /&gt;
Detects but ignores nowiki and math stripmarkers.  Also detects other named stripmarkers&lt;br /&gt;
(gallery, math, pre, ref) and identifies them with a slightly different error message.&lt;br /&gt;
See also coins_cleanup().&lt;br /&gt;
&lt;br /&gt;
Output of this function is an error message that identifies the character or the&lt;br /&gt;
Unicode group, or the stripmarker that was detected along with its position (or,&lt;br /&gt;
for multi-byte characters, the position of its first byte) in the parameter value.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function has_invisible_chars (param, v)&lt;br /&gt;
	local position = &#039;&#039;;														-- position of invisible char or starting position of stripmarker&lt;br /&gt;
	local capture;																-- used by stripmarker detection to hold name of the stripmarker&lt;br /&gt;
	local stripmarker;															-- boolean set true when a stripmarker is found&lt;br /&gt;
&lt;br /&gt;
	capture = string.match (v, &#039;[%w%p ]*&#039;);										-- test for values that are simple ASCII text and bypass other tests if true&lt;br /&gt;
	if capture == v then														-- if same there are no Unicode characters&lt;br /&gt;
		return;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	for _, invisible_char in ipairs (cfg.invisible_chars) do&lt;br /&gt;
		local char_name = invisible_char[1];									-- the character or group name&lt;br /&gt;
		local pattern = invisible_char[2];										-- the pattern used to find it&lt;br /&gt;
		position, _, capture = mw.ustring.find (v, pattern);					-- see if the parameter value contains characters that match the pattern&lt;br /&gt;
		&lt;br /&gt;
		if position and (cfg.invisible_defs.zwj == capture) then				-- if we found a zero-width joiner character&lt;br /&gt;
			if mw.ustring.find (v, cfg.indic_script) then						-- it&#039;s ok if one of the Indic scripts&lt;br /&gt;
				position = nil;													-- unset position&lt;br /&gt;
			elseif cfg.emoji[mw.ustring.codepoint (v, position+1)] then			-- is zwj followed by a character listed in emoji{}?&lt;br /&gt;
				position = nil;													-- unset position&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		if position then&lt;br /&gt;
			if &#039;nowiki&#039; == capture or &#039;math&#039; == capture or						-- nowiki and math stripmarkers (not an error condition)&lt;br /&gt;
				(&#039;templatestyles&#039; == capture and utilities.in_array (param, {&#039;id&#039;, &#039;quote&#039;})) then	-- templatestyles stripmarker allowed in these parameters&lt;br /&gt;
					stripmarker = true;											-- set a flag&lt;br /&gt;
			elseif true == stripmarker and cfg.invisible_defs.del == capture then	-- because stripmakers begin and end with the delete char, assume that we&#039;ve found one end of a stripmarker&lt;br /&gt;
				position = nil;													-- unset&lt;br /&gt;
			else&lt;br /&gt;
				local err_msg;&lt;br /&gt;
				if capture and not (cfg.invisible_defs.del == capture or cfg.invisible_defs.zwj == capture) then&lt;br /&gt;
					err_msg = capture .. &#039; &#039; .. char_name;&lt;br /&gt;
				else&lt;br /&gt;
					err_msg = char_name .. &#039; &#039; .. &#039;character&#039;;&lt;br /&gt;
				end&lt;br /&gt;
&lt;br /&gt;
				utilities.set_message (&#039;err_invisible_char&#039;, {err_msg, utilities.wrap_style (&#039;parameter&#039;, param), position});	-- add error message&lt;br /&gt;
				return;															-- and done with this parameter&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[-------------------&amp;lt; A R G U M E N T _ W R A P P E R &amp;gt;----------------------&lt;br /&gt;
&lt;br /&gt;
Argument wrapper.  This function provides support for argument mapping defined&lt;br /&gt;
in the configuration file so that multiple names can be transparently aliased to&lt;br /&gt;
single internal variable.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function argument_wrapper ( args )&lt;br /&gt;
	local origin = {};&lt;br /&gt;
	&lt;br /&gt;
	return setmetatable({&lt;br /&gt;
		ORIGIN = function ( self, k )&lt;br /&gt;
			local dummy = self[k];												-- force the variable to be loaded.&lt;br /&gt;
			return origin[k];&lt;br /&gt;
		end&lt;br /&gt;
	},&lt;br /&gt;
	{&lt;br /&gt;
		__index = function ( tbl, k )&lt;br /&gt;
			if origin[k] ~= nil then&lt;br /&gt;
				return nil;&lt;br /&gt;
			end&lt;br /&gt;
			&lt;br /&gt;
			local args, list, v = args, cfg.aliases[k];&lt;br /&gt;
			&lt;br /&gt;
			if type( list ) == &#039;table&#039; then&lt;br /&gt;
				v, origin[k] = utilities.select_one ( args, list, &#039;err_redundant_parameters&#039; );&lt;br /&gt;
				if origin[k] == nil then&lt;br /&gt;
					origin[k] = &#039;&#039;;												-- Empty string, not nil&lt;br /&gt;
				end&lt;br /&gt;
			elseif list ~= nil then&lt;br /&gt;
				v, origin[k] = args[list], list;&lt;br /&gt;
			else&lt;br /&gt;
				-- maybe let through instead of raising an error?&lt;br /&gt;
				-- v, origin[k] = args[k], k;&lt;br /&gt;
				error( cfg.messages[&#039;unknown_argument_map&#039;] .. &#039;: &#039; .. k);&lt;br /&gt;
			end&lt;br /&gt;
			&lt;br /&gt;
			-- Empty strings, not nil;&lt;br /&gt;
			if v == nil then&lt;br /&gt;
				v = &#039;&#039;;&lt;br /&gt;
				origin[k] = &#039;&#039;;&lt;br /&gt;
			end&lt;br /&gt;
			&lt;br /&gt;
			tbl = rawset( tbl, k, v );&lt;br /&gt;
			return v;&lt;br /&gt;
		end,&lt;br /&gt;
	});&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; N O W R A P _ D A T E &amp;gt;-------------------------&lt;br /&gt;
&lt;br /&gt;
When date is YYYY-MM-DD format wrap in nowrap span: &amp;lt;span ...&amp;gt;YYYY-MM-DD&amp;lt;/span&amp;gt;.&lt;br /&gt;
When date is DD MMMM YYYY or is MMMM DD, YYYY then wrap in nowrap span:&lt;br /&gt;
&amp;lt;span ...&amp;gt;DD MMMM&amp;lt;/span&amp;gt; YYYY or &amp;lt;span ...&amp;gt;MMMM DD,&amp;lt;/span&amp;gt; YYYY&lt;br /&gt;
&lt;br /&gt;
DOES NOT yet support MMMM YYYY or any of the date ranges.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function nowrap_date (date)&lt;br /&gt;
	local cap = &#039;&#039;;&lt;br /&gt;
	local cap2 = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
	if date:match(&amp;quot;^%d%d%d%d%-%d%d%-%d%d$&amp;quot;) then&lt;br /&gt;
		date = utilities.substitute (cfg.presentation[&#039;nowrap1&#039;], date);&lt;br /&gt;
	&lt;br /&gt;
	elseif date:match(&amp;quot;^%a+%s*%d%d?,%s+%d%d%d%d$&amp;quot;) or date:match (&amp;quot;^%d%d?%s*%a+%s+%d%d%d%d$&amp;quot;) then&lt;br /&gt;
		cap, cap2 = string.match (date, &amp;quot;^(.*)%s+(%d%d%d%d)$&amp;quot;);&lt;br /&gt;
		date = utilities.substitute (cfg.presentation[&#039;nowrap2&#039;], {cap, cap2});&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return date;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S E T _ T I T L E T Y P E &amp;gt;---------------------&lt;br /&gt;
&lt;br /&gt;
This function sets default title types (equivalent to the citation including&lt;br /&gt;
|type=&amp;lt;default value&amp;gt;) for those templates that have defaults. Also handles the&lt;br /&gt;
special case where it is desirable to omit the title type from the rendered citation&lt;br /&gt;
(|type=none).&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function set_titletype (cite_class, title_type)&lt;br /&gt;
	if utilities.is_set (title_type) then&lt;br /&gt;
		if &#039;none&#039; == cfg.keywords_xlate[title_type] then&lt;br /&gt;
			title_type = &#039;&#039;;													-- if |type=none then type parameter not displayed&lt;br /&gt;
		end&lt;br /&gt;
		return title_type;														-- if |type= has been set to any other value use that value&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return cfg.title_types [cite_class] or &#039;&#039;;									-- set template&#039;s default title type; else empty string for concatenation&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S A F E _ J O I N &amp;gt;-----------------------------&lt;br /&gt;
&lt;br /&gt;
Joins a sequence of strings together while checking for duplicate separation characters.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function safe_join( tbl, duplicate_char )&lt;br /&gt;
	local f = {};																-- create a function table appropriate to type of &#039;duplicate character&#039;&lt;br /&gt;
		if 1 == #duplicate_char then											-- for single byte ASCII characters use the string library functions&lt;br /&gt;
			f.gsub = string.gsub&lt;br /&gt;
			f.match = string.match&lt;br /&gt;
			f.sub = string.sub&lt;br /&gt;
		else																	-- for multi-byte characters use the ustring library functions&lt;br /&gt;
			f.gsub = mw.ustring.gsub&lt;br /&gt;
			f.match = mw.ustring.match&lt;br /&gt;
			f.sub = mw.ustring.sub&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
	local str = &#039;&#039;;																-- the output string&lt;br /&gt;
	local comp = &#039;&#039;;															-- what does &#039;comp&#039; mean?&lt;br /&gt;
	local end_chr = &#039;&#039;;&lt;br /&gt;
	local trim;&lt;br /&gt;
	for _, value in ipairs( tbl ) do&lt;br /&gt;
		if value == nil then value = &#039;&#039;; end&lt;br /&gt;
		&lt;br /&gt;
		if str == &#039;&#039; then														-- if output string is empty&lt;br /&gt;
			str = value;														-- assign value to it (first time through the loop)&lt;br /&gt;
		elseif value ~= &#039;&#039; then&lt;br /&gt;
			if value:sub(1, 1) == &#039;&amp;lt;&#039; then										-- special case of values enclosed in spans and other markup.&lt;br /&gt;
				comp = value:gsub( &amp;quot;%b&amp;lt;&amp;gt;&amp;quot;, &amp;quot;&amp;quot; );								-- remove HTML markup (&amp;lt;span&amp;gt;string&amp;lt;/span&amp;gt; -&amp;gt; string)&lt;br /&gt;
			else&lt;br /&gt;
				comp = value;&lt;br /&gt;
			end&lt;br /&gt;
																				-- typically duplicate_char is sepc&lt;br /&gt;
			if f.sub(comp, 1, 1) == duplicate_char then							-- is first character same as duplicate_char? why test first character?&lt;br /&gt;
																				--   Because individual string segments often (always?) begin with terminal punct for the&lt;br /&gt;
																				--   preceding segment: &#039;First element&#039; .. &#039;sepc next element&#039; .. etc.?&lt;br /&gt;
				trim = false;&lt;br /&gt;
				end_chr = f.sub(str, -1, -1);									-- get the last character of the output string&lt;br /&gt;
				-- str = str .. &amp;quot;&amp;lt;HERE(enchr=&amp;quot; .. end_chr .. &amp;quot;)&amp;quot;				-- debug stuff?&lt;br /&gt;
				if end_chr == duplicate_char then								-- if same as separator&lt;br /&gt;
					str = f.sub(str, 1, -2);									-- remove it&lt;br /&gt;
				elseif end_chr == &amp;quot;&#039;&amp;quot; then										-- if it might be wiki-markup&lt;br /&gt;
					if f.sub(str, -3, -1) == duplicate_char .. &amp;quot;&#039;&#039;&amp;quot; then		-- if last three chars of str are sepc&#039;&#039; &lt;br /&gt;
						str = f.sub(str, 1, -4) .. &amp;quot;&#039;&#039;&amp;quot;;						-- remove them and add back &#039;&#039;&lt;br /&gt;
					elseif  f.sub(str, -5, -1) == duplicate_char .. &amp;quot;]]&#039;&#039;&amp;quot; then	-- if last five chars of str are sepc]]&#039;&#039; &lt;br /&gt;
						trim = true;											-- why? why do this and next differently from previous?&lt;br /&gt;
					elseif f.sub(str, -4, -1) == duplicate_char .. &amp;quot;]&#039;&#039;&amp;quot; then	-- if last four chars of str are sepc]&#039;&#039; &lt;br /&gt;
						trim = true;											-- same question&lt;br /&gt;
					end&lt;br /&gt;
				elseif end_chr == &amp;quot;]&amp;quot; then										-- if it might be wiki-markup&lt;br /&gt;
					if f.sub(str, -3, -1) == duplicate_char .. &amp;quot;]]&amp;quot; then		-- if last three chars of str are sepc]] wikilink &lt;br /&gt;
						trim = true;&lt;br /&gt;
					elseif f.sub(str, -3, -1) == duplicate_char .. &#039;&amp;quot;]&#039; then	-- if last three chars of str are sepc&amp;quot;] quoted external link &lt;br /&gt;
						trim = true;&lt;br /&gt;
					elseif  f.sub(str, -2, -1) == duplicate_char .. &amp;quot;]&amp;quot; then	-- if last two chars of str are sepc] external link&lt;br /&gt;
						trim = true;&lt;br /&gt;
					elseif f.sub(str, -4, -1) == duplicate_char .. &amp;quot;&#039;&#039;]&amp;quot; then	-- normal case when |url=something &amp;amp; |title=Title.&lt;br /&gt;
						trim = true;&lt;br /&gt;
					end&lt;br /&gt;
				elseif end_chr == &amp;quot; &amp;quot; then										-- if last char of output string is a space&lt;br /&gt;
					if f.sub(str, -2, -1) == duplicate_char .. &amp;quot; &amp;quot; then			-- if last two chars of str are &amp;lt;sepc&amp;gt;&amp;lt;space&amp;gt;&lt;br /&gt;
						str = f.sub(str, 1, -3);								-- remove them both&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
&lt;br /&gt;
				if trim then&lt;br /&gt;
					if value ~= comp then 										-- value does not equal comp when value contains HTML markup&lt;br /&gt;
						local dup2 = duplicate_char;&lt;br /&gt;
						if f.match(dup2, &amp;quot;%A&amp;quot; ) then dup2 = &amp;quot;%&amp;quot; .. dup2; end	-- if duplicate_char not a letter then escape it&lt;br /&gt;
						&lt;br /&gt;
						value = f.gsub(value, &amp;quot;(%b&amp;lt;&amp;gt;)&amp;quot; .. dup2, &amp;quot;%1&amp;quot;, 1 )		-- remove duplicate_char if it follows HTML markup&lt;br /&gt;
					else&lt;br /&gt;
						value = f.sub(value, 2, -1 );							-- remove duplicate_char when it is first character&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			str = str .. value; 												-- add it to the output string&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return str;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; I S _ S U F F I X &amp;gt;-----------------------------&lt;br /&gt;
&lt;br /&gt;
returns true if suffix is properly formed Jr, Sr, or ordinal in the range 1–9.&lt;br /&gt;
Puncutation not allowed.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function is_suffix (suffix)&lt;br /&gt;
	if utilities.in_array (suffix, {&#039;Jr&#039;, &#039;Sr&#039;, &#039;Jnr&#039;, &#039;Snr&#039;, &#039;1st&#039;, &#039;2nd&#039;, &#039;3rd&#039;}) or suffix:match (&#039;^%dth$&#039;) then&lt;br /&gt;
		return true;&lt;br /&gt;
	end&lt;br /&gt;
	return false;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------&amp;lt; I S _ G O O D _ V A N C _ N A M E &amp;gt;-------------------&lt;br /&gt;
&lt;br /&gt;
For Vancouver style, author/editor names are supposed to be rendered in Latin&lt;br /&gt;
(read ASCII) characters.  When a name uses characters that contain diacritical&lt;br /&gt;
marks, those characters are to be converted to the corresponding Latin&lt;br /&gt;
character. When a name is written using a non-Latin alphabet or logogram, that&lt;br /&gt;
name is to be transliterated into Latin characters. The module doesn&#039;t do this&lt;br /&gt;
so editors may/must.&lt;br /&gt;
&lt;br /&gt;
This test allows |first= and |last= names to contain any of the letters defined&lt;br /&gt;
in the four Unicode Latin character sets&lt;br /&gt;
	[http://www.unicode.org/charts/PDF/U0000.pdf C0 Controls and Basic Latin] 0041–005A, 0061–007A&lt;br /&gt;
	[http://www.unicode.org/charts/PDF/U0080.pdf C1 Controls and Latin-1 Supplement] 00C0–00D6, 00D8–00F6, 00F8–00FF&lt;br /&gt;
	[http://www.unicode.org/charts/PDF/U0100.pdf Latin Extended-A] 0100–017F&lt;br /&gt;
	[http://www.unicode.org/charts/PDF/U0180.pdf Latin Extended-B] 0180–01BF, 01C4–024F&lt;br /&gt;
&lt;br /&gt;
|lastn= also allowed to contain hyphens, spaces, and apostrophes.&lt;br /&gt;
	(http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35029/)&lt;br /&gt;
|firstn= also allowed to contain hyphens, spaces, apostrophes, and periods&lt;br /&gt;
&lt;br /&gt;
This original test:&lt;br /&gt;
	if nil == mw.ustring.find (last, &amp;quot;^[A-Za-zÀ-ÖØ-öø-ƿǄ-ɏ%-%s%&#039;]*$&amp;quot;)&lt;br /&gt;
	or nil == mw.ustring.find (first, &amp;quot;^[A-Za-zÀ-ÖØ-öø-ƿǄ-ɏ%-%s%&#039;%.]+[2-6%a]*$&amp;quot;) then&lt;br /&gt;
was written outside of the code editor and pasted here because the code editor&lt;br /&gt;
gets confused between character insertion point and cursor position. The test has&lt;br /&gt;
been rewritten to use decimal character escape sequence for the individual bytes&lt;br /&gt;
of the Unicode characters so that it is not necessary to use an external editor&lt;br /&gt;
to maintain this code.&lt;br /&gt;
&lt;br /&gt;
	\195\128-\195\150 – À-Ö (U+00C0–U+00D6 – C0 controls)&lt;br /&gt;
	\195\152-\195\182 – Ø-ö (U+00D8-U+00F6 – C0 controls)&lt;br /&gt;
	\195\184-\198\191 – ø-ƿ (U+00F8-U+01BF – C0 controls, Latin extended A &amp;amp; B)&lt;br /&gt;
	\199\132-\201\143 – Ǆ-ɏ (U+01C4-U+024F – Latin extended B)&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function is_good_vanc_name (last, first, suffix, position)&lt;br /&gt;
	if not suffix then&lt;br /&gt;
		if first:find (&#039;[,%s]&#039;) then											-- when there is a space or comma, might be first name/initials + generational suffix&lt;br /&gt;
			first = first:match (&#039;(.-)[,%s]+&#039;);									-- get name/initials&lt;br /&gt;
			suffix = first:match (&#039;[,%s]+(.+)$&#039;);								-- get generational suffix&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if utilities.is_set (suffix) then&lt;br /&gt;
		if not is_suffix (suffix) then&lt;br /&gt;
			add_vanc_error (cfg.err_msg_supl.suffix, position);&lt;br /&gt;
			return false;														-- not a name with an appropriate suffix&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if nil == mw.ustring.find (last, &amp;quot;^[A-Za-z\195\128-\195\150\195\152-\195\182\195\184-\198\191\199\132-\201\143%-%s%&#039;]*$&amp;quot;) or&lt;br /&gt;
		nil == mw.ustring.find (first, &amp;quot;^[A-Za-z\195\128-\195\150\195\152-\195\182\195\184-\198\191\199\132-\201\143%-%s%&#039;%.]*$&amp;quot;) then&lt;br /&gt;
			add_vanc_error (cfg.err_msg_supl[&#039;non-Latin char&#039;], position);&lt;br /&gt;
			return false;														-- not a string of Latin characters; Vancouver requires Romanization&lt;br /&gt;
	end;&lt;br /&gt;
	return true;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; R E D U C E _ T O _ I N I T I A L S &amp;gt;------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Attempts to convert names to initials in support of |name-list-style=vanc.  &lt;br /&gt;
&lt;br /&gt;
Names in |firstn= may be separated by spaces or hyphens, or for initials, a period.&lt;br /&gt;
See http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35062/.&lt;br /&gt;
&lt;br /&gt;
Vancouver style requires family rank designations (Jr, II, III, etc.) to be rendered&lt;br /&gt;
as Jr, 2nd, 3rd, etc.  See http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35085/.&lt;br /&gt;
This code only accepts and understands generational suffix in the Vancouver format&lt;br /&gt;
because Roman numerals look like, and can be mistaken for, initials.&lt;br /&gt;
&lt;br /&gt;
This function uses ustring functions because firstname initials may be any of the&lt;br /&gt;
Unicode Latin characters accepted by is_good_vanc_name ().&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function reduce_to_initials(first, position)&lt;br /&gt;
	local name, suffix = mw.ustring.match(first, &amp;quot;^(%u+) ([%dJS][%drndth]+)$&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	if not name then															-- if not initials and a suffix&lt;br /&gt;
		name = mw.ustring.match(first, &amp;quot;^(%u+)$&amp;quot;);								-- is it just initials?&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if name then																-- if first is initials with or without suffix&lt;br /&gt;
		if 3 &amp;gt; mw.ustring.len (name) then										-- if one or two initials&lt;br /&gt;
			if suffix then														-- if there is a suffix&lt;br /&gt;
				if is_suffix (suffix) then										-- is it legitimate?&lt;br /&gt;
					return first;												-- one or two initials and a valid suffix so nothing to do&lt;br /&gt;
				else&lt;br /&gt;
					add_vanc_error (cfg.err_msg_supl.suffix, position);			-- one or two initials with invalid suffix so error message&lt;br /&gt;
					return first;												-- and return first unmolested&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				return first;													-- one or two initials without suffix; nothing to do&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end																			-- if here then name has 3 or more uppercase letters so treat them as a word&lt;br /&gt;
&lt;br /&gt;
	local initials, names = {}, {};												-- tables to hold name parts and initials&lt;br /&gt;
	local i = 1;																-- counter for number of initials&lt;br /&gt;
&lt;br /&gt;
	names = mw.text.split (first, &#039;[%s,]+&#039;);									-- split into a table of names and possible suffix&lt;br /&gt;
&lt;br /&gt;
	while names[i] do															-- loop through the table&lt;br /&gt;
		if 1 &amp;lt; i and names[i]:match (&#039;[%dJS][%drndth]+%.?$&#039;) then				-- if not the first name, and looks like a suffix (may have trailing dot)&lt;br /&gt;
			names[i] = names[i]:gsub (&#039;%.&#039;, &#039;&#039;);								-- remove terminal dot if present&lt;br /&gt;
			if is_suffix (names[i]) then										-- if a legitimate suffix&lt;br /&gt;
				table.insert (initials, &#039; &#039; .. names[i]);						-- add a separator space, insert at end of initials table&lt;br /&gt;
				break;															-- and done because suffix must fall at the end of a name&lt;br /&gt;
			end																	-- no error message if not a suffix; possibly because of Romanization&lt;br /&gt;
		end&lt;br /&gt;
		if 3 &amp;gt; i then&lt;br /&gt;
			table.insert (initials, mw.ustring.sub(names[i], 1, 1));			-- insert the initial at end of initials table&lt;br /&gt;
		end&lt;br /&gt;
		i = i + 1;																-- bump the counter&lt;br /&gt;
	end&lt;br /&gt;
			&lt;br /&gt;
	return table.concat(initials)												-- Vancouver format does not include spaces.&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; L I S T _ P E O P L E &amp;gt;--------------------------&lt;br /&gt;
&lt;br /&gt;
Formats a list of people (authors, contributors, editors, interviewers, translators) &lt;br /&gt;
&lt;br /&gt;
names in the list will be linked when&lt;br /&gt;
	|&amp;lt;name&amp;gt;-link= has a value&lt;br /&gt;
	|&amp;lt;name&amp;gt;-mask- does NOT have a value; masked names are presumed to have been&lt;br /&gt;
		rendered previously so should have been linked there&lt;br /&gt;
&lt;br /&gt;
when |&amp;lt;name&amp;gt;-mask=0, the associated name is not rendered&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function list_people (control, people, etal)&lt;br /&gt;
	local sep;&lt;br /&gt;
	local namesep;&lt;br /&gt;
	local format = control.format;&lt;br /&gt;
	local maximum = control.maximum;&lt;br /&gt;
	local name_list = {};&lt;br /&gt;
&lt;br /&gt;
	if &#039;vanc&#039; == format then													-- Vancouver-like name styling?&lt;br /&gt;
		sep = cfg.presentation[&#039;sep_nl_vanc&#039;];									-- name-list separator between names is a comma&lt;br /&gt;
		namesep = cfg.presentation[&#039;sep_name_vanc&#039;];							-- last/first separator is a space&lt;br /&gt;
	else&lt;br /&gt;
		sep = cfg.presentation[&#039;sep_nl&#039;];										-- name-list separator between names is a semicolon&lt;br /&gt;
		namesep = cfg.presentation[&#039;sep_name&#039;];									-- last/first separator is &amp;lt;comma&amp;gt;&amp;lt;space&amp;gt;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if sep:sub (-1, -1) ~= &amp;quot; &amp;quot; then sep = sep .. &amp;quot; &amp;quot; end&lt;br /&gt;
	if utilities.is_set (maximum) and maximum &amp;lt; 1 then return &amp;quot;&amp;quot;, 0; end		-- returned 0 is for EditorCount; not used for other names&lt;br /&gt;
	&lt;br /&gt;
	for i, person in ipairs (people) do&lt;br /&gt;
		if utilities.is_set (person.last) then&lt;br /&gt;
			local mask = person.mask;&lt;br /&gt;
			local one;&lt;br /&gt;
			local sep_one = sep;&lt;br /&gt;
&lt;br /&gt;
			if utilities.is_set (maximum) and i &amp;gt; maximum then&lt;br /&gt;
				etal = true;&lt;br /&gt;
				break;&lt;br /&gt;
			end&lt;br /&gt;
			&lt;br /&gt;
			if mask then&lt;br /&gt;
				local n = tonumber (mask);										-- convert to a number if it can be converted; nil else&lt;br /&gt;
				if n then&lt;br /&gt;
					one = 0 ~= n and string.rep(&amp;quot;&amp;amp;mdash;&amp;quot;, n) or nil;			-- make a string of (n &amp;gt; 0) mdashes, nil else, to replace name&lt;br /&gt;
					person.link = nil;											-- don&#039;t create link to name if name is replaces with mdash string or has been set nil&lt;br /&gt;
				else&lt;br /&gt;
					one = mask;													-- replace name with mask text (must include name-list separator)&lt;br /&gt;
					sep_one = &amp;quot; &amp;quot;;												-- modify name-list separator&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				one = person.last;												-- get surname&lt;br /&gt;
				local first = person.first										-- get given name&lt;br /&gt;
				if utilities.is_set (first) then&lt;br /&gt;
					if (&amp;quot;vanc&amp;quot; == format) then									-- if Vancouver format&lt;br /&gt;
						one = one:gsub (&#039;%.&#039;, &#039;&#039;);								-- remove periods from surnames (http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35029/)&lt;br /&gt;
						if not person.corporate and is_good_vanc_name (one, first, nil, i) then		-- and name is all Latin characters; corporate authors not tested&lt;br /&gt;
							first = reduce_to_initials (first, i);				-- attempt to convert first name(s) to initials&lt;br /&gt;
						end&lt;br /&gt;
					end&lt;br /&gt;
					one = one .. namesep .. first;&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			if utilities.is_set (person.link) then&lt;br /&gt;
				one = utilities.make_wikilink (person.link, one);				-- link author/editor&lt;br /&gt;
			end&lt;br /&gt;
			if one then															-- if &amp;lt;one&amp;gt; has a value (name, mdash replacement, or mask text replacement)&lt;br /&gt;
				table.insert (name_list, one);									-- add it to the list of names&lt;br /&gt;
				table.insert (name_list, sep_one);								-- add the proper name-list separator&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local count = #name_list / 2;												-- (number of names + number of separators) divided by 2&lt;br /&gt;
	if 0 &amp;lt; count then &lt;br /&gt;
		if 1 &amp;lt; count and not etal then&lt;br /&gt;
			if &#039;amp&#039; == format then&lt;br /&gt;
				name_list[#name_list-2] = &amp;quot; &amp;amp; &amp;quot;;								-- replace last separator with ampersand text&lt;br /&gt;
			elseif &#039;and&#039; == format then&lt;br /&gt;
				if 2 == count then&lt;br /&gt;
					name_list[#name_list-2] = cfg.presentation.sep_nl_and;		-- replace last separator with &#039;and&#039; text&lt;br /&gt;
				else&lt;br /&gt;
					name_list[#name_list-2] = cfg.presentation.sep_nl_end;		-- replace last separator with &#039;(sep) and&#039; text&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		name_list[#name_list] = nil;											-- erase the last separator&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local result = table.concat (name_list);									-- construct list&lt;br /&gt;
	if etal and utilities.is_set (result) then									-- etal may be set by |display-authors=etal but we might not have a last-first list&lt;br /&gt;
		result = result .. sep .. &#039; &#039; .. cfg.messages[&#039;et al&#039;];					-- we&#039;ve got a last-first list and etal so add et al.&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return result, count;														-- return name-list string and count of number of names (count used for editor names only)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------&amp;lt; M A K E _ C I T E R E F _ I D &amp;gt;-----------------------&lt;br /&gt;
&lt;br /&gt;
Generates a CITEREF anchor ID if we have at least one name or a date.  Otherwise&lt;br /&gt;
returns an empty string.&lt;br /&gt;
&lt;br /&gt;
namelist is one of the contributor-, author-, or editor-name lists chosen in that&lt;br /&gt;
order.  year is Year or anchor_year.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function make_citeref_id (namelist, year)&lt;br /&gt;
	local names={};							-- a table for the one to four names and year&lt;br /&gt;
	for i,v in ipairs (namelist) do			-- loop through the list and take up to the first four last names&lt;br /&gt;
		names[i] = v.last&lt;br /&gt;
		if i == 4 then break end			-- if four then done&lt;br /&gt;
	end&lt;br /&gt;
	table.insert (names, year);				-- add the year at the end&lt;br /&gt;
	local id = table.concat(names);			-- concatenate names and year for CITEREF id&lt;br /&gt;
	if utilities.is_set (id) then			-- if concatenation is not an empty string&lt;br /&gt;
		return &amp;quot;CITEREF&amp;quot; .. id;				-- add the CITEREF portion&lt;br /&gt;
	else&lt;br /&gt;
		return &#039;&#039;;							-- return an empty string; no reason to include CITEREF id in this citation&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; C I T E _ C L A S S _A T T R I B U T E _M A K E &amp;gt;------------------------------&lt;br /&gt;
&lt;br /&gt;
construct &amp;lt;cite&amp;gt; tag class attribute for this citation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cite_class&amp;gt; – config.CitationClass from calling template&lt;br /&gt;
&amp;lt;mode&amp;gt; – value from |mode= parameter&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function cite_class_attribute_make (cite_class, mode)&lt;br /&gt;
	local class_t = {};&lt;br /&gt;
	table.insert (class_t, &#039;citation&#039;);											-- required for blue highlight&lt;br /&gt;
	if &#039;citation&#039; ~= cite_class then&lt;br /&gt;
		table.insert (class_t, cite_class);										-- identify this template for user css&lt;br /&gt;
		table.insert (class_t, utilities.is_set (mode) and mode or &#039;cs1&#039;);		-- identify the citation style for user css or javascript&lt;br /&gt;
	else&lt;br /&gt;
		table.insert (class_t, utilities.is_set (mode) and mode or &#039;cs2&#039;);		-- identify the citation style for user css or javascript&lt;br /&gt;
	end&lt;br /&gt;
	for _, prop_key in ipairs (z.prop_keys_t) do&lt;br /&gt;
		table.insert (class_t, prop_key);										-- identify various properties for user css or javascript&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return table.concat (class_t, &#039; &#039;);											-- make a big string and done&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[---------------------&amp;lt; N A M E _ H A S _ E T A L &amp;gt;--------------------------&lt;br /&gt;
&lt;br /&gt;
Evaluates the content of name parameters (author, editor, etc.) for variations on&lt;br /&gt;
the theme of et al.  If found, the et al. is removed, a flag is set to true and&lt;br /&gt;
the function returns the modified name and the flag.&lt;br /&gt;
&lt;br /&gt;
This function never sets the flag to false but returns its previous state because&lt;br /&gt;
it may have been set by previous passes through this function or by the associated&lt;br /&gt;
|display-&amp;lt;names&amp;gt;=etal parameter&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function name_has_etal (name, etal, nocat, param)&lt;br /&gt;
&lt;br /&gt;
	if utilities.is_set (name) then												-- name can be nil in which case just return&lt;br /&gt;
		local patterns = cfg.et_al_patterns; 									-- get patterns from configuration&lt;br /&gt;
		&lt;br /&gt;
		for _, pattern in ipairs (patterns) do									-- loop through all of the patterns&lt;br /&gt;
			if name:match (pattern) then										-- if this &#039;et al&#039; pattern is found in name&lt;br /&gt;
				name = name:gsub (pattern, &#039;&#039;);									-- remove the offending text&lt;br /&gt;
				etal = true;													-- set flag (may have been set previously here or by |display-&amp;lt;names&amp;gt;=etal)&lt;br /&gt;
				if not nocat then												-- no categorization for |vauthors=&lt;br /&gt;
					utilities.set_message (&#039;err_etal&#039;, {param});				-- and set an error if not added&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return name, etal;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[---------------------&amp;lt; N A M E _ I S _ N U M E R I C &amp;gt;----------------------&lt;br /&gt;
&lt;br /&gt;
Add maint cat when name parameter value does not contain letters.  Does not catch&lt;br /&gt;
mixed alphanumeric names so |last=A. Green (1922-1987) does not get caught in the&lt;br /&gt;
current version of this test but |first=(1888) is caught.&lt;br /&gt;
&lt;br /&gt;
returns nothing&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function name_is_numeric (name, list_name)&lt;br /&gt;
	if utilities.is_set (name) then&lt;br /&gt;
		if mw.ustring.match (name, &#039;^[%A]+$&#039;) then								-- when name does not contain any letters&lt;br /&gt;
			utilities.set_message (&#039;maint_numeric_names&#039;, cfg.special_case_translation [list_name]);	-- add a maint cat for this template&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[-----------------&amp;lt; N A M E _ H A S _ M U L T _ N A M E S &amp;gt;------------------&lt;br /&gt;
&lt;br /&gt;
Evaluates the content of last/surname (authors etc.) parameters for multiple names.&lt;br /&gt;
Multiple names are indicated if there is more than one comma or any &amp;quot;unescaped&amp;quot;&lt;br /&gt;
semicolons. Escaped semicolons are ones used as part of selected HTML entities.&lt;br /&gt;
If the condition is met, the function adds the multiple name maintenance category.&lt;br /&gt;
&lt;br /&gt;
returns nothing&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function name_has_mult_names (name, list_name)&lt;br /&gt;
	local _, commas, semicolons, nbsps;&lt;br /&gt;
	if utilities.is_set (name) then&lt;br /&gt;
		_, commas = name:gsub (&#039;,&#039;, &#039;&#039;);										-- count the number of commas&lt;br /&gt;
		_, semicolons = name:gsub (&#039;;&#039;, &#039;&#039;);									-- count the number of semicolons&lt;br /&gt;
		-- nbsps probably should be its own separate count rather than merged in&lt;br /&gt;
		-- some way with semicolons because Lua patterns do not support the&lt;br /&gt;
		-- grouping operator that regex does, which means there is no way to add&lt;br /&gt;
		-- more entities to escape except by adding more counts with the new&lt;br /&gt;
		-- entities&lt;br /&gt;
		_, nbsps = name:gsub (&#039;&amp;amp;nbsp;&#039;,&#039;&#039;);										-- count nbsps&lt;br /&gt;
		&lt;br /&gt;
		-- There is exactly 1 semicolon per &amp;amp;nbsp; entity, so subtract nbsps&lt;br /&gt;
		-- from semicolons to &#039;escape&#039; them. If additional entities are added,&lt;br /&gt;
		-- they also can be subtracted.&lt;br /&gt;
		if 1 &amp;lt; commas or 0 &amp;lt; (semicolons - nbsps) then&lt;br /&gt;
			utilities.set_message (&#039;maint_mult_names&#039;, cfg.special_case_translation [list_name]);	-- add a maint message&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[=[-------------------------&amp;lt; I S _ G E N E R I C &amp;gt;----------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Compares values assigned to various parameters according to the string provided as &amp;lt;item&amp;gt; in the function call.&lt;br /&gt;
&amp;lt;item&amp;gt; can have on of two values:&lt;br /&gt;
	&#039;generic_names&#039; – for name-holding parameters: |last=, |first=, |editor-last=, etc&lt;br /&gt;
	&#039;generic_titles&#039; – for |title=&lt;br /&gt;
&lt;br /&gt;
There are two types of generic tests.  The &#039;accept&#039; tests look for a pattern that should not be rejected by the&lt;br /&gt;
&#039;reject&#039; test.  For example,&lt;br /&gt;
	|author=[[John Smith (author)|Smith, John]]&lt;br /&gt;
would be rejected by the &#039;author&#039; reject test.  But piped wikilinks with &#039;author&#039; disambiguation should not be&lt;br /&gt;
rejected so the &#039;accept&#039; test prevents that from happening.  Accept tests are always performed before reject&lt;br /&gt;
tests.&lt;br /&gt;
&lt;br /&gt;
Each of the &#039;accept&#039; and &#039;reject&#039; sequence tables hold tables for en.wiki ([&#039;en&#039;]) and local.wiki ([&#039;local&#039;])&lt;br /&gt;
that each can hold a test sequence table  The sequence table holds, at index [1], a test pattern, and, at index&lt;br /&gt;
[2], a boolean control value.  The control value tells string.find() or mw.ustring.find() to do plain-text search (true)&lt;br /&gt;
or a pattern search (false).  The intent of all this complexity is to make these searches as fast as possible so&lt;br /&gt;
that we don&#039;t run out of processing time on very large articles.&lt;br /&gt;
&lt;br /&gt;
Returns&lt;br /&gt;
	true when a reject test finds the pattern or string&lt;br /&gt;
	false when an accept test finds the pattern or string&lt;br /&gt;
	nil else&lt;br /&gt;
&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local function is_generic (item, value, wiki)&lt;br /&gt;
	local test_val;&lt;br /&gt;
	local str_lower = {															-- use string.lower() for en.wiki ([&#039;en&#039;]) and use mw.ustring.lower() or local.wiki ([&#039;local&#039;])&lt;br /&gt;
		[&#039;en&#039;] = string.lower,&lt;br /&gt;
		[&#039;local&#039;] = mw.ustring.lower,&lt;br /&gt;
		}&lt;br /&gt;
	local str_find = {															-- use string.find() for en.wiki ([&#039;en&#039;]) and use mw.ustring.find() or local.wiki ([&#039;local&#039;])&lt;br /&gt;
		[&#039;en&#039;] = string.find,&lt;br /&gt;
		[&#039;local&#039;] = mw.ustring.find,&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
	local function test (val, test_t, wiki)										-- local function to do the testing; &amp;lt;wiki&amp;gt; selects lower() and find() functions&lt;br /&gt;
		val = test_t[2] and str_lower[wiki](value) or val;						-- when &amp;lt;test_t[2]&amp;gt; set to &#039;true&#039;, plaintext search using lowercase value&lt;br /&gt;
		return str_find[wiki] (val, test_t[1], 1, test_t[2]);					-- return nil when not found or matched&lt;br /&gt;
	end&lt;br /&gt;
		&lt;br /&gt;
	local test_types_t = {&#039;accept&#039;, &#039;reject&#039;};									-- test accept patterns first, then reject patterns&lt;br /&gt;
	local wikis_t = {&#039;en&#039;, &#039;local&#039;};											-- do tests for each of these keys; en.wiki first, local.wiki second&lt;br /&gt;
&lt;br /&gt;
	for _, test_type in ipairs (test_types_t) do								-- for each test type&lt;br /&gt;
		for _, generic_value in pairs (cfg.special_case_translation[item][test_type]) do	-- spin through the list of generic value fragments to accept or reject&lt;br /&gt;
			for _, wiki in ipairs (wikis_t) do&lt;br /&gt;
				if generic_value[wiki] then&lt;br /&gt;
					if test (value, generic_value[wiki], wiki) then				-- go do the test&lt;br /&gt;
						return (&#039;reject&#039; == test_type);							-- param value rejected, return true; false else&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; N A M E _ I S _ G E N E R I C &amp;gt;------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
calls is_generic() to determine if &amp;lt;name&amp;gt; is a &#039;generic name&#039; listed in cfg.generic_names; &amp;lt;name_alias&amp;gt; is the&lt;br /&gt;
parameter name used in error messaging&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function name_is_generic (name, name_alias)&lt;br /&gt;
	if not added_generic_name_errs  and is_generic (&#039;generic_names&#039;, name) then&lt;br /&gt;
		utilities.set_message (&#039;err_generic_name&#039;, name_alias);					-- set an error message&lt;br /&gt;
		added_generic_name_errs = true;&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; N A M E _ C H E C K S &amp;gt;--------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
This function calls various name checking functions used to validate the content of the various name-holding parameters.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function name_checks (last, first, list_name, last_alias, first_alias)&lt;br /&gt;
	local accept_name;&lt;br /&gt;
&lt;br /&gt;
	if utilities.is_set (last) then&lt;br /&gt;
		last, accept_name = utilities.has_accept_as_written (last);				-- remove accept-this-as-written markup when it wraps all of &amp;lt;last&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		if not accept_name then													-- &amp;lt;last&amp;gt; not wrapped in accept-as-written markup&lt;br /&gt;
			name_has_mult_names (last, list_name);								-- check for multiple names in the parameter (last only)&lt;br /&gt;
			name_is_numeric (last, list_name);									-- check for names that are composed of digits and punctuation&lt;br /&gt;
			name_is_generic (last, last_alias);									-- check for names found in the generic names list&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if utilities.is_set (first) then&lt;br /&gt;
		first, accept_name = utilities.has_accept_as_written (first);			-- remove accept-this-as-written markup when it wraps all of &amp;lt;first&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		if not accept_name then													-- &amp;lt;first&amp;gt; not wrapped in accept-as-written markup&lt;br /&gt;
			name_is_numeric (first, list_name);									-- check for names that are composed of digits and punctuation&lt;br /&gt;
			name_is_generic (first, first_alias);								-- check for names found in the generic names list&lt;br /&gt;
		end&lt;br /&gt;
		local wl_type, D = utilities.is_wikilink (first);&lt;br /&gt;
		if 0 ~= wl_type then&lt;br /&gt;
			first = D;&lt;br /&gt;
			utilities.set_message (&#039;err_bad_paramlink&#039;, first_alias);&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return last, first;															-- done&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[----------------------&amp;lt; E X T R A C T _ N A M E S &amp;gt;-------------------------&lt;br /&gt;
&lt;br /&gt;
Gets name list from the input arguments&lt;br /&gt;
&lt;br /&gt;
Searches through args in sequential order to find |lastn= and |firstn= parameters&lt;br /&gt;
(or their aliases), and their matching link and mask parameters. Stops searching&lt;br /&gt;
when both |lastn= and |firstn= are not found in args after two sequential attempts:&lt;br /&gt;
found |last1=, |last2=, and |last3= but doesn&#039;t find |last4= and |last5= then the&lt;br /&gt;
search is done.&lt;br /&gt;
&lt;br /&gt;
This function emits an error message when there is a |firstn= without a matching&lt;br /&gt;
|lastn=.  When there are &#039;holes&#039; in the list of last names, |last1= and |last3=&lt;br /&gt;
are present but |last2= is missing, an error message is emitted. |lastn= is not&lt;br /&gt;
required to have a matching |firstn=.&lt;br /&gt;
&lt;br /&gt;
When an author or editor parameter contains some form of &#039;et al.&#039;, the &#039;et al.&#039;&lt;br /&gt;
is stripped from the parameter and a flag (etal) returned that will cause list_people()&lt;br /&gt;
to add the static &#039;et al.&#039; text from Module:Citation/CS1/Configuration.  This keeps&lt;br /&gt;
&#039;et al.&#039; out of the template&#039;s metadata.  When this occurs, an error is emitted.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function extract_names(args, list_name)&lt;br /&gt;
	local names = {};															-- table of names&lt;br /&gt;
	local last;																	-- individual name components&lt;br /&gt;
	local first;&lt;br /&gt;
	local link;&lt;br /&gt;
	local mask;&lt;br /&gt;
	local i = 1;																-- loop counter/indexer&lt;br /&gt;
	local n = 1;																-- output table indexer&lt;br /&gt;
	local count = 0;															-- used to count the number of times we haven&#039;t found a |last= (or alias for authors, |editor-last or alias for editors)&lt;br /&gt;
	local etal = false;															-- return value set to true when we find some form of et al. in an author parameter&lt;br /&gt;
&lt;br /&gt;
	local last_alias, first_alias, link_alias;									-- selected parameter aliases used in error messaging&lt;br /&gt;
	while true do&lt;br /&gt;
		last, last_alias = utilities.select_one ( args, cfg.aliases[list_name .. &#039;-Last&#039;], &#039;err_redundant_parameters&#039;, i );		-- search through args for name components beginning at 1&lt;br /&gt;
		first, first_alias = utilities.select_one ( args, cfg.aliases[list_name .. &#039;-First&#039;], &#039;err_redundant_parameters&#039;, i );&lt;br /&gt;
		link, link_alias = utilities.select_one ( args, cfg.aliases[list_name .. &#039;-Link&#039;], &#039;err_redundant_parameters&#039;, i );&lt;br /&gt;
		mask = utilities.select_one ( args, cfg.aliases[list_name .. &#039;-Mask&#039;], &#039;err_redundant_parameters&#039;, i );&lt;br /&gt;
&lt;br /&gt;
		last, etal = name_has_etal (last, etal, false, last_alias);				-- find and remove variations on et al.&lt;br /&gt;
		first, etal = name_has_etal (first, etal, false, first_alias);			-- find and remove variations on et al.&lt;br /&gt;
		last, first = name_checks (last, first, list_name, last_alias, first_alias);						-- multiple names, extraneous annotation, etc. checks&lt;br /&gt;
&lt;br /&gt;
		if first and not last then												-- if there is a firstn without a matching lastn&lt;br /&gt;
			local alias = first_alias:find (&#039;given&#039;, 1, true) and &#039;given&#039; or &#039;first&#039;;	-- get first or given form of the alias&lt;br /&gt;
			utilities.set_message (&#039;err_first_missing_last&#039;, {&lt;br /&gt;
				first_alias,													-- param name of alias missing its mate&lt;br /&gt;
				first_alias:gsub (alias, {[&#039;first&#039;] = &#039;last&#039;, [&#039;given&#039;] = &#039;surname&#039;}),	-- make param name appropriate to the alias form&lt;br /&gt;
				});																-- add this error message&lt;br /&gt;
		elseif not first and not last then										-- if both firstn and lastn aren&#039;t found, are we done?&lt;br /&gt;
			count = count + 1;													-- number of times we haven&#039;t found last and first&lt;br /&gt;
			if 2 &amp;lt;= count then													-- two missing names and we give up&lt;br /&gt;
				break;															-- normal exit or there is a two-name hole in the list; can&#039;t tell which&lt;br /&gt;
			end&lt;br /&gt;
		else																	-- we have last with or without a first&lt;br /&gt;
			local result;&lt;br /&gt;
			link = link_title_ok (link, link_alias, last, last_alias);			-- check for improper wiki-markup&lt;br /&gt;
&lt;br /&gt;
			if first then&lt;br /&gt;
				link = link_title_ok (link, link_alias, first, first_alias);	-- check for improper wiki-markup&lt;br /&gt;
			end&lt;br /&gt;
&lt;br /&gt;
			names[n] = {last = last, first = first, link = link, mask = mask, corporate = false};	-- add this name to our names list (corporate for |vauthors= only)&lt;br /&gt;
			n = n + 1;															-- point to next location in the names table&lt;br /&gt;
			if 1 == count then													-- if the previous name was missing&lt;br /&gt;
				utilities.set_message (&#039;err_missing_name&#039;, {list_name:match (&amp;quot;(%w+)List&amp;quot;):lower(), i - 1});	-- add this error message&lt;br /&gt;
			end&lt;br /&gt;
			count = 0;															-- reset the counter, we&#039;re looking for two consecutive missing names&lt;br /&gt;
		end&lt;br /&gt;
		i = i + 1;																-- point to next args location&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return names, etal;															-- all done, return our list of names and the etal flag&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; N A M E _ T A G _ G E T &amp;gt;------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
attempt to decode |language=&amp;lt;lang_param&amp;gt; and return language name and matching tag; nil else.&lt;br /&gt;
&lt;br /&gt;
This function looks for:&lt;br /&gt;
	&amp;lt;lang_param&amp;gt; as a tag in cfg.lang_code_remap{}&lt;br /&gt;
	&amp;lt;lang_param&amp;gt; as a name in cfg.lang_name_remap{}&lt;br /&gt;
	&lt;br /&gt;
	&amp;lt;lang_param&amp;gt; as a name in cfg.mw_languages_by_name_t&lt;br /&gt;
	&amp;lt;lang_param&amp;gt; as a tag in cfg.mw_languages_by_tag_t&lt;br /&gt;
when those fail, presume that &amp;lt;lang_param&amp;gt; is an IETF-like tag that MediaWiki does not recognize.  Strip all&lt;br /&gt;
script, region, variant, whatever subtags from &amp;lt;lang_param&amp;gt; to leave just a two or three character language tag&lt;br /&gt;
and look for the new &amp;lt;lang_param&amp;gt; in cfg.mw_languages_by_tag_t{}&lt;br /&gt;
&lt;br /&gt;
on success, returns name (in properly capitalized form) and matching tag (in lowercase); on failure returns nil&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function name_tag_get (lang_param)&lt;br /&gt;
	local lang_param_lc = mw.ustring.lower (lang_param);						-- use lowercase as an index into the various tables&lt;br /&gt;
	local name;&lt;br /&gt;
	local tag;&lt;br /&gt;
&lt;br /&gt;
	name = cfg.lang_code_remap[lang_param_lc];									-- assume &amp;lt;lang_param_lc&amp;gt; is a tag; attempt to get remapped language name &lt;br /&gt;
	if name then																-- when &amp;lt;name&amp;gt;, &amp;lt;lang_param&amp;gt; is a tag for a remapped language name&lt;br /&gt;
		return name, lang_param_lc;												-- so return &amp;lt;name&amp;gt; from remap and &amp;lt;lang_param_lc&amp;gt;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	tag = lang_param_lc:match (&#039;^(%a%a%a?)%-.*&#039;);								-- still assuming that &amp;lt;lang_param_lc&amp;gt; is a tag; strip script, region, variant subtags&lt;br /&gt;
	name = cfg.lang_code_remap[tag];											-- attempt to get remapped language name with language subtag only&lt;br /&gt;
	if name then																-- when &amp;lt;name&amp;gt;, &amp;lt;tag&amp;gt; is a tag for a remapped language name&lt;br /&gt;
		return name, tag;														-- so return &amp;lt;name&amp;gt; from remap and &amp;lt;tag&amp;gt;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if cfg.lang_name_remap[lang_param_lc] then									-- not a tag, assume &amp;lt;lang_param_lc&amp;gt; is a name; attempt to get remapped language tag &lt;br /&gt;
		return cfg.lang_name_remap[lang_param_lc][1], cfg.lang_name_remap[lang_param_lc][2];	-- for this &amp;lt;lang_param_lc&amp;gt;, return a (possibly) new name and appropriate tag&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	tag = cfg.mw_languages_by_name_t[lang_param_lc];							-- assume that &amp;lt;lang_param_lc&amp;gt; is a language name; attempt to get its matching tag&lt;br /&gt;
	&lt;br /&gt;
	if tag then&lt;br /&gt;
		return cfg.mw_languages_by_tag_t[tag], tag;								-- &amp;lt;lang_param_lc&amp;gt; is a name so return the name from the table and &amp;lt;tag&amp;gt;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	name = cfg.mw_languages_by_tag_t[lang_param_lc];							-- assume that &amp;lt;lang_param_lc&amp;gt; is a tag; attempt to get its matching language name&lt;br /&gt;
	&lt;br /&gt;
	if name then&lt;br /&gt;
		return name, lang_param_lc;												-- &amp;lt;lang_param_lc&amp;gt; is a tag so return it and &amp;lt;name&amp;gt;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	tag = lang_param_lc:match (&#039;^(%a%a%a?)%-.*&#039;);								-- is &amp;lt;lang_param_lc&amp;gt; an IETF-like tag that MediaWiki doesn&#039;t recognize? &amp;lt;tag&amp;gt; gets the language subtag; nil else&lt;br /&gt;
&lt;br /&gt;
	if tag then&lt;br /&gt;
		name = cfg.mw_languages_by_tag_t[tag];									-- attempt to get a language name using the shortened &amp;lt;tag&amp;gt;&lt;br /&gt;
		if name then&lt;br /&gt;
			return name, tag;													-- &amp;lt;lang_param_lc&amp;gt; is an unrecognized IETF-like tag so return &amp;lt;name&amp;gt; and language subtag&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[-------------------&amp;lt; L A N G U A G E _ P A R A M E T E R &amp;gt;------------------&lt;br /&gt;
&lt;br /&gt;
Gets language name from a provided two- or three-character ISO 639 code.  If a code&lt;br /&gt;
is recognized by MediaWiki, use the returned name; if not, then use the value that&lt;br /&gt;
was provided with the language parameter.&lt;br /&gt;
&lt;br /&gt;
When |language= contains a recognized language (either code or name), the page is&lt;br /&gt;
assigned to the category for that code: Category:Norwegian-language sources (no).&lt;br /&gt;
For valid three-character code languages, the page is assigned to the single category&lt;br /&gt;
for &#039;639-2&#039; codes: Category:CS1 ISO 639-2 language sources.&lt;br /&gt;
&lt;br /&gt;
Languages that are the same as the local wiki are not categorized.  MediaWiki does&lt;br /&gt;
not recognize three-character equivalents of two-character codes: code &#039;ar&#039; is&lt;br /&gt;
recognized but code &#039;ara&#039; is not.&lt;br /&gt;
&lt;br /&gt;
This function supports multiple languages in the form |language=nb, French, th&lt;br /&gt;
where the language names or codes are separated from each other by commas with&lt;br /&gt;
optional space characters.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function language_parameter (lang)&lt;br /&gt;
	local tag;																	-- some form of IETF-like language tag; language subtag with optional region, sript, vatiant, etc subtags&lt;br /&gt;
	local lang_subtag;															-- ve populates |language= with mostly unecessary region subtags the MediaWiki does not recognize; this is the base language subtag&lt;br /&gt;
	local name;																	-- the language name&lt;br /&gt;
	local language_list = {};													-- table of language names to be rendered&lt;br /&gt;
	local names_t = {};															-- table made from the value assigned to |language=&lt;br /&gt;
&lt;br /&gt;
	local this_wiki_name = mw.language.fetchLanguageName (cfg.this_wiki_code, cfg.this_wiki_code);	-- get this wiki&#039;s language name&lt;br /&gt;
&lt;br /&gt;
	names_t = mw.text.split (lang, &#039;%s*,%s*&#039;);									-- names should be a comma separated list&lt;br /&gt;
&lt;br /&gt;
	for _, lang in ipairs (names_t) do											-- reuse lang here because we don&#039;t yet know if lang is a language name or a language tag&lt;br /&gt;
		name, tag = name_tag_get (lang);										-- attempt to get name/tag pair for &amp;lt;lang&amp;gt;; &amp;lt;name&amp;gt; has proper capitalization; &amp;lt;tag&amp;gt; is lowercase&lt;br /&gt;
&lt;br /&gt;
		if utilities.is_set (tag) then&lt;br /&gt;
			lang_subtag = tag:gsub (&#039;^(%a%a%a?)%-.*&#039;, &#039;%1&#039;);					-- for categorization, strip any IETF-like tags from language tag&lt;br /&gt;
&lt;br /&gt;
			if cfg.this_wiki_code ~= lang_subtag then							-- when the language is not the same as this wiki&#039;s language&lt;br /&gt;
				if 2 == lang_subtag:len() then									-- and is a two-character tag&lt;br /&gt;
--					utilities.add_prop_cat (&#039;foreign-lang-source&#039;, {name, lang_subtag}, lang_subtag);		-- categorize it; tag appended to allow for multiple language categorization&lt;br /&gt;
					utilities.add_prop_cat (&#039;foreign-lang-source&#039;, {name, tag}, lang_subtag);		-- categorize it; tag appended to allow for multiple language categorization&lt;br /&gt;
				else															-- or is a recognized language (but has a three-character tag)&lt;br /&gt;
					utilities.add_prop_cat (&#039;foreign-lang-source-2&#039;, {lang_subtag}, lang_subtag);			-- categorize it differently TODO: support multiple three-character tag categories per cs1|2 template?&lt;br /&gt;
				end&lt;br /&gt;
			elseif cfg.local_lang_cat_enable then								-- when the language and this wiki&#039;s language are the same and categorization is enabled&lt;br /&gt;
				utilities.add_prop_cat (&#039;local-lang-source&#039;, {name, lang_subtag});		-- categorize it&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			name = lang;														-- return whatever &amp;lt;lang&amp;gt; has so that we show something&lt;br /&gt;
			utilities.set_message (&#039;maint_unknown_lang&#039;);						-- add maint category if not already added&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		table.insert (language_list, name);&lt;br /&gt;
		name = &#039;&#039;;																-- so we can reuse it&lt;br /&gt;
	end&lt;br /&gt;
 &lt;br /&gt;
	name = utilities.make_sep_list (#language_list, language_list);&lt;br /&gt;
	if (1 == #language_list) and (lang_subtag == cfg.this_wiki_code) then		-- when only one language, find lang name in this wiki lang name; for |language=en-us, &#039;English&#039; in &#039;American English&#039;&lt;br /&gt;
		return &#039;&#039;;																-- if one language and that language is this wiki&#039;s return an empty string (no annotation)&lt;br /&gt;
	end&lt;br /&gt;
	return (&amp;quot; &amp;quot; .. wrap_msg (&#039;language&#039;, name));								-- otherwise wrap with &#039;(in ...)&#039;&lt;br /&gt;
	--[[ TODO: should only return blank or name rather than full list&lt;br /&gt;
	so we can clean up the bunched parenthetical elements Language, Type, Format&lt;br /&gt;
	]]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[-----------------------&amp;lt; S E T _ C S _ S T Y L E &amp;gt;--------------------------&lt;br /&gt;
&lt;br /&gt;
Gets the default CS style configuration for the given mode.&lt;br /&gt;
Returns default separator and either postscript as passed in or the default.&lt;br /&gt;
In CS1, the default postscript and separator are &#039;.&#039;.&lt;br /&gt;
In CS2, the default postscript is the empty string and the default separator is &#039;,&#039;.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function set_cs_style (postscript, mode)&lt;br /&gt;
	if utilities.is_set(postscript) then&lt;br /&gt;
		-- emit a maintenance message if user postscript is the default cs1 postscript&lt;br /&gt;
		-- we catch the opposite case for cs2 in set_style&lt;br /&gt;
		if mode == &#039;cs1&#039; and postscript == cfg.presentation[&#039;ps_&#039; .. mode] then&lt;br /&gt;
			utilities.set_message (&#039;maint_postscript&#039;);&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		postscript = cfg.presentation[&#039;ps_&#039; .. mode];&lt;br /&gt;
	end&lt;br /&gt;
	return cfg.presentation[&#039;sep_&#039; .. mode], postscript;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S E T _ S T Y L E &amp;gt;-----------------------------&lt;br /&gt;
&lt;br /&gt;
Sets the separator and postscript styles. Checks the |mode= first and the&lt;br /&gt;
#invoke CitationClass second. Removes the postscript if postscript == none.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function set_style (mode, postscript, cite_class)&lt;br /&gt;
	local sep;&lt;br /&gt;
	if &#039;cs2&#039; == mode then&lt;br /&gt;
		sep, postscript = set_cs_style (postscript, &#039;cs2&#039;);&lt;br /&gt;
	elseif &#039;cs1&#039; == mode then&lt;br /&gt;
		sep, postscript = set_cs_style (postscript, &#039;cs1&#039;);&lt;br /&gt;
	elseif &#039;citation&#039; == cite_class	then&lt;br /&gt;
		sep, postscript = set_cs_style (postscript, &#039;cs2&#039;);&lt;br /&gt;
	else&lt;br /&gt;
		sep, postscript = set_cs_style (postscript, &#039;cs1&#039;);&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if cfg.keywords_xlate[postscript:lower()] == &#039;none&#039; then&lt;br /&gt;
		-- emit a maintenance message if user postscript is the default cs2 postscript&lt;br /&gt;
		-- we catch the opposite case for cs1 in set_cs_style&lt;br /&gt;
		if &#039;cs2&#039; == mode or &#039;citation&#039; == cite_class then&lt;br /&gt;
			utilities.set_message (&#039;maint_postscript&#039;);&lt;br /&gt;
		end&lt;br /&gt;
		postscript = &#039;&#039;;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return sep, postscript&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[=[-------------------------&amp;lt; I S _ P D F &amp;gt;-----------------------------------&lt;br /&gt;
&lt;br /&gt;
Determines if a URL has the file extension that is one of the PDF file extensions&lt;br /&gt;
used by [[MediaWiki:Common.css]] when applying the PDF icon to external links.&lt;br /&gt;
&lt;br /&gt;
returns true if file extension is one of the recognized extensions, else false&lt;br /&gt;
&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local function is_pdf (url)&lt;br /&gt;
	return url:match (&#039;%.pdf$&#039;) or url:match (&#039;%.PDF$&#039;) or&lt;br /&gt;
		url:match (&#039;%.pdf[%?#]&#039;) or url:match (&#039;%.PDF[%?#]&#039;) or&lt;br /&gt;
		url:match (&#039;%.PDF&amp;amp;#035&#039;) or url:match (&#039;%.pdf&amp;amp;#035&#039;);&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S T Y L E _ F O R M A T &amp;gt;-----------------------&lt;br /&gt;
&lt;br /&gt;
Applies CSS style to |format=, |chapter-format=, etc.  Also emits an error message&lt;br /&gt;
if the format parameter does not have a matching URL parameter.  If the format parameter&lt;br /&gt;
is not set and the URL contains a file extension that is recognized as a PDF document&lt;br /&gt;
by MediaWiki&#039;s commons.css, this code will set the format parameter to (PDF) with&lt;br /&gt;
the appropriate styling.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function style_format (format, url, fmt_param, url_param)&lt;br /&gt;
	if utilities.is_set (format) then&lt;br /&gt;
		format = utilities.wrap_style (&#039;format&#039;, format);						-- add leading space, parentheses, resize&lt;br /&gt;
		if not utilities.is_set (url) then&lt;br /&gt;
			utilities.set_message (&#039;err_format_missing_url&#039;, {fmt_param, url_param});	-- add an error message&lt;br /&gt;
		end&lt;br /&gt;
	elseif is_pdf (url) then													-- format is not set so if URL is a PDF file then&lt;br /&gt;
		format = utilities.wrap_style (&#039;format&#039;, &#039;PDF&#039;);						-- set format to PDF&lt;br /&gt;
	else&lt;br /&gt;
		format = &#039;&#039;;															-- empty string for concatenation&lt;br /&gt;
	end&lt;br /&gt;
	return format;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[---------------------&amp;lt; G E T _ D I S P L A Y _ N A M E S &amp;gt;------------------&lt;br /&gt;
&lt;br /&gt;
Returns a number that defines the number of names displayed for author and editor&lt;br /&gt;
name lists and a Boolean flag to indicate when et al. should be appended to the name list.&lt;br /&gt;
&lt;br /&gt;
When the value assigned to |display-xxxxors= is a number greater than or equal to zero,&lt;br /&gt;
return the number and the previous state of the &#039;etal&#039; flag (false by default&lt;br /&gt;
but may have been set to true if the name list contains some variant of the text &#039;et al.&#039;).&lt;br /&gt;
&lt;br /&gt;
When the value assigned to |display-xxxxors= is the keyword &#039;etal&#039;, return a number&lt;br /&gt;
that is one greater than the number of authors in the list and set the &#039;etal&#039; flag true.&lt;br /&gt;
This will cause the list_people() to display all of the names in the name list followed by &#039;et al.&#039;&lt;br /&gt;
&lt;br /&gt;
In all other cases, returns nil and the previous state of the &#039;etal&#039; flag.&lt;br /&gt;
&lt;br /&gt;
inputs:&lt;br /&gt;
	max: A[&#039;DisplayAuthors&#039;] or A[&#039;DisplayEditors&#039;]; a number or some flavor of etal&lt;br /&gt;
	count: #a or #e&lt;br /&gt;
	list_name: &#039;authors&#039; or &#039;editors&#039;&lt;br /&gt;
	etal: author_etal or editor_etal&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function get_display_names (max, count, list_name, etal, param)&lt;br /&gt;
	if utilities.is_set (max) then&lt;br /&gt;
		if &#039;etal&#039; == max:lower():gsub(&amp;quot;[ &#039;%.]&amp;quot;, &#039;&#039;) then						-- the :gsub() portion makes &#039;etal&#039; from a variety of &#039;et al.&#039; spellings and stylings&lt;br /&gt;
			max = count + 1;													-- number of authors + 1 so display all author name plus et al.&lt;br /&gt;
			etal = true;														-- overrides value set by extract_names()&lt;br /&gt;
		elseif max:match (&#039;^%d+$&#039;) then											-- if is a string of numbers&lt;br /&gt;
			max = tonumber (max);												-- make it a number&lt;br /&gt;
			if max &amp;gt;= count then												-- if |display-xxxxors= value greater than or equal to number of authors/editors&lt;br /&gt;
				utilities.set_message (&#039;err_disp_name&#039;, {param, max});			-- add error message&lt;br /&gt;
				max = nil;&lt;br /&gt;
			end&lt;br /&gt;
		else																	-- not a valid keyword or number&lt;br /&gt;
			utilities.set_message (&#039;err_disp_name&#039;, {param, max});		-- add error message&lt;br /&gt;
			max = nil;															-- unset; as if |display-xxxxors= had not been set&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return max, etal;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[----------&amp;lt; E X T R A _ T E X T _ I N _ P A G E _ C H E C K &amp;gt;---------------&lt;br /&gt;
&lt;br /&gt;
Adds error if |page=, |pages=, |quote-page=, |quote-pages= has what appears to be&lt;br /&gt;
some form of p. or pp. abbreviation in the first characters of the parameter content.&lt;br /&gt;
&lt;br /&gt;
check page for extraneous p, p., pp, pp., pg, pg. at start of parameter value:&lt;br /&gt;
	good pattern: &#039;^P[^%.P%l]&#039; matches when page begins PX or P# but not Px&lt;br /&gt;
		      where x and X are letters and # is a digit&lt;br /&gt;
	bad pattern:  &#039;^[Pp][PpGg]&#039; matches when page begins pp, pP, Pp, PP, pg, pG, Pg, PG&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function extra_text_in_page_check (val, name)&lt;br /&gt;
	if not val:match (cfg.vol_iss_pg_patterns.good_ppattern) then&lt;br /&gt;
		for _, pattern in ipairs (cfg.vol_iss_pg_patterns.bad_ppatterns) do		-- spin through the selected sequence table of patterns&lt;br /&gt;
			if val:match (pattern) then											-- when a match, error so&lt;br /&gt;
				utilities.set_message (&#039;err_extra_text_pages&#039;, name);	 		-- add error message&lt;br /&gt;
				return;															-- and done&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end		&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; E X T R A _ T E X T _ I N _ V O L _ I S S _ C H E C K &amp;gt;------------------------&lt;br /&gt;
&lt;br /&gt;
Adds error if |volume= or |issue= has what appears to be some form of redundant &#039;type&#039; indicator.&lt;br /&gt;
&lt;br /&gt;
For |volume=:&lt;br /&gt;
	&#039;V.&#039;, or &#039;Vol.&#039; (with or without the dot) abbreviations or &#039;Volume&#039; in the first characters of the parameter&lt;br /&gt;
	content (all case insensitive). &#039;V&#039; and &#039;v&#039; (without the dot) are presumed to be roman numerals so&lt;br /&gt;
	are allowed.&lt;br /&gt;
&lt;br /&gt;
For |issue=:&lt;br /&gt;
	&#039;No.&#039;, &#039;I.&#039;, &#039;Iss.&#039; (with or without the dot) abbreviations, or &#039;Issue&#039; in the first characters of the&lt;br /&gt;
	parameter content (all case insensitive).&lt;br /&gt;
	&lt;br /&gt;
Single character values (&#039;v&#039;, &#039;i&#039;, &#039;n&#039;) allowed when not followed by separator character (&#039;.&#039;, &#039;:&#039;, &#039;=&#039;, or&lt;br /&gt;
whitespace character) – param values are trimmed of whitespace by MediaWiki before delivered to the module.&lt;br /&gt;
	&lt;br /&gt;
&amp;lt;val&amp;gt; is |volume= or |issue= parameter value&lt;br /&gt;
&amp;lt;name&amp;gt; is |volume= or |issue= parameter name for error message&lt;br /&gt;
&amp;lt;selector&amp;gt; is &#039;v&#039; for |volume=, &#039;i&#039; for |issue=&lt;br /&gt;
&lt;br /&gt;
sets error message on failure; returns nothing&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function extra_text_in_vol_iss_check (val, name, selector)&lt;br /&gt;
	if not utilities.is_set (val) then&lt;br /&gt;
		return;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local patterns = &#039;v&#039; == selector and cfg.vol_iss_pg_patterns.vpatterns or cfg.vol_iss_pg_patterns.ipatterns;&lt;br /&gt;
&lt;br /&gt;
	local handler = &#039;v&#039; == selector and &#039;err_extra_text_volume&#039; or &#039;err_extra_text_issue&#039;;&lt;br /&gt;
	val = val:lower();															-- force parameter value to lower case&lt;br /&gt;
	for _, pattern in ipairs (patterns) do										-- spin through the selected sequence table of patterns&lt;br /&gt;
		if val:match (pattern) then												-- when a match, error so&lt;br /&gt;
			utilities.set_message (handler, name);								-- add error message&lt;br /&gt;
			return;																-- and done&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[=[-------------------------&amp;lt; G E T _ V _ N A M E _ T A B L E &amp;gt;----------------------------------------------&lt;br /&gt;
&lt;br /&gt;
split apart a |vauthors= or |veditors= parameter.  This function allows for corporate names, wrapped in doubled&lt;br /&gt;
parentheses to also have commas; in the old version of the code, the doubled parentheses were included in the&lt;br /&gt;
rendered citation and in the metadata.  Individual author names may be wikilinked&lt;br /&gt;
&lt;br /&gt;
	|vauthors=Jones AB, [[E. B. White|White EB]], ((Black, Brown, and Co.))&lt;br /&gt;
&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local function get_v_name_table (vparam, output_table, output_link_table)&lt;br /&gt;
	local name_table = mw.text.split(vparam, &amp;quot;%s*,%s*&amp;quot;);						-- names are separated by commas&lt;br /&gt;
	local wl_type, label, link;													-- wl_type not used here; just a placeholder&lt;br /&gt;
	&lt;br /&gt;
	local i = 1;&lt;br /&gt;
	&lt;br /&gt;
	while name_table[i] do&lt;br /&gt;
		if name_table[i]:match (&#039;^%(%(.*[^%)][^%)]$&#039;) then						-- first segment of corporate with one or more commas; this segment has the opening doubled parentheses&lt;br /&gt;
			local name = name_table[i];&lt;br /&gt;
			i = i + 1;															-- bump indexer to next segment&lt;br /&gt;
			while name_table[i] do&lt;br /&gt;
				name = name .. &#039;, &#039; .. name_table[i];							-- concatenate with previous segments&lt;br /&gt;
				if name_table[i]:match (&#039;^.*%)%)$&#039;) then						-- if this table member has the closing doubled parentheses&lt;br /&gt;
					break;														-- and done reassembling so&lt;br /&gt;
				end&lt;br /&gt;
				i = i + 1;														-- bump indexer&lt;br /&gt;
			end&lt;br /&gt;
			table.insert (output_table, name);									-- and add corporate name to the output table&lt;br /&gt;
			table.insert (output_link_table, &#039;&#039;);								-- no wikilink&lt;br /&gt;
		else&lt;br /&gt;
			wl_type, label, link = utilities.is_wikilink (name_table[i]);		-- wl_type is: 0, no wl (text in label variable); 1, [[D]]; 2, [[L|D]]&lt;br /&gt;
			table.insert (output_table, label);									-- add this name&lt;br /&gt;
			if 1 == wl_type then&lt;br /&gt;
				table.insert (output_link_table, label);						-- simple wikilink [[D]]&lt;br /&gt;
			else&lt;br /&gt;
				table.insert (output_link_table, link);							-- no wikilink or [[L|D]]; add this link if there is one, else empty string&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		i = i + 1;&lt;br /&gt;
	end	&lt;br /&gt;
	return output_table;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; P A R S E _ V A U T H O R S _ V E D I T O R S &amp;gt;--------------------------------&lt;br /&gt;
&lt;br /&gt;
This function extracts author / editor names from |vauthors= or |veditors= and finds matching |xxxxor-maskn= and&lt;br /&gt;
|xxxxor-linkn= in args.  It then returns a table of assembled names just as extract_names() does.&lt;br /&gt;
&lt;br /&gt;
Author / editor names in |vauthors= or |veditors= must be in Vancouver system style. Corporate or institutional names&lt;br /&gt;
may sometimes be required and because such names will often fail the is_good_vanc_name() and other format compliance&lt;br /&gt;
tests, are wrapped in doubled parentheses ((corporate name)) to suppress the format tests.&lt;br /&gt;
&lt;br /&gt;
Supports generational suffixes Jr, 2nd, 3rd, 4th–6th.&lt;br /&gt;
&lt;br /&gt;
This function sets the Vancouver error when a required comma is missing and when there is a space between an author&#039;s initials.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function parse_vauthors_veditors (args, vparam, list_name)&lt;br /&gt;
	local names = {};															-- table of names assembled from |vauthors=, |author-maskn=, |author-linkn=&lt;br /&gt;
	local v_name_table = {};&lt;br /&gt;
	local v_link_table = {};													-- when name is wikilinked, targets go in this table&lt;br /&gt;
	local etal = false;															-- return value set to true when we find some form of et al. vauthors parameter&lt;br /&gt;
	local last, first, link, mask, suffix;&lt;br /&gt;
	local corporate = false;&lt;br /&gt;
&lt;br /&gt;
	vparam, etal = name_has_etal (vparam, etal, true);							-- find and remove variations on et al. do not categorize (do it here because et al. might have a period)&lt;br /&gt;
	v_name_table = get_v_name_table (vparam, v_name_table, v_link_table);		-- names are separated by commas&lt;br /&gt;
&lt;br /&gt;
	for i, v_name in ipairs(v_name_table) do&lt;br /&gt;
		first = &#039;&#039;;																-- set to empty string for concatenation and because it may have been set for previous author/editor&lt;br /&gt;
		local accept_name;&lt;br /&gt;
		v_name, accept_name = utilities.has_accept_as_written (v_name);			-- remove accept-this-as-written markup when it wraps all of &amp;lt;v_name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
		if accept_name then&lt;br /&gt;
			last = v_name;&lt;br /&gt;
			corporate = true;													-- flag used in list_people()&lt;br /&gt;
		elseif string.find(v_name, &amp;quot;%s&amp;quot;) then&lt;br /&gt;
			if v_name:find(&#039;[;%.]&#039;) then										-- look for commonly occurring punctuation characters; &lt;br /&gt;
				add_vanc_error (cfg.err_msg_supl.punctuation, i);&lt;br /&gt;
			end&lt;br /&gt;
			local lastfirstTable = {}&lt;br /&gt;
			lastfirstTable = mw.text.split(v_name, &amp;quot;%s+&amp;quot;)&lt;br /&gt;
			first = table.remove(lastfirstTable);								-- removes and returns value of last element in table which should be initials or generational suffix&lt;br /&gt;
&lt;br /&gt;
			if not mw.ustring.match (first, &#039;^%u+$&#039;) then						-- mw.ustring here so that later we will catch non-Latin characters&lt;br /&gt;
				suffix = first;													-- not initials so assume that whatever we got is a generational suffix&lt;br /&gt;
				first = table.remove(lastfirstTable);							-- get what should be the initials from the table&lt;br /&gt;
			end&lt;br /&gt;
			last = table.concat(lastfirstTable, &#039; &#039;)							-- returns a string that is the concatenation of all other names that are not initials and generational suffix&lt;br /&gt;
			if not utilities.is_set (last) then&lt;br /&gt;
				first = &#039;&#039;;														-- unset&lt;br /&gt;
				last = v_name;													-- last empty because something wrong with first&lt;br /&gt;
				add_vanc_error (cfg.err_msg_supl.name, i);&lt;br /&gt;
			end&lt;br /&gt;
			if mw.ustring.match (last, &#039;%a+%s+%u+%s+%a+&#039;) then&lt;br /&gt;
				add_vanc_error (cfg.err_msg_supl[&#039;missing comma&#039;], i);			-- matches last II last; the case when a comma is missing&lt;br /&gt;
			end&lt;br /&gt;
			if mw.ustring.match (v_name, &#039; %u %u$&#039;) then						-- this test is in the wrong place TODO: move or replace with a more appropriate test&lt;br /&gt;
				add_vanc_error (cfg.err_msg_supl.initials, i);					-- matches a space between two initials&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			last = v_name;														-- last name or single corporate name?  Doesn&#039;t support multiword corporate names? do we need this?&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		if utilities.is_set (first) then&lt;br /&gt;
			if not mw.ustring.match (first, &amp;quot;^%u?%u$&amp;quot;) then						-- first shall contain one or two upper-case letters, nothing else&lt;br /&gt;
				add_vanc_error (cfg.err_msg_supl.initials, i);					-- too many initials; mixed case initials (which may be ok Romanization); hyphenated initials&lt;br /&gt;
			end&lt;br /&gt;
			is_good_vanc_name (last, first, suffix, i);							-- check first and last before restoring the suffix which may have a non-Latin digit&lt;br /&gt;
			if utilities.is_set (suffix) then&lt;br /&gt;
				first = first .. &#039; &#039; .. suffix;									-- if there was a suffix concatenate with the initials&lt;br /&gt;
				suffix = &#039;&#039;;													-- unset so we don&#039;t add this suffix to all subsequent names&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			if not corporate then&lt;br /&gt;
				is_good_vanc_name (last, &#039;&#039;, nil, i);&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		link = utilities.select_one ( args, cfg.aliases[list_name .. &#039;-Link&#039;], &#039;err_redundant_parameters&#039;, i ) or v_link_table[i];&lt;br /&gt;
		mask = utilities.select_one ( args, cfg.aliases[list_name .. &#039;-Mask&#039;], &#039;err_redundant_parameters&#039;, i );&lt;br /&gt;
		names[i] = {last = last, first = first, link = link, mask = mask, corporate = corporate};		-- add this assembled name to our names list&lt;br /&gt;
	end&lt;br /&gt;
	return names, etal;															-- all done, return our list of names&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S E L E C T _ A U T H O R _ E D I T O R _ S O U R C E &amp;gt;------------------------&lt;br /&gt;
&lt;br /&gt;
Select one of |authors=, |authorn= / |lastn / firstn=, or |vauthors= as the source of the author name list or&lt;br /&gt;
select one of |editorn= / editor-lastn= / |editor-firstn= or |veditors= as the source of the editor name list.&lt;br /&gt;
&lt;br /&gt;
Only one of these appropriate three will be used.  The hierarchy is: |authorn= (and aliases) highest and |authors= lowest;&lt;br /&gt;
|editorn= (and aliases) highest and |veditors= lowest (support for |editors= withdrawn)&lt;br /&gt;
&lt;br /&gt;
When looking for |authorn= / |editorn= parameters, test |xxxxor1= and |xxxxor2= (and all of their aliases); stops after the second&lt;br /&gt;
test which mimicks the test used in extract_names() when looking for a hole in the author name list.  There may be a better&lt;br /&gt;
way to do this, I just haven&#039;t discovered what that way is.&lt;br /&gt;
&lt;br /&gt;
Emits an error message when more than one xxxxor name source is provided.&lt;br /&gt;
&lt;br /&gt;
In this function, vxxxxors = vauthors or veditors; xxxxors = authors as appropriate.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function select_author_editor_source (vxxxxors, xxxxors, args, list_name)&lt;br /&gt;
	local lastfirst = false;&lt;br /&gt;
	if utilities.select_one ( args, cfg.aliases[list_name .. &#039;-Last&#039;], &#039;none&#039;, 1 ) or		-- do this twice in case we have a |first1= without a |last1=; this ...&lt;br /&gt;
		utilities.select_one ( args, cfg.aliases[list_name .. &#039;-First&#039;], &#039;none&#039;, 1 ) or		-- ... also catches the case where |first= is used with |vauthors=&lt;br /&gt;
		utilities.select_one ( args, cfg.aliases[list_name .. &#039;-Last&#039;], &#039;none&#039;, 2 ) or&lt;br /&gt;
		utilities.select_one ( args, cfg.aliases[list_name .. &#039;-First&#039;], &#039;none&#039;, 2 ) then&lt;br /&gt;
			lastfirst = true;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if (utilities.is_set (vxxxxors) and true == lastfirst) or					-- these are the three error conditions&lt;br /&gt;
		(utilities.is_set (vxxxxors) and utilities.is_set (xxxxors)) or&lt;br /&gt;
		(true == lastfirst and utilities.is_set (xxxxors)) then&lt;br /&gt;
			local err_name;&lt;br /&gt;
			if &#039;AuthorList&#039; == list_name then									-- figure out which name should be used in error message&lt;br /&gt;
				err_name = &#039;author&#039;;&lt;br /&gt;
			else&lt;br /&gt;
				err_name = &#039;editor&#039;;&lt;br /&gt;
			end&lt;br /&gt;
			utilities.set_message (&#039;err_redundant_parameters&#039;, err_name .. &#039;-name-list parameters&#039;);	-- add error message&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if true == lastfirst then return 1 end;										-- return a number indicating which author name source to use&lt;br /&gt;
	if utilities.is_set (vxxxxors) then return 2 end;&lt;br /&gt;
	if utilities.is_set (xxxxors) then return 3 end;&lt;br /&gt;
	return 1;																	-- no authors so return 1; this allows missing author name test to run in case there is a first without last &lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; I S _ V A L I D _ P A R A M E T E R _ V A L U E &amp;gt;------------------------------&lt;br /&gt;
&lt;br /&gt;
This function is used to validate a parameter&#039;s assigned value for those parameters that have only a limited number&lt;br /&gt;
of allowable values (yes, y, true, live, dead, etc.).  When the parameter value has not been assigned a value (missing&lt;br /&gt;
or empty in the source template) the function returns the value specified by ret_val.  If the parameter value is one&lt;br /&gt;
of the list of allowed values returns the translated value; else, emits an error message and returns the value&lt;br /&gt;
specified by ret_val.&lt;br /&gt;
&lt;br /&gt;
TODO: explain &amp;lt;invert&amp;gt;&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function is_valid_parameter_value (value, name, possible, ret_val, invert)&lt;br /&gt;
	if not utilities.is_set (value) then&lt;br /&gt;
		return ret_val;															-- an empty parameter is ok&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if (not invert and utilities.in_array (value, possible)) then				-- normal; &amp;lt;value&amp;gt; is in &amp;lt;possible&amp;gt; table&lt;br /&gt;
		return cfg.keywords_xlate[value];										-- return translation of parameter keyword&lt;br /&gt;
	elseif invert and not utilities.in_array (value, possible) then				-- invert; &amp;lt;value&amp;gt; is not in &amp;lt;possible&amp;gt; table&lt;br /&gt;
		return value;															-- return &amp;lt;value&amp;gt; as it is&lt;br /&gt;
	else&lt;br /&gt;
		utilities.set_message (&#039;err_invalid_param_val&#039;, {name, value});			-- not an allowed value so add error message&lt;br /&gt;
		return ret_val;&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; T E R M I N A T E _ N A M E _ L I S T &amp;gt;----------------------------------------&lt;br /&gt;
&lt;br /&gt;
This function terminates a name list (author, contributor, editor) with a separator character (sepc) and a space&lt;br /&gt;
when the last character is not a sepc character or when the last three characters are not sepc followed by two&lt;br /&gt;
closing square brackets (close of a wikilink).  When either of these is true, the name_list is terminated with a&lt;br /&gt;
single space character.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function terminate_name_list (name_list, sepc)&lt;br /&gt;
	if (string.sub (name_list, -3, -1) == sepc .. &#039;. &#039;) then					-- if already properly terminated&lt;br /&gt;
		return name_list;														-- just return the name list&lt;br /&gt;
	elseif (string.sub (name_list, -1, -1) == sepc) or (string.sub (name_list, -3, -1) == sepc .. &#039;]]&#039;) then	-- if last name in list ends with sepc char&lt;br /&gt;
		return name_list .. &amp;quot; &amp;quot;;												-- don&#039;t add another&lt;br /&gt;
	else&lt;br /&gt;
		return name_list .. sepc .. &#039; &#039;;										-- otherwise terminate the name list&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[-------------------------&amp;lt; F O R M A T _ V O L U M E _ I S S U E &amp;gt;----------------------------------------&lt;br /&gt;
&lt;br /&gt;
returns the concatenation of the formatted volume and issue parameters as a single string; or formatted volume&lt;br /&gt;
or formatted issue, or an empty string if neither are set.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
	&lt;br /&gt;
local function format_volume_issue (volume, issue, cite_class, origin, sepc, lower)&lt;br /&gt;
	if not utilities.is_set (volume) and not utilities.is_set (issue) then&lt;br /&gt;
		return &#039;&#039;;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- same condition as in format_pages_sheets()&lt;br /&gt;
	local is_journal = &#039;journal&#039; == cite_class or (utilities.in_array (cite_class, {&#039;citation&#039;, &#039;map&#039;, &#039;interview&#039;}) and &#039;journal&#039; == origin);&lt;br /&gt;
&lt;br /&gt;
	local is_numeric_vol = volume and (volume:match (&#039;^[MDCLXVI]+$&#039;) or volume:match (&#039;^%d+$&#039;));	-- is only uppercase roman numerals or only digits?&lt;br /&gt;
	local is_long_vol = volume and (4 &amp;lt; mw.ustring.len(volume));				-- is |volume= value longer than 4 characters?&lt;br /&gt;
	&lt;br /&gt;
	if volume and (not is_numeric_vol and is_long_vol) then						-- when not all digits or Roman numerals, is |volume= longer than 4 characters?&lt;br /&gt;
		utilities.add_prop_cat (&#039;long-vol&#039;);									-- yes, add properties cat&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if is_journal then															-- journal-style formatting&lt;br /&gt;
		local vol = &#039;&#039;;&lt;br /&gt;
		&lt;br /&gt;
		if utilities.is_set (volume) then&lt;br /&gt;
			if is_numeric_vol then												-- |volume= value all digits or all uppercase Roman numerals?&lt;br /&gt;
				vol = utilities.substitute (cfg.presentation[&#039;vol-bold&#039;], {sepc, volume});	-- render in bold face&lt;br /&gt;
			elseif is_long_vol then												-- not all digits or Roman numerals; longer than 4 characters?&lt;br /&gt;
				vol = utilities.substitute (cfg.messages[&#039;j-vol&#039;], {sepc, utilities.hyphen_to_dash (volume)});	-- not bold&lt;br /&gt;
			else																-- four or fewer characters&lt;br /&gt;
				vol = utilities.substitute (cfg.presentation[&#039;vol-bold&#039;], {sepc, utilities.hyphen_to_dash (volume)});	-- bold&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		if utilities.is_set (issue) then&lt;br /&gt;
			return vol .. utilities.substitute (cfg.messages[&#039;j-issue&#039;], issue);&lt;br /&gt;
		end&lt;br /&gt;
		return vol;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if &#039;podcast&#039; == cite_class and utilities.is_set (issue) then&lt;br /&gt;
		return wrap_msg (&#039;issue&#039;, {sepc, issue}, lower);&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- all other types of citation&lt;br /&gt;
	if utilities.is_set (volume) and utilities.is_set (issue) then&lt;br /&gt;
		return wrap_msg (&#039;vol-no&#039;, {sepc, utilities.hyphen_to_dash (volume), issue}, lower);&lt;br /&gt;
	elseif utilities.is_set (volume) then&lt;br /&gt;
		return wrap_msg (&#039;vol&#039;, {sepc, utilities.hyphen_to_dash (volume)}, lower);&lt;br /&gt;
	else&lt;br /&gt;
		return wrap_msg (&#039;issue&#039;, {sepc, issue}, lower);&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[-------------------------&amp;lt; F O R M A T _ P A G E S _ S H E E T S &amp;gt;-----------------------------------------&lt;br /&gt;
&lt;br /&gt;
adds static text to one of |page(s)= or |sheet(s)= values and returns it with all of the others set to empty strings.&lt;br /&gt;
The return order is:&lt;br /&gt;
	page, pages, sheet, sheets&lt;br /&gt;
&lt;br /&gt;
Singular has priority over plural when both are provided.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function format_pages_sheets (page, pages, sheet, sheets, cite_class, origin, sepc, nopp, lower)&lt;br /&gt;
	if &#039;map&#039; == cite_class then													-- only cite map supports sheet(s) as in-source locators&lt;br /&gt;
		if utilities.is_set (sheet) then&lt;br /&gt;
			if &#039;journal&#039; == origin then&lt;br /&gt;
				return &#039;&#039;, &#039;&#039;, wrap_msg (&#039;j-sheet&#039;, sheet, lower), &#039;&#039;;&lt;br /&gt;
			else&lt;br /&gt;
				return &#039;&#039;, &#039;&#039;, wrap_msg (&#039;sheet&#039;, {sepc, sheet}, lower), &#039;&#039;;&lt;br /&gt;
			end&lt;br /&gt;
		elseif utilities.is_set (sheets) then&lt;br /&gt;
			if &#039;journal&#039; == origin then&lt;br /&gt;
				return &#039;&#039;, &#039;&#039;, &#039;&#039;, wrap_msg (&#039;j-sheets&#039;, sheets, lower);&lt;br /&gt;
			else&lt;br /&gt;
				return &#039;&#039;, &#039;&#039;, &#039;&#039;, wrap_msg (&#039;sheets&#039;, {sepc, sheets}, lower);&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local is_journal = &#039;journal&#039; == cite_class or (utilities.in_array (cite_class, {&#039;citation&#039;, &#039;map&#039;, &#039;interview&#039;}) and &#039;journal&#039; == origin);&lt;br /&gt;
	&lt;br /&gt;
	if utilities.is_set (page) then&lt;br /&gt;
		if is_journal then&lt;br /&gt;
			return utilities.substitute (cfg.messages[&#039;j-page(s)&#039;], page), &#039;&#039;, &#039;&#039;, &#039;&#039;;&lt;br /&gt;
		elseif not nopp then&lt;br /&gt;
			return utilities.substitute (cfg.messages[&#039;p-prefix&#039;], {sepc, page}), &#039;&#039;, &#039;&#039;, &#039;&#039;;&lt;br /&gt;
		else&lt;br /&gt;
			return utilities.substitute (cfg.messages[&#039;nopp&#039;], {sepc, page}), &#039;&#039;, &#039;&#039;, &#039;&#039;;&lt;br /&gt;
		end&lt;br /&gt;
	elseif utilities.is_set (pages) then&lt;br /&gt;
		if is_journal then&lt;br /&gt;
			return utilities.substitute (cfg.messages[&#039;j-page(s)&#039;], pages), &#039;&#039;, &#039;&#039;, &#039;&#039;;&lt;br /&gt;
		elseif tonumber(pages) ~= nil and not nopp then							-- if pages is only digits, assume a single page number&lt;br /&gt;
			return &#039;&#039;, utilities.substitute (cfg.messages[&#039;p-prefix&#039;], {sepc, pages}), &#039;&#039;, &#039;&#039;;&lt;br /&gt;
		elseif not nopp then&lt;br /&gt;
			return &#039;&#039;, utilities.substitute (cfg.messages[&#039;pp-prefix&#039;], {sepc, pages}), &#039;&#039;, &#039;&#039;;&lt;br /&gt;
		else&lt;br /&gt;
			return &#039;&#039;, utilities.substitute (cfg.messages[&#039;nopp&#039;], {sepc, pages}), &#039;&#039;, &#039;&#039;;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return &#039;&#039;, &#039;&#039;, &#039;&#039;, &#039;&#039;;														-- return empty strings&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; I N S O U R C E _ L O C _ G E T &amp;gt;----------------------------------------------&lt;br /&gt;
&lt;br /&gt;
returns one of the in-source locators: page, pages, or at. &lt;br /&gt;
&lt;br /&gt;
If any of these are interwiki links to Wikisource, returns the label portion of the interwiki-link as plain text&lt;br /&gt;
for use in COinS.  This COinS thing is done because here we convert an interwiki-link to an external link and&lt;br /&gt;
add an icon span around that; get_coins_pages() doesn&#039;t know about the span.  TODO: should it?  &lt;br /&gt;
&lt;br /&gt;
TODO: add support for sheet and sheets?; streamline;&lt;br /&gt;
&lt;br /&gt;
TODO: make it so that this function returns only one of the three as the single in-source (the return value assigned&lt;br /&gt;
to a new name)?&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function insource_loc_get (page, page_orig, pages, pages_orig, at)&lt;br /&gt;
	local ws_url, ws_label, coins_pages, L;										-- for Wikisource interwiki-links; TODO: this corrupts page metadata (span remains in place after cleanup; fix there?)&lt;br /&gt;
&lt;br /&gt;
	if utilities.is_set (page) then&lt;br /&gt;
		if utilities.is_set (pages) or utilities.is_set (at) then&lt;br /&gt;
			pages = &#039;&#039;;															-- unset the others&lt;br /&gt;
			at = &#039;&#039;;&lt;br /&gt;
		end&lt;br /&gt;
		extra_text_in_page_check (page, page_orig);								-- emit error message when |page= value begins with what looks like p., pp., etc.&lt;br /&gt;
&lt;br /&gt;
		ws_url, ws_label, L = wikisource_url_make (page);						-- make ws URL from |page= interwiki link; link portion L becomes tooltip label&lt;br /&gt;
		if ws_url then&lt;br /&gt;
			page = external_link (ws_url, ws_label .. &#039;&amp;amp;nbsp;&#039;, &#039;ws link in page&#039;);	-- space char after label to move icon away from in-source text; TODO: a better way to do this?&lt;br /&gt;
			page = utilities.substitute (cfg.presentation[&#039;interwiki-icon&#039;], {cfg.presentation[&#039;class-wikisource&#039;], L, page});&lt;br /&gt;
			coins_pages = ws_label;&lt;br /&gt;
		end&lt;br /&gt;
	elseif utilities.is_set (pages) then&lt;br /&gt;
		if utilities.is_set (at) then&lt;br /&gt;
			at = &#039;&#039;;															-- unset&lt;br /&gt;
		end&lt;br /&gt;
		extra_text_in_page_check (pages, pages_orig);							-- emit error message when |page= value begins with what looks like p., pp., etc.&lt;br /&gt;
&lt;br /&gt;
		ws_url, ws_label, L = wikisource_url_make (pages);						-- make ws URL from |pages= interwiki link; link portion L becomes tooltip label&lt;br /&gt;
		if ws_url then&lt;br /&gt;
			pages = external_link (ws_url, ws_label .. &#039;&amp;amp;nbsp;&#039;, &#039;ws link in pages&#039;);	-- space char after label to move icon away from in-source text; TODO: a better way to do this?&lt;br /&gt;
			pages = utilities.substitute (cfg.presentation[&#039;interwiki-icon&#039;], {cfg.presentation[&#039;class-wikisource&#039;], L, pages});&lt;br /&gt;
			coins_pages = ws_label;&lt;br /&gt;
		end&lt;br /&gt;
	elseif utilities.is_set (at) then&lt;br /&gt;
		ws_url, ws_label, L = wikisource_url_make (at);							-- make ws URL from |at= interwiki link; link portion L becomes tooltip label&lt;br /&gt;
		if ws_url then&lt;br /&gt;
			at = external_link (ws_url, ws_label .. &#039;&amp;amp;nbsp;&#039;, &#039;ws link in at&#039;);	-- space char after label to move icon away from in-source text; TODO: a better way to do this?&lt;br /&gt;
			at = utilities.substitute (cfg.presentation[&#039;interwiki-icon&#039;], {cfg.presentation[&#039;class-wikisource&#039;], L, at});&lt;br /&gt;
			coins_pages = ws_label;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return page, pages, at, coins_pages;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; I S _ U N I Q U E _ A R C H I V E _ U R L &amp;gt;------------------------------------&lt;br /&gt;
&lt;br /&gt;
add error message when |archive-url= value is same as |url= or chapter-url= (or alias...) value&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function is_unique_archive_url (archive, url, c_url, source, date)&lt;br /&gt;
	if utilities.is_set (archive) then&lt;br /&gt;
		if archive == url or archive == c_url then&lt;br /&gt;
			utilities.set_message (&#039;err_bad_url&#039;, {utilities.wrap_style (&#039;parameter&#039;, source)});	-- add error message&lt;br /&gt;
			return &#039;&#039;, &#039;&#039;;														-- unset |archive-url= and |archive-date= because same as |url= or |chapter-url=&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return archive, date;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[=[-------------------------&amp;lt; A R C H I V E _ U R L _ C H E C K &amp;gt;--------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Check archive.org URLs to make sure they at least look like they are pointing at valid archives and not to the &lt;br /&gt;
save snapshot URL or to calendar pages.  When the archive URL is &#039;https://web.archive.org/save/&#039; (or http://...)&lt;br /&gt;
archive.org saves a snapshot of the target page in the URL.  That is something that Wikipedia should not allow&lt;br /&gt;
unwitting readers to do.&lt;br /&gt;
&lt;br /&gt;
When the archive.org URL does not have a complete timestamp, archive.org chooses a snapshot according to its own&lt;br /&gt;
algorithm or provides a calendar &#039;search&#039; result.  [[WP:ELNO]] discourages links to search results.&lt;br /&gt;
&lt;br /&gt;
This function looks at the value assigned to |archive-url= and returns empty strings for |archive-url= and&lt;br /&gt;
|archive-date= and an error message when:&lt;br /&gt;
	|archive-url= holds an archive.org save command URL&lt;br /&gt;
	|archive-url= is an archive.org URL that does not have a complete timestamp (YYYYMMDDhhmmss 14 digits) in the&lt;br /&gt;
		correct place&lt;br /&gt;
otherwise returns |archive-url= and |archive-date=&lt;br /&gt;
&lt;br /&gt;
There are two mostly compatible archive.org URLs:&lt;br /&gt;
	//web.archive.org/&amp;lt;timestamp&amp;gt;...		-- the old form&lt;br /&gt;
	//web.archive.org/web/&amp;lt;timestamp&amp;gt;...	-- the new form&lt;br /&gt;
&lt;br /&gt;
The old form does not support or map to the new form when it contains a display flag.  There are four identified flags&lt;br /&gt;
(&#039;id_&#039;, &#039;js_&#039;, &#039;cs_&#039;, &#039;im_&#039;) but since archive.org ignores others following the same form (two letters and an underscore)&lt;br /&gt;
we don&#039;t check for these specific flags but we do check the form.&lt;br /&gt;
&lt;br /&gt;
This function supports a preview mode.  When the article is rendered in preview mode, this function may return a modified&lt;br /&gt;
archive URL:&lt;br /&gt;
	for save command errors, return undated wildcard (/*/)&lt;br /&gt;
	for timestamp errors when the timestamp has a wildcard, return the URL unmodified&lt;br /&gt;
	for timestamp errors when the timestamp does not have a wildcard, return with timestamp limited to six digits plus wildcard (/yyyymm*/)&lt;br /&gt;
&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local function archive_url_check (url, date)&lt;br /&gt;
	local err_msg = &#039;&#039;;															-- start with the error message empty&lt;br /&gt;
	local path, timestamp, flag;												-- portions of the archive.org URL&lt;br /&gt;
	&lt;br /&gt;
	if (not url:match(&#039;//web%.archive%.org/&#039;)) and (not url:match(&#039;//liveweb%.archive%.org/&#039;)) then		-- also deprecated liveweb Wayback machine URL&lt;br /&gt;
		return url, date;														-- not an archive.org archive, return ArchiveURL and ArchiveDate&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if url:match(&#039;//web%.archive%.org/save/&#039;) then								-- if a save command URL, we don&#039;t want to allow saving of the target page &lt;br /&gt;
		err_msg = cfg.err_msg_supl.save;&lt;br /&gt;
		url = url:gsub (&#039;(//web%.archive%.org)/save/&#039;, &#039;%1/*/&#039;, 1);				-- for preview mode: modify ArchiveURL&lt;br /&gt;
	elseif url:match(&#039;//liveweb%.archive%.org/&#039;) then&lt;br /&gt;
		err_msg = cfg.err_msg_supl.liveweb;&lt;br /&gt;
	else&lt;br /&gt;
		path, timestamp, flag = url:match(&#039;//web%.archive%.org/([^%d]*)(%d+)([^/]*)/&#039;);	-- split out some of the URL parts for evaluation&lt;br /&gt;
		if not path then														-- malformed in some way; pattern did not match&lt;br /&gt;
			err_msg = cfg.err_msg_supl.timestamp;&lt;br /&gt;
		elseif 14 ~= timestamp:len() then										-- path and flag optional, must have 14-digit timestamp here&lt;br /&gt;
			err_msg = cfg.err_msg_supl.timestamp;&lt;br /&gt;
			if &#039;*&#039; ~= flag then&lt;br /&gt;
				local replacement = timestamp:match (&#039;^%d%d%d%d%d%d&#039;) or timestamp:match (&#039;^%d%d%d%d&#039;);	-- get the first 6 (YYYYMM) or first 4 digits (YYYY)&lt;br /&gt;
				if replacement then												-- nil if there aren&#039;t at least 4 digits (year)&lt;br /&gt;
					replacement = replacement .. string.rep (&#039;0&#039;, 14 - replacement:len());	-- year or yearmo (4 or 6 digits) zero-fill to make 14-digit timestamp&lt;br /&gt;
					url=url:gsub (&#039;(//web%.archive%.org/[^%d]*)%d[^/]*&#039;, &#039;%1&#039; .. replacement .. &#039;*&#039;, 1)	-- for preview, modify ts to 14 digits plus splat for calendar display&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		elseif utilities.is_set (path) and &#039;web/&#039; ~= path then					-- older archive URLs do not have the extra &#039;web/&#039; path element&lt;br /&gt;
			err_msg = cfg.err_msg_supl.path;&lt;br /&gt;
		elseif utilities.is_set (flag) and not utilities.is_set (path) then		-- flag not allowed with the old form URL (without the &#039;web/&#039; path element)&lt;br /&gt;
			err_msg = cfg.err_msg_supl.flag;&lt;br /&gt;
		elseif utilities.is_set (flag) and not flag:match (&#039;%a%a_&#039;) then		-- flag if present must be two alpha characters and underscore (requires &#039;web/&#039; path element)&lt;br /&gt;
			err_msg = cfg.err_msg_supl.flag;&lt;br /&gt;
		else&lt;br /&gt;
			return url, date;													-- return ArchiveURL and ArchiveDate&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
																				-- if here, something not right so&lt;br /&gt;
	utilities.set_message (&#039;err_archive_url&#039;, {err_msg});						-- add error message and&lt;br /&gt;
&lt;br /&gt;
	if is_preview_mode then&lt;br /&gt;
		return url, date;														-- preview mode so return ArchiveURL and ArchiveDate&lt;br /&gt;
	else&lt;br /&gt;
		return &#039;&#039;, &#039;&#039;;															-- return empty strings for ArchiveURL and ArchiveDate&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; P L A C E _ C H E C K &amp;gt;--------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
check |place=, |publication-place=, |location= to see if these params include digits.  This function added because&lt;br /&gt;
many editors misuse location to specify the in-source location (|page(s)= and |at= are supposed to do that)&lt;br /&gt;
&lt;br /&gt;
returns the original parameter value without modification; added maint cat when parameter value contains digits&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function place_check (param_val)&lt;br /&gt;
	if not utilities.is_set (param_val) then									-- parameter empty or omitted&lt;br /&gt;
		return param_val;														-- return that empty state&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if mw.ustring.find (param_val, &#039;%d&#039;) then									-- not empty, are there digits in the parameter value&lt;br /&gt;
		utilities.set_message (&#039;maint_location&#039;);								-- yep, add maint cat&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return param_val;															-- and done&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; I S _ A R C H I V E D _ C O P Y &amp;gt;----------------------------------------------&lt;br /&gt;
&lt;br /&gt;
compares |title= to &#039;Archived copy&#039; (placeholder added by bots that can&#039;t find proper title); if matches, return true; nil else&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function is_archived_copy (title)&lt;br /&gt;
	title = mw.ustring.lower(title);											-- switch title to lower case&lt;br /&gt;
	if title:find (cfg.special_case_translation.archived_copy.en) then			-- if title is &#039;Archived copy&#039;&lt;br /&gt;
		return true;&lt;br /&gt;
	elseif cfg.special_case_translation.archived_copy[&#039;local&#039;] then&lt;br /&gt;
		if mw.ustring.find (title, cfg.special_case_translation.archived_copy[&#039;local&#039;]) then	-- mw.ustring() because might not be Latin script&lt;br /&gt;
			return true;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; C I T A T I O N 0 &amp;gt;------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
This is the main function doing the majority of the citation formatting.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function citation0( config, args )&lt;br /&gt;
	--[[ &lt;br /&gt;
	Load Input Parameters&lt;br /&gt;
	The argument_wrapper facilitates the mapping of multiple aliases to single internal variable.&lt;br /&gt;
	]]&lt;br /&gt;
	local A = argument_wrapper ( args );&lt;br /&gt;
	local i &lt;br /&gt;
&lt;br /&gt;
	-- Pick out the relevant fields from the arguments.  Different citation templates&lt;br /&gt;
	-- define different field names for the same underlying things.	&lt;br /&gt;
&lt;br /&gt;
	local author_etal;&lt;br /&gt;
	local a	= {};																-- authors list from |lastn= / |firstn= pairs or |vauthors=&lt;br /&gt;
	local Authors;&lt;br /&gt;
	local NameListStyle = is_valid_parameter_value (A[&#039;NameListStyle&#039;], A:ORIGIN(&#039;NameListStyle&#039;), cfg.keywords_lists[&#039;name-list-style&#039;], &#039;&#039;);&lt;br /&gt;
	local Collaboration = A[&#039;Collaboration&#039;];&lt;br /&gt;
&lt;br /&gt;
	do																			-- to limit scope of selected&lt;br /&gt;
		local selected = select_author_editor_source (A[&#039;Vauthors&#039;], A[&#039;Authors&#039;], args, &#039;AuthorList&#039;);&lt;br /&gt;
		if 1 == selected then&lt;br /&gt;
			a, author_etal = extract_names (args, &#039;AuthorList&#039;);				-- fetch author list from |authorn= / |lastn= / |firstn=, |author-linkn=, and |author-maskn=&lt;br /&gt;
		elseif 2 == selected then&lt;br /&gt;
			NameListStyle = &#039;vanc&#039;;												-- override whatever |name-list-style= might be&lt;br /&gt;
			a, author_etal = parse_vauthors_veditors (args, args.vauthors, &#039;AuthorList&#039;);	-- fetch author list from |vauthors=, |author-linkn=, and |author-maskn=&lt;br /&gt;
		elseif 3 == selected then&lt;br /&gt;
			Authors = A[&#039;Authors&#039;];												-- use content of |authors=&lt;br /&gt;
			if &#039;authors&#039; == A:ORIGIN(&#039;Authors&#039;) then							-- but add a maint cat if the parameter is |authors=&lt;br /&gt;
				utilities.set_message (&#039;maint_authors&#039;);						-- because use of this parameter is discouraged; what to do about the aliases is a TODO:&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		if utilities.is_set (Collaboration) then&lt;br /&gt;
			author_etal = true;													-- so that |display-authors=etal not required&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local editor_etal;&lt;br /&gt;
	local e	= {};																-- editors list from |editor-lastn= / |editor-firstn= pairs or |veditors=&lt;br /&gt;
&lt;br /&gt;
	do																			-- to limit scope of selected&lt;br /&gt;
		local selected = select_author_editor_source (A[&#039;Veditors&#039;], nil, args, &#039;EditorList&#039;);	-- support for |editors= withdrawn&lt;br /&gt;
		if 1 == selected then&lt;br /&gt;
			e, editor_etal = extract_names (args, &#039;EditorList&#039;);				-- fetch editor list from |editorn= / |editor-lastn= / |editor-firstn=, |editor-linkn=, and |editor-maskn=&lt;br /&gt;
		elseif 2 == selected then&lt;br /&gt;
			NameListStyle = &#039;vanc&#039;;												-- override whatever |name-list-style= might be&lt;br /&gt;
			e, editor_etal = parse_vauthors_veditors (args, args.veditors, &#039;EditorList&#039;);	-- fetch editor list from |veditors=, |editor-linkn=, and |editor-maskn=&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
							&lt;br /&gt;
	local Chapter = A[&#039;Chapter&#039;];												-- done here so that we have access to |contribution= from |chapter= aliases&lt;br /&gt;
	local Chapter_origin = A:ORIGIN (&#039;Chapter&#039;);&lt;br /&gt;
	local Contribution;															-- because contribution is required for contributor(s)&lt;br /&gt;
		if &#039;contribution&#039; == Chapter_origin then&lt;br /&gt;
			Contribution = Chapter;												-- get the name of the contribution&lt;br /&gt;
		end&lt;br /&gt;
	local c = {};																-- contributors list from |contributor-lastn= / contributor-firstn= pairs&lt;br /&gt;
	&lt;br /&gt;
	if utilities.in_array (config.CitationClass, {&amp;quot;book&amp;quot;, &amp;quot;citation&amp;quot;}) and not utilities.is_set (A[&#039;Periodical&#039;]) then	-- |contributor= and |contribution= only supported in book cites&lt;br /&gt;
		c = extract_names (args, &#039;ContributorList&#039;);							-- fetch contributor list from |contributorn= / |contributor-lastn=, -firstn=, -linkn=, -maskn=&lt;br /&gt;
		&lt;br /&gt;
		if 0 &amp;lt; #c then&lt;br /&gt;
			if not utilities.is_set (Contribution) then							-- |contributor= requires |contribution=&lt;br /&gt;
				utilities.set_message (&#039;err_contributor_missing_required_param&#039;, &#039;contribution&#039;);	-- add missing contribution error message&lt;br /&gt;
				c = {};															-- blank the contributors&#039; table; it is used as a flag later&lt;br /&gt;
			end&lt;br /&gt;
			if 0 == #a then														-- |contributor= requires |author=&lt;br /&gt;
				utilities.set_message (&#039;err_contributor_missing_required_param&#039;, &#039;author&#039;);	-- add missing author error message&lt;br /&gt;
				c = {};															-- blank the contributors&#039; table; it is used as a flag later&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	else																		-- if not a book cite&lt;br /&gt;
		if utilities.select_one (args, cfg.aliases[&#039;ContributorList-Last&#039;], &#039;err_redundant_parameters&#039;, 1 ) then	-- are there contributor name list parameters?&lt;br /&gt;
			utilities.set_message (&#039;err_contributor_ignored&#039;);					-- add contributor ignored error message&lt;br /&gt;
		end&lt;br /&gt;
		Contribution = nil;														-- unset&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local Title = A[&#039;Title&#039;];&lt;br /&gt;
	local TitleLink = A[&#039;TitleLink&#039;];&lt;br /&gt;
&lt;br /&gt;
	local auto_select = &#039;&#039;; -- default is auto&lt;br /&gt;
	local accept_link;&lt;br /&gt;
	TitleLink, accept_link = utilities.has_accept_as_written (TitleLink, true);	-- test for accept-this-as-written markup&lt;br /&gt;
	if (not accept_link) and utilities.in_array (TitleLink, {&#039;none&#039;, &#039;pmc&#039;, &#039;doi&#039;}) then -- check for special keywords&lt;br /&gt;
		auto_select = TitleLink;												-- remember selection for later&lt;br /&gt;
		TitleLink = &#039;&#039;;															-- treat as if |title-link= would have been empty&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	TitleLink = link_title_ok (TitleLink, A:ORIGIN (&#039;TitleLink&#039;), Title, &#039;title&#039;);	-- check for wiki-markup in |title-link= or wiki-markup in |title= when |title-link= is set&lt;br /&gt;
&lt;br /&gt;
	local Section = &#039;&#039;;															-- {{cite map}} only; preset to empty string for concatenation if not used&lt;br /&gt;
	if &#039;map&#039; == config.CitationClass and &#039;section&#039; == Chapter_origin then&lt;br /&gt;
		Section = A[&#039;Chapter&#039;];													-- get |section= from |chapter= alias list; |chapter= and the other aliases not supported in {{cite map}}&lt;br /&gt;
		Chapter = &#039;&#039;;															-- unset for now; will be reset later from |map= if present&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local Periodical = A[&#039;Periodical&#039;];&lt;br /&gt;
	local Periodical_origin = &#039;&#039;;&lt;br /&gt;
	if utilities.is_set (Periodical) then&lt;br /&gt;
		Periodical_origin = A:ORIGIN(&#039;Periodical&#039;);								-- get the name of the periodical parameter&lt;br /&gt;
		local i;&lt;br /&gt;
		Periodical, i = utilities.strip_apostrophe_markup (Periodical);			-- strip apostrophe markup so that metadata isn&#039;t contaminated &lt;br /&gt;
		if i then																-- non-zero when markup was stripped so emit an error message&lt;br /&gt;
			utilities.set_message (&#039;err_apostrophe_markup&#039;, {Periodical_origin});&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if &#039;mailinglist&#039; == config.CitationClass then								-- special case for {{cite mailing list}}&lt;br /&gt;
		if utilities.is_set (Periodical) and utilities.is_set (A [&#039;MailingList&#039;]) then	-- both set emit an error TODO: make a function for this and similar?&lt;br /&gt;
			utilities.set_message (&#039;err_redundant_parameters&#039;, {utilities.wrap_style (&#039;parameter&#039;, Periodical_origin) .. &#039; and &#039; .. utilities.wrap_style (&#039;parameter&#039;, &#039;mailinglist&#039;)});&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		Periodical = A [&#039;MailingList&#039;];											-- error or no, set Periodical to |mailinglist= value because this template is {{cite mailing list}}&lt;br /&gt;
		Periodical_origin = A:ORIGIN(&#039;MailingList&#039;);&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local ScriptPeriodical = A[&#039;ScriptPeriodical&#039;];&lt;br /&gt;
&lt;br /&gt;
	-- web and news not tested for now because of &lt;br /&gt;
	-- Wikipedia:Administrators%27_noticeboard#Is_there_a_semi-automated_tool_that_could_fix_these_annoying_&amp;quot;Cite_Web&amp;quot;_errors?&lt;br /&gt;
	if not (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) then	-- &#039;periodical&#039; templates require periodical parameter&lt;br /&gt;
	--	local p = {[&#039;journal&#039;] = &#039;journal&#039;, [&#039;magazine&#039;] = &#039;magazine&#039;, [&#039;news&#039;] = &#039;newspaper&#039;, [&#039;web&#039;] = &#039;website&#039;};	-- for error message&lt;br /&gt;
		local p = {[&#039;journal&#039;] = &#039;journal&#039;, [&#039;magazine&#039;] = &#039;magazine&#039;};			-- for error message&lt;br /&gt;
		if p[config.CitationClass]  then&lt;br /&gt;
			utilities.set_message (&#039;err_missing_periodical&#039;, {config.CitationClass, p[config.CitationClass]});&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local Volume;&lt;br /&gt;
	local ScriptPeriodical_origin = A:ORIGIN(&#039;ScriptPeriodical&#039;);&lt;br /&gt;
	if &#039;citation&#039; == config.CitationClass then&lt;br /&gt;
		if utilities.is_set (Periodical) then&lt;br /&gt;
			if not utilities.in_array (Periodical_origin, cfg.citation_no_volume_t) then	-- {{citation}} does not render |volume= when these parameters are used&lt;br /&gt;
				Volume = A[&#039;Volume&#039;];											-- but does for all other &#039;periodicals&#039;&lt;br /&gt;
			end&lt;br /&gt;
		elseif utilities.is_set (ScriptPeriodical) then&lt;br /&gt;
			if &#039;script-website&#039; ~= ScriptPeriodical_origin then					-- {{citation}} does not render volume for |script-website=&lt;br /&gt;
				Volume = A[&#039;Volume&#039;];											-- but does for all other &#039;periodicals&#039;&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			Volume = A[&#039;Volume&#039;];												-- and does for non-&#039;periodical&#039; cites&lt;br /&gt;
		end&lt;br /&gt;
	elseif utilities.in_array (config.CitationClass, cfg.templates_using_volume) then	-- render |volume= for cs1 according to the configuration settings&lt;br /&gt;
		Volume = A[&#039;Volume&#039;];&lt;br /&gt;
	end	&lt;br /&gt;
	extra_text_in_vol_iss_check (Volume, A:ORIGIN (&#039;Volume&#039;), &#039;v&#039;);	&lt;br /&gt;
&lt;br /&gt;
	local Issue;&lt;br /&gt;
	if &#039;citation&#039; == config.CitationClass then&lt;br /&gt;
		if utilities.is_set (Periodical) and utilities.in_array (Periodical_origin, cfg.citation_issue_t) then	-- {{citation}} may render |issue= when these parameters are used&lt;br /&gt;
			Issue = utilities.hyphen_to_dash (A[&#039;Issue&#039;]);&lt;br /&gt;
		end&lt;br /&gt;
	elseif utilities.in_array (config.CitationClass, cfg.templates_using_issue) then	-- conference &amp;amp; map books do not support issue; {{citation}} listed here because included in settings table&lt;br /&gt;
		if not (utilities.in_array (config.CitationClass, {&#039;conference&#039;, &#039;map&#039;, &#039;citation&#039;}) and not (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical))) then&lt;br /&gt;
			Issue = utilities.hyphen_to_dash (A[&#039;Issue&#039;]);&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	extra_text_in_vol_iss_check (Issue, A:ORIGIN (&#039;Issue&#039;), &#039;i&#039;);	&lt;br /&gt;
&lt;br /&gt;
	local Page;&lt;br /&gt;
	local Pages;&lt;br /&gt;
	local At;&lt;br /&gt;
	if not utilities.in_array (config.CitationClass, cfg.templates_not_using_page) then&lt;br /&gt;
		Page = A[&#039;Page&#039;];&lt;br /&gt;
		Pages = utilities.hyphen_to_dash (A[&#039;Pages&#039;]);	&lt;br /&gt;
		At = A[&#039;At&#039;];&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local Edition = A[&#039;Edition&#039;];&lt;br /&gt;
	local PublicationPlace = place_check (A[&#039;PublicationPlace&#039;], A:ORIGIN(&#039;PublicationPlace&#039;));&lt;br /&gt;
	local Place = place_check (A[&#039;Place&#039;], A:ORIGIN(&#039;Place&#039;));&lt;br /&gt;
	&lt;br /&gt;
	local PublisherName = A[&#039;PublisherName&#039;];&lt;br /&gt;
	local PublisherName_origin = A:ORIGIN(&#039;PublisherName&#039;);&lt;br /&gt;
	if utilities.is_set (PublisherName) then&lt;br /&gt;
		local i = 0;&lt;br /&gt;
		PublisherName, i = utilities.strip_apostrophe_markup (PublisherName);	-- strip apostrophe markup so that metadata isn&#039;t contaminated; publisher is never italicized&lt;br /&gt;
		if i then																-- non-zero when markup was stripped so emit an error message&lt;br /&gt;
			utilities.set_message (&#039;err_apostrophe_markup&#039;, {PublisherName_origin});&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local Newsgroup = A[&#039;Newsgroup&#039;];											-- TODO: strip apostrophe markup?&lt;br /&gt;
	local Newsgroup_origin = A:ORIGIN(&#039;Newsgroup&#039;);	&lt;br /&gt;
&lt;br /&gt;
	if &#039;newsgroup&#039; == config.CitationClass then&lt;br /&gt;
		if utilities.is_set (PublisherName) then								-- general use parameter |publisher= not allowed in cite newsgroup&lt;br /&gt;
			utilities.set_message (&#039;err_parameter_ignored&#039;, {PublisherName_origin});&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		PublisherName = nil;													-- ensure that this parameter is unset for the time being; will be used again after COinS&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local URL = A[&#039;URL&#039;];														-- TODO: better way to do this for URL, ChapterURL, and MapURL?&lt;br /&gt;
	local UrlAccess = is_valid_parameter_value (A[&#039;UrlAccess&#039;], A:ORIGIN(&#039;UrlAccess&#039;), cfg.keywords_lists[&#039;url-access&#039;], nil);&lt;br /&gt;
	&lt;br /&gt;
	if not utilities.is_set (URL) and utilities.is_set (UrlAccess) then&lt;br /&gt;
		UrlAccess = nil;&lt;br /&gt;
		utilities.set_message (&#039;err_param_access_requires_param&#039;, &#039;url&#039;);&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local ChapterURL = A[&#039;ChapterURL&#039;];&lt;br /&gt;
	local ChapterUrlAccess = is_valid_parameter_value (A[&#039;ChapterUrlAccess&#039;], A:ORIGIN(&#039;ChapterUrlAccess&#039;), cfg.keywords_lists[&#039;url-access&#039;], nil);&lt;br /&gt;
	if not utilities.is_set (ChapterURL) and utilities.is_set (ChapterUrlAccess) then&lt;br /&gt;
		ChapterUrlAccess = nil;&lt;br /&gt;
		utilities.set_message (&#039;err_param_access_requires_param&#039;, {A:ORIGIN(&#039;ChapterUrlAccess&#039;):gsub (&#039;%-access&#039;, &#039;&#039;)});&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local MapUrlAccess = is_valid_parameter_value (A[&#039;MapUrlAccess&#039;], A:ORIGIN(&#039;MapUrlAccess&#039;), cfg.keywords_lists[&#039;url-access&#039;], nil);&lt;br /&gt;
	if not utilities.is_set (A[&#039;MapURL&#039;]) and utilities.is_set (MapUrlAccess) then&lt;br /&gt;
		MapUrlAccess = nil;&lt;br /&gt;
		utilities.set_message (&#039;err_param_access_requires_param&#039;, {&#039;map-url&#039;});&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local this_page = mw.title.getCurrentTitle();								-- also used for COinS and for language&lt;br /&gt;
	local no_tracking_cats = is_valid_parameter_value (A[&#039;NoTracking&#039;], A:ORIGIN(&#039;NoTracking&#039;), cfg.keywords_lists[&#039;yes_true_y&#039;], nil);&lt;br /&gt;
&lt;br /&gt;
	-- check this page to see if it is in one of the namespaces that cs1 is not supposed to add to the error categories&lt;br /&gt;
	if not utilities.is_set (no_tracking_cats) then								-- ignore if we are already not going to categorize this page&lt;br /&gt;
		if utilities.in_array (this_page.nsText, cfg.uncategorized_namespaces) then&lt;br /&gt;
			no_tracking_cats = &amp;quot;true&amp;quot;;											-- set no_tracking_cats&lt;br /&gt;
		end&lt;br /&gt;
		for _, v in ipairs (cfg.uncategorized_subpages) do						-- cycle through page name patterns&lt;br /&gt;
			if this_page.text:match (v) then									-- test page name against each pattern&lt;br /&gt;
				no_tracking_cats = &amp;quot;true&amp;quot;;										-- set no_tracking_cats&lt;br /&gt;
				break;															-- bail out if one is found&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
																				-- check for extra |page=, |pages= or |at= parameters. (also sheet and sheets while we&#039;re at it)&lt;br /&gt;
	utilities.select_one (args, {&#039;page&#039;, &#039;p&#039;, &#039;pp&#039;, &#039;pages&#039;, &#039;at&#039;, &#039;sheet&#039;, &#039;sheets&#039;}, &#039;err_redundant_parameters&#039;);	-- this is a dummy call simply to get the error message and category&lt;br /&gt;
&lt;br /&gt;
	local coins_pages;&lt;br /&gt;
	&lt;br /&gt;
	Page, Pages, At, coins_pages = insource_loc_get (Page, A:ORIGIN(&#039;Page&#039;), Pages, A:ORIGIN(&#039;Pages&#039;), At);&lt;br /&gt;
&lt;br /&gt;
	local NoPP = is_valid_parameter_value (A[&#039;NoPP&#039;], A:ORIGIN(&#039;NoPP&#039;), cfg.keywords_lists[&#039;yes_true_y&#039;], nil);&lt;br /&gt;
&lt;br /&gt;
	if utilities.is_set (PublicationPlace) and utilities.is_set (Place) then	-- both |publication-place= and |place= (|location=) allowed if different&lt;br /&gt;
		utilities.add_prop_cat (&#039;location-test&#039;);								-- add property cat to evaluate how often PublicationPlace and Place are used together&lt;br /&gt;
		if PublicationPlace == Place then&lt;br /&gt;
			Place = &#039;&#039;;															-- unset; don&#039;t need both if they are the same&lt;br /&gt;
		end&lt;br /&gt;
	elseif not utilities.is_set (PublicationPlace) and utilities.is_set (Place) then	-- when only |place= (|location=) is set ...&lt;br /&gt;
		PublicationPlace = Place;												-- promote |place= (|location=) to |publication-place&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if PublicationPlace == Place then Place = &#039;&#039;; end							-- don&#039;t need both if they are the same&lt;br /&gt;
	&lt;br /&gt;
	local URL_origin = A:ORIGIN(&#039;URL&#039;);											-- get name of parameter that holds URL&lt;br /&gt;
	local ChapterURL_origin = A:ORIGIN(&#039;ChapterURL&#039;);							-- get name of parameter that holds ChapterURL&lt;br /&gt;
	local ScriptChapter = A[&#039;ScriptChapter&#039;];&lt;br /&gt;
	local ScriptChapter_origin = A:ORIGIN (&#039;ScriptChapter&#039;);&lt;br /&gt;
	local Format = A[&#039;Format&#039;];&lt;br /&gt;
	local ChapterFormat = A[&#039;ChapterFormat&#039;];&lt;br /&gt;
	local TransChapter = A[&#039;TransChapter&#039;];&lt;br /&gt;
	local TransChapter_origin = A:ORIGIN (&#039;TransChapter&#039;);&lt;br /&gt;
	local TransTitle = A[&#039;TransTitle&#039;];&lt;br /&gt;
	local ScriptTitle = A[&#039;ScriptTitle&#039;];&lt;br /&gt;
	&lt;br /&gt;
	--[[&lt;br /&gt;
	Parameter remapping for cite encyclopedia:&lt;br /&gt;
	When the citation has these parameters:&lt;br /&gt;
		|encyclopedia= and |title= then map |title= to |article= and |encyclopedia= to |title=&lt;br /&gt;
		|encyclopedia= and |article= then map |encyclopedia= to |title=&lt;br /&gt;
&lt;br /&gt;
		|trans-title= maps to |trans-chapter= when |title= is re-mapped&lt;br /&gt;
		|url= maps to |chapter-url= when |title= is remapped&lt;br /&gt;
	&lt;br /&gt;
	All other combinations of |encyclopedia=, |title=, and |article= are not modified&lt;br /&gt;
	&lt;br /&gt;
	]]&lt;br /&gt;
&lt;br /&gt;
	local Encyclopedia = A[&#039;Encyclopedia&#039;];										-- used as a flag by this module and by ~/COinS&lt;br /&gt;
&lt;br /&gt;
	if utilities.is_set (Encyclopedia) then										-- emit error message when Encyclopedia set but template is other than {{cite encyclopedia}} or {{citation}}&lt;br /&gt;
		if &#039;encyclopaedia&#039; ~= config.CitationClass and &#039;citation&#039; ~= config.CitationClass then&lt;br /&gt;
			utilities.set_message (&#039;err_parameter_ignored&#039;, {A:ORIGIN (&#039;Encyclopedia&#039;)});&lt;br /&gt;
			Encyclopedia = nil;													-- unset because not supported by this template&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if (&#039;encyclopaedia&#039; == config.CitationClass) or (&#039;citation&#039; == config.CitationClass and utilities.is_set (Encyclopedia)) then&lt;br /&gt;
		if utilities.is_set (Periodical) and utilities.is_set (Encyclopedia) then	-- when both set emit an error TODO: make a function for this and similar?&lt;br /&gt;
			utilities.set_message (&#039;err_redundant_parameters&#039;, {utilities.wrap_style (&#039;parameter&#039;, A:ORIGIN (&#039;Encyclopedia&#039;)) .. &#039; and &#039; .. utilities.wrap_style (&#039;parameter&#039;, Periodical_origin)});&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		if utilities.is_set (Encyclopedia) then&lt;br /&gt;
			Periodical = Encyclopedia;											-- error or no, set Periodical to Encyclopedia; allow periodical without encyclopedia&lt;br /&gt;
			Periodical_origin = A:ORIGIN (&#039;Encyclopedia&#039;);&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		if utilities.is_set (Periodical) then									-- Periodical is set when |encyclopedia= is set&lt;br /&gt;
			if utilities.is_set (Title) or utilities.is_set (ScriptTitle) then&lt;br /&gt;
				if not utilities.is_set (Chapter) then&lt;br /&gt;
					Chapter = Title;											-- |encyclopedia= and |title= are set so map |title= to |article= and |encyclopedia= to |title=&lt;br /&gt;
					ScriptChapter = ScriptTitle;&lt;br /&gt;
					ScriptChapter_origin = A:ORIGIN(&#039;ScriptTitle&#039;)&lt;br /&gt;
					TransChapter = TransTitle;&lt;br /&gt;
					ChapterURL = URL;&lt;br /&gt;
					ChapterURL_origin = URL_origin;&lt;br /&gt;
&lt;br /&gt;
					ChapterUrlAccess = UrlAccess;&lt;br /&gt;
&lt;br /&gt;
					if not utilities.is_set (ChapterURL) and utilities.is_set (TitleLink) then&lt;br /&gt;
						Chapter = utilities.make_wikilink (TitleLink, Chapter);&lt;br /&gt;
					end&lt;br /&gt;
					Title = Periodical;&lt;br /&gt;
					ChapterFormat = Format;&lt;br /&gt;
					Periodical = &#039;&#039;;											-- redundant so unset&lt;br /&gt;
					TransTitle = &#039;&#039;;&lt;br /&gt;
					URL = &#039;&#039;;&lt;br /&gt;
					Format = &#039;&#039;;&lt;br /&gt;
					TitleLink = &#039;&#039;;&lt;br /&gt;
					ScriptTitle = &#039;&#039;;&lt;br /&gt;
				end&lt;br /&gt;
			elseif utilities.is_set (Chapter) or utilities.is_set (ScriptChapter) then								-- |title= not set&lt;br /&gt;
				Title = Periodical;												-- |encyclopedia= set and |article= set so map |encyclopedia= to |title=&lt;br /&gt;
				Periodical = &#039;&#039;;												-- redundant so unset&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- special case for cite techreport.&lt;br /&gt;
	local ID = A[&#039;ID&#039;];&lt;br /&gt;
	if (config.CitationClass == &amp;quot;techreport&amp;quot;) then								-- special case for cite techreport&lt;br /&gt;
		if utilities.is_set (A[&#039;Number&#039;]) then									-- cite techreport uses &#039;number&#039;, which other citations alias to &#039;issue&#039;&lt;br /&gt;
			if not utilities.is_set (ID) then									-- can we use ID for the &amp;quot;number&amp;quot;?&lt;br /&gt;
				ID = A[&#039;Number&#039;];												-- yes, use it&lt;br /&gt;
			else																-- ID has a value so emit error message&lt;br /&gt;
				utilities.set_message (&#039;err_redundant_parameters&#039;, {utilities.wrap_style (&#039;parameter&#039;, &#039;id&#039;) .. &#039; and &#039; .. utilities.wrap_style (&#039;parameter&#039;, &#039;number&#039;)});&lt;br /&gt;
			end&lt;br /&gt;
		end	&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Account for the oddity that is {{cite conference}}, before generation of COinS data.&lt;br /&gt;
	local ChapterLink -- = A[&#039;ChapterLink&#039;];									-- deprecated as a parameter but still used internally by cite episode&lt;br /&gt;
	local Conference = A[&#039;Conference&#039;];&lt;br /&gt;
	local BookTitle = A[&#039;BookTitle&#039;];&lt;br /&gt;
	local TransTitle_origin = A:ORIGIN (&#039;TransTitle&#039;);&lt;br /&gt;
	if &#039;conference&#039; == config.CitationClass then&lt;br /&gt;
		if utilities.is_set (BookTitle) then&lt;br /&gt;
			Chapter = Title;&lt;br /&gt;
			Chapter_origin = &#039;title&#039;;&lt;br /&gt;
	--		ChapterLink = TitleLink;											-- |chapter-link= is deprecated&lt;br /&gt;
			ChapterURL = URL;&lt;br /&gt;
			ChapterUrlAccess = UrlAccess;&lt;br /&gt;
			ChapterURL_origin = URL_origin;&lt;br /&gt;
			URL_origin = &#039;&#039;;&lt;br /&gt;
			ChapterFormat = Format;&lt;br /&gt;
			TransChapter = TransTitle;&lt;br /&gt;
			TransChapter_origin = TransTitle_origin;&lt;br /&gt;
			Title = BookTitle;&lt;br /&gt;
			Format = &#039;&#039;;&lt;br /&gt;
	--		TitleLink = &#039;&#039;;&lt;br /&gt;
			TransTitle = &#039;&#039;;&lt;br /&gt;
			URL = &#039;&#039;;&lt;br /&gt;
		end&lt;br /&gt;
	elseif &#039;speech&#039; ~= config.CitationClass then&lt;br /&gt;
		Conference = &#039;&#039;;														-- not cite conference or cite speech so make sure this is empty string&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- CS1/2 mode&lt;br /&gt;
	local Mode = is_valid_parameter_value (A[&#039;Mode&#039;], A:ORIGIN(&#039;Mode&#039;), cfg.keywords_lists[&#039;mode&#039;], &#039;&#039;);&lt;br /&gt;
	-- separator character and postscript&lt;br /&gt;
	local sepc, PostScript = set_style (Mode:lower(), A[&#039;PostScript&#039;], config.CitationClass);&lt;br /&gt;
	-- controls capitalization of certain static text&lt;br /&gt;
	local use_lowercase = ( sepc == &#039;,&#039; );&lt;br /&gt;
	&lt;br /&gt;
	-- cite map oddities&lt;br /&gt;
	local Cartography = &amp;quot;&amp;quot;;&lt;br /&gt;
	local Scale = &amp;quot;&amp;quot;;&lt;br /&gt;
	local Sheet = A[&#039;Sheet&#039;] or &#039;&#039;;&lt;br /&gt;
	local Sheets = A[&#039;Sheets&#039;] or &#039;&#039;;&lt;br /&gt;
	if config.CitationClass == &amp;quot;map&amp;quot; then&lt;br /&gt;
		if utilities.is_set (Chapter) then										--TODO: make a function for this and similar?&lt;br /&gt;
			utilities.set_message (&#039;err_redundant_parameters&#039;, {utilities.wrap_style (&#039;parameter&#039;, &#039;map&#039;) .. &#039; and &#039; .. utilities.wrap_style (&#039;parameter&#039;, Chapter_origin)});	-- add error message&lt;br /&gt;
		end&lt;br /&gt;
		Chapter = A[&#039;Map&#039;];&lt;br /&gt;
		Chapter_origin = A:ORIGIN(&#039;Map&#039;);&lt;br /&gt;
		ChapterURL = A[&#039;MapURL&#039;];&lt;br /&gt;
		ChapterURL_origin = A:ORIGIN(&#039;MapURL&#039;);&lt;br /&gt;
		TransChapter = A[&#039;TransMap&#039;];&lt;br /&gt;
		ScriptChapter = A[&#039;ScriptMap&#039;]&lt;br /&gt;
		ScriptChapter_origin = A:ORIGIN(&#039;ScriptMap&#039;)&lt;br /&gt;
&lt;br /&gt;
		ChapterUrlAccess = MapUrlAccess;&lt;br /&gt;
		ChapterFormat = A[&#039;MapFormat&#039;];&lt;br /&gt;
&lt;br /&gt;
		Cartography = A[&#039;Cartography&#039;];&lt;br /&gt;
		if utilities.is_set ( Cartography ) then&lt;br /&gt;
			Cartography = sepc .. &amp;quot; &amp;quot; .. wrap_msg (&#039;cartography&#039;, Cartography, use_lowercase);&lt;br /&gt;
		end		&lt;br /&gt;
		Scale = A[&#039;Scale&#039;];&lt;br /&gt;
		if utilities.is_set ( Scale ) then&lt;br /&gt;
			Scale = sepc .. &amp;quot; &amp;quot; .. Scale;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Account for the oddities that are {{cite episode}} and {{cite serial}}, before generation of COinS data.&lt;br /&gt;
	local Series = A[&#039;Series&#039;];&lt;br /&gt;
	if &#039;episode&#039; == config.CitationClass or &#039;serial&#039; == config.CitationClass then&lt;br /&gt;
		local SeriesLink = A[&#039;SeriesLink&#039;];&lt;br /&gt;
&lt;br /&gt;
		SeriesLink = link_title_ok (SeriesLink, A:ORIGIN (&#039;SeriesLink&#039;), Series, &#039;series&#039;);	-- check for wiki-markup in |series-link= or wiki-markup in |series= when |series-link= is set&lt;br /&gt;
&lt;br /&gt;
		local Network = A[&#039;Network&#039;];&lt;br /&gt;
		local Station = A[&#039;Station&#039;];&lt;br /&gt;
		local s, n = {}, {};&lt;br /&gt;
																				-- do common parameters first&lt;br /&gt;
		if utilities.is_set (Network) then table.insert(n, Network); end&lt;br /&gt;
		if utilities.is_set (Station) then table.insert(n, Station); end&lt;br /&gt;
		ID = table.concat(n, sepc .. &#039; &#039;);&lt;br /&gt;
		&lt;br /&gt;
		if &#039;episode&#039; == config.CitationClass then								-- handle the oddities that are strictly {{cite episode}}&lt;br /&gt;
			local Season = A[&#039;Season&#039;];&lt;br /&gt;
			local SeriesNumber = A[&#039;SeriesNumber&#039;];&lt;br /&gt;
&lt;br /&gt;
			if utilities.is_set (Season) and utilities.is_set (SeriesNumber) then	-- these are mutually exclusive so if both are set TODO: make a function for this and similar?&lt;br /&gt;
				utilities.set_message (&#039;err_redundant_parameters&#039;, {utilities.wrap_style (&#039;parameter&#039;, &#039;season&#039;) .. &#039; and &#039; .. utilities.wrap_style (&#039;parameter&#039;, &#039;seriesno&#039;)});		-- add error message&lt;br /&gt;
				SeriesNumber = &#039;&#039;;												-- unset; prefer |season= over |seriesno=&lt;br /&gt;
			end&lt;br /&gt;
																				-- assemble a table of parts concatenated later into Series&lt;br /&gt;
			if utilities.is_set (Season) then table.insert(s, wrap_msg (&#039;season&#039;, Season, use_lowercase)); end&lt;br /&gt;
			if utilities.is_set (SeriesNumber) then table.insert(s, wrap_msg (&#039;seriesnum&#039;, SeriesNumber, use_lowercase)); end&lt;br /&gt;
			if utilities.is_set (Issue) then table.insert(s, wrap_msg (&#039;episode&#039;, Issue, use_lowercase)); end&lt;br /&gt;
			Issue = &#039;&#039;;															-- unset because this is not a unique parameter&lt;br /&gt;
	&lt;br /&gt;
			Chapter = Title;													-- promote title parameters to chapter&lt;br /&gt;
			ScriptChapter = ScriptTitle;&lt;br /&gt;
			ScriptChapter_origin = A:ORIGIN(&#039;ScriptTitle&#039;);&lt;br /&gt;
			ChapterLink = TitleLink;											-- alias |episode-link=&lt;br /&gt;
			TransChapter = TransTitle;&lt;br /&gt;
			ChapterURL = URL;&lt;br /&gt;
			ChapterUrlAccess = UrlAccess;&lt;br /&gt;
			ChapterURL_origin = URL_origin;&lt;br /&gt;
			ChapterFormat = Format;&lt;br /&gt;
&lt;br /&gt;
			Title = Series;														-- promote series to title&lt;br /&gt;
			TitleLink = SeriesLink;&lt;br /&gt;
			Series = table.concat(s, sepc .. &#039; &#039;);								-- this is concatenation of season, seriesno, episode number&lt;br /&gt;
&lt;br /&gt;
			if utilities.is_set (ChapterLink) and not utilities.is_set (ChapterURL) then	-- link but not URL&lt;br /&gt;
				Chapter = utilities.make_wikilink (ChapterLink, Chapter);&lt;br /&gt;
			elseif utilities.is_set (ChapterLink) and utilities.is_set (ChapterURL) then	-- if both are set, URL links episode;&lt;br /&gt;
				Series = utilities.make_wikilink (ChapterLink, Series);&lt;br /&gt;
			end&lt;br /&gt;
			URL = &#039;&#039;;															-- unset&lt;br /&gt;
			TransTitle = &#039;&#039;;&lt;br /&gt;
			ScriptTitle = &#039;&#039;;&lt;br /&gt;
			Format = &#039;&#039;;&lt;br /&gt;
			&lt;br /&gt;
		else																	-- now oddities that are cite serial&lt;br /&gt;
			Issue = &#039;&#039;;															-- unset because this parameter no longer supported by the citation/core version of cite serial&lt;br /&gt;
			Chapter = A[&#039;Episode&#039;];												-- TODO: make |episode= available to cite episode someday?&lt;br /&gt;
			if utilities.is_set (Series) and utilities.is_set (SeriesLink) then&lt;br /&gt;
				Series = utilities.make_wikilink (SeriesLink, Series);&lt;br /&gt;
			end&lt;br /&gt;
			Series = utilities.wrap_style (&#039;italic-title&#039;, Series);				-- series is italicized&lt;br /&gt;
		end	&lt;br /&gt;
	end&lt;br /&gt;
	-- end of {{cite episode}} stuff&lt;br /&gt;
&lt;br /&gt;
	-- handle type parameter for those CS1 citations that have default values&lt;br /&gt;
	local TitleType = A[&#039;TitleType&#039;];&lt;br /&gt;
	local Degree = A[&#039;Degree&#039;];&lt;br /&gt;
	if utilities.in_array (config.CitationClass, {&#039;AV-media-notes&#039;, &#039;interview&#039;, &#039;mailinglist&#039;, &#039;map&#039;, &#039;podcast&#039;, &#039;pressrelease&#039;, &#039;report&#039;, &#039;speech&#039;, &#039;techreport&#039;, &#039;thesis&#039;}) then&lt;br /&gt;
		TitleType = set_titletype (config.CitationClass, TitleType);&lt;br /&gt;
		if utilities.is_set (Degree) and &amp;quot;Thesis&amp;quot; == TitleType then				-- special case for cite thesis&lt;br /&gt;
			TitleType = Degree .. &#039; &#039; .. cfg.title_types [&#039;thesis&#039;]:lower();&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if utilities.is_set (TitleType) then										-- if type parameter is specified&lt;br /&gt;
		TitleType = utilities.substitute ( cfg.messages[&#039;type&#039;], TitleType);	-- display it in parentheses&lt;br /&gt;
	-- TODO: Hack on TitleType to fix bunched parentheses problem&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- legacy: promote PublicationDate to Date if neither Date nor Year are set.&lt;br /&gt;
	local Date = A[&#039;Date&#039;];&lt;br /&gt;
 	local Date_origin;															-- to hold the name of parameter promoted to Date; required for date error messaging&lt;br /&gt;
	local PublicationDate = A[&#039;PublicationDate&#039;];&lt;br /&gt;
	local Year = A[&#039;Year&#039;];&lt;br /&gt;
&lt;br /&gt;
	if not utilities.is_set (Date) then&lt;br /&gt;
		Date = Year;															-- promote Year to Date&lt;br /&gt;
		Year = nil;																-- make nil so Year as empty string isn&#039;t used for CITEREF&lt;br /&gt;
		if not utilities.is_set (Date) and utilities.is_set (PublicationDate) then	-- use PublicationDate when |date= and |year= are not set&lt;br /&gt;
			Date = PublicationDate;												-- promote PublicationDate to Date&lt;br /&gt;
			PublicationDate = &#039;&#039;;												-- unset, no longer needed&lt;br /&gt;
			Date_origin = A:ORIGIN(&#039;PublicationDate&#039;);							-- save the name of the promoted parameter&lt;br /&gt;
		else&lt;br /&gt;
			Date_origin = A:ORIGIN(&#039;Year&#039;);										-- save the name of the promoted parameter&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		Date_origin = A:ORIGIN(&#039;Date&#039;);											-- not a promotion; name required for error messaging&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if PublicationDate == Date then PublicationDate = &#039;&#039;; end					-- if PublicationDate is same as Date, don&#039;t display in rendered citation&lt;br /&gt;
&lt;br /&gt;
	--[[&lt;br /&gt;
	Go test all of the date-holding parameters for valid MOS:DATE format and make sure that dates are real dates. This must be done before we do COinS because here is where&lt;br /&gt;
	we get the date used in the metadata.&lt;br /&gt;
	&lt;br /&gt;
	Date validation supporting code is in Module:Citation/CS1/Date_validation&lt;br /&gt;
	]]&lt;br /&gt;
&lt;br /&gt;
	local DF = is_valid_parameter_value (A[&#039;DF&#039;], A:ORIGIN(&#039;DF&#039;), cfg.keywords_lists[&#039;df&#039;], &#039;&#039;);&lt;br /&gt;
	if not utilities.is_set (DF) then&lt;br /&gt;
		DF = cfg.global_df;														-- local |df= if present overrides global df set by {{use xxx date}} template&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local ArchiveURL;&lt;br /&gt;
	local ArchiveDate;&lt;br /&gt;
	local ArchiveFormat = A[&#039;ArchiveFormat&#039;];&lt;br /&gt;
&lt;br /&gt;
	ArchiveURL, ArchiveDate = archive_url_check (A[&#039;ArchiveURL&#039;], A[&#039;ArchiveDate&#039;])&lt;br /&gt;
	ArchiveFormat = style_format (ArchiveFormat, ArchiveURL, &#039;archive-format&#039;, &#039;archive-url&#039;);&lt;br /&gt;
	&lt;br /&gt;
	ArchiveURL, ArchiveDate = is_unique_archive_url (ArchiveURL, URL, ChapterURL, A:ORIGIN(&#039;ArchiveURL&#039;), ArchiveDate);		-- add error message when URL or ChapterURL == ArchiveURL&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	local AccessDate = A[&#039;AccessDate&#039;];&lt;br /&gt;
	local LayDate = A[&#039;LayDate&#039;];&lt;br /&gt;
	local COinS_date = {};														-- holds date info extracted from |date= for the COinS metadata by Module:Date verification&lt;br /&gt;
	local DoiBroken = A[&#039;DoiBroken&#039;];&lt;br /&gt;
	local Embargo = A[&#039;Embargo&#039;];&lt;br /&gt;
	local anchor_year;															-- used in the CITEREF identifier&lt;br /&gt;
	do	-- create defined block to contain local variables error_message, date_parameters_list, mismatch&lt;br /&gt;
		local error_message = &#039;&#039;;&lt;br /&gt;
																				-- AirDate has been promoted to Date so not necessary to check it&lt;br /&gt;
		local date_parameters_list = {&lt;br /&gt;
			[&#039;access-date&#039;] = {val = AccessDate, name = A:ORIGIN (&#039;AccessDate&#039;)},&lt;br /&gt;
			[&#039;archive-date&#039;] = {val = ArchiveDate, name = A:ORIGIN (&#039;ArchiveDate&#039;)},&lt;br /&gt;
			[&#039;date&#039;] = {val = Date, name = Date_origin},&lt;br /&gt;
			[&#039;doi-broken-date&#039;] = {val = DoiBroken, name = A:ORIGIN (&#039;DoiBroken&#039;)},&lt;br /&gt;
			[&#039;pmc-embargo-date&#039;] = {val = Embargo, name = A:ORIGIN (&#039;Embargo&#039;)},&lt;br /&gt;
			[&#039;lay-date&#039;] = {val = LayDate, name = A:ORIGIN (&#039;LayDate&#039;)},&lt;br /&gt;
			[&#039;publication-date&#039;] = {val = PublicationDate, name = A:ORIGIN (&#039;PublicationDate&#039;)},&lt;br /&gt;
			[&#039;year&#039;] = {val = Year, name = A:ORIGIN (&#039;Year&#039;)},&lt;br /&gt;
			};&lt;br /&gt;
&lt;br /&gt;
		local error_list = {};&lt;br /&gt;
		anchor_year, Embargo = validation.dates(date_parameters_list, COinS_date, error_list);&lt;br /&gt;
&lt;br /&gt;
-- start temporary Julian / Gregorian calendar uncertainty categorization&lt;br /&gt;
		if COinS_date.inter_cal_cat then&lt;br /&gt;
			utilities.add_prop_cat (&#039;jul-greg-uncertainty&#039;);&lt;br /&gt;
		end&lt;br /&gt;
-- end temporary Julian / Gregorian calendar uncertainty categorization&lt;br /&gt;
&lt;br /&gt;
		if utilities.is_set (Year) and utilities.is_set (Date) then				-- both |date= and |year= not normally needed; &lt;br /&gt;
			validation.year_date_check (Year, A:ORIGIN (&#039;Year&#039;), Date, A:ORIGIN (&#039;Date&#039;), error_list);&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		if 0 == #error_list then												-- error free dates only; 0 when error_list is empty&lt;br /&gt;
			local modified = false;												-- flag&lt;br /&gt;
			&lt;br /&gt;
			if utilities.is_set (DF) then										-- if we need to reformat dates&lt;br /&gt;
				modified = validation.reformat_dates (date_parameters_list, DF);	-- reformat to DF format, use long month names if appropriate&lt;br /&gt;
			end&lt;br /&gt;
&lt;br /&gt;
			if true == validation.date_hyphen_to_dash (date_parameters_list) then	-- convert hyphens to dashes where appropriate&lt;br /&gt;
				modified = true;&lt;br /&gt;
				utilities.set_message (&#039;maint_date_format&#039;);					-- hyphens were converted so add maint category&lt;br /&gt;
			end&lt;br /&gt;
			&lt;br /&gt;
	-- for those wikis that can and want to have English date names translated to the local language; not supported at en.wiki&lt;br /&gt;
			if cfg.date_name_auto_xlate_enable and validation.date_name_xlate (date_parameters_list, cfg.date_digit_auto_xlate_enable ) then&lt;br /&gt;
				utilities.set_message (&#039;maint_date_auto_xlated&#039;);				-- add maint cat&lt;br /&gt;
				modified = true;&lt;br /&gt;
			end&lt;br /&gt;
&lt;br /&gt;
			if modified then													-- if the date_parameters_list values were modified&lt;br /&gt;
				AccessDate = date_parameters_list[&#039;access-date&#039;].val;			-- overwrite date holding parameters with modified values&lt;br /&gt;
				ArchiveDate = date_parameters_list[&#039;archive-date&#039;].val;&lt;br /&gt;
				Date = date_parameters_list[&#039;date&#039;].val;&lt;br /&gt;
				DoiBroken = date_parameters_list[&#039;doi-broken-date&#039;].val;&lt;br /&gt;
				LayDate = date_parameters_list[&#039;lay-date&#039;].val;&lt;br /&gt;
				PublicationDate = date_parameters_list[&#039;publication-date&#039;].val;&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			utilities.set_message (&#039;err_bad_date&#039;, {utilities.make_sep_list (#error_list, error_list)});	-- add this error message&lt;br /&gt;
		end&lt;br /&gt;
	end	-- end of do&lt;br /&gt;
&lt;br /&gt;
	local ID_list = {};															-- sequence table of rendered identifiers&lt;br /&gt;
	local ID_list_coins = {};													-- table of identifiers and their values from args; key is same as cfg.id_handlers&#039;s key&lt;br /&gt;
	local Class = A[&#039;Class&#039;];													-- arxiv class identifier&lt;br /&gt;
	&lt;br /&gt;
	local ID_support = {&lt;br /&gt;
		{A[&#039;ASINTLD&#039;], &#039;ASIN&#039;, &#039;err_asintld_missing_asin&#039;, A:ORIGIN (&#039;ASINTLD&#039;)},				&lt;br /&gt;
		{DoiBroken, &#039;DOI&#039;, &#039;err_doibroken_missing_doi&#039;, A:ORIGIN (&#039;DoiBroken&#039;)},&lt;br /&gt;
		{Embargo, &#039;PMC&#039;, &#039;err_embargo_missing_pmc&#039;, A:ORIGIN (&#039;Embargo&#039;)},&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
	ID_list, ID_list_coins = identifiers.identifier_lists_get (args, {DoiBroken = DoiBroken, ASINTLD = A[&#039;ASINTLD&#039;], Embargo = Embargo, Class = Class}, ID_support);&lt;br /&gt;
&lt;br /&gt;
	-- Account for the oddities that are {{cite arxiv}}, {{cite biorxiv}}, {{cite citeseerx}}, {{cite ssrn}}, before generation of COinS data.&lt;br /&gt;
	if utilities.in_array (config.CitationClass, whitelist.preprint_template_list) then&lt;br /&gt;
		if not utilities.is_set (ID_list_coins[config.CitationClass:upper()]) then 	-- |arxiv= or |eprint= required for cite arxiv; |biorxiv= &amp;amp; |citeseerx= required for their templates&lt;br /&gt;
			utilities.set_message (&#039;err_&#039; .. config.CitationClass .. &#039;_missing&#039;);	-- add error message&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		Periodical = ({[&#039;arxiv&#039;] = &#039;arXiv&#039;, [&#039;biorxiv&#039;] = &#039;bioRxiv&#039;, [&#039;citeseerx&#039;] = &#039;CiteSeerX&#039;, [&#039;ssrn&#039;] = &#039;Social Science Research Network&#039;})[config.CitationClass];&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Link the title of the work if no |url= was provided, but we have a |pmc= or a |doi= with |doi-access=free&lt;br /&gt;
&lt;br /&gt;
	if config.CitationClass == &amp;quot;journal&amp;quot; and not utilities.is_set (URL) and not utilities.is_set (TitleLink) and not utilities.in_array (cfg.keywords_xlate[Title], {&#039;off&#039;, &#039;none&#039;}) then -- TODO: remove &#039;none&#039; once existing citations have been switched to &#039;off&#039;, so &#039;none&#039; can be used as token for &amp;quot;no title&amp;quot; instead&lt;br /&gt;
		if &#039;none&#039; ~= cfg.keywords_xlate[auto_select] then						-- if auto-linking not disabled&lt;br /&gt;
 	 		if identifiers.auto_link_urls[auto_select] then						-- manual selection&lt;br /&gt;
		 		URL = identifiers.auto_link_urls[auto_select];					-- set URL to be the same as identifier&#039;s external link&lt;br /&gt;
 				URL_origin = cfg.id_handlers[auto_select:upper()].parameters[1];	-- set URL_origin to parameter name for use in error message if citation is missing a |title=&lt;br /&gt;
			elseif identifiers.auto_link_urls[&#039;pmc&#039;] then						-- auto-select PMC&lt;br /&gt;
				URL = identifiers.auto_link_urls[&#039;pmc&#039;];						-- set URL to be the same as the PMC external link if not embargoed&lt;br /&gt;
				URL_origin = cfg.id_handlers[&#039;PMC&#039;].parameters[1];				-- set URL_origin to parameter name for use in error message if citation is missing a |title=&lt;br /&gt;
			elseif identifiers.auto_link_urls[&#039;doi&#039;] then						-- auto-select DOI&lt;br /&gt;
				URL = identifiers.auto_link_urls[&#039;doi&#039;];&lt;br /&gt;
				URL_origin = cfg.id_handlers[&#039;DOI&#039;].parameters[1];&lt;br /&gt;
			end&lt;br /&gt;
 	 	end&lt;br /&gt;
&lt;br /&gt;
		if utilities.is_set (URL) then											-- set when using an identifier-created URL&lt;br /&gt;
			if utilities.is_set (AccessDate) then								-- |access-date= requires |url=; identifier-created URL is not |url=&lt;br /&gt;
				utilities.set_message (&#039;err_accessdate_missing_url&#039;);			-- add an error message&lt;br /&gt;
				AccessDate = &#039;&#039;;												-- unset&lt;br /&gt;
			end&lt;br /&gt;
&lt;br /&gt;
			if utilities.is_set (ArchiveURL) then								-- |archive-url= requires |url=; identifier-created URL is not |url=&lt;br /&gt;
				utilities.set_message (&#039;err_archive_missing_url&#039;);				-- add an error message&lt;br /&gt;
				ArchiveURL = &#039;&#039;;												-- unset&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- At this point fields may be nil if they weren&#039;t specified in the template use.  We can use that fact.&lt;br /&gt;
	-- Test if citation has no title&lt;br /&gt;
	if	not utilities.is_set (Title) and not utilities.is_set (TransTitle) and not utilities.is_set (ScriptTitle) then	-- has special case for cite episode&lt;br /&gt;
		utilities.set_message (&#039;err_citation_missing_title&#039;, {&#039;episode&#039; == config.CitationClass and &#039;series&#039; or &#039;title&#039;});&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if utilities.in_array (cfg.keywords_xlate[Title], {&#039;off&#039;, &#039;none&#039;}) and&lt;br /&gt;
			utilities.in_array (config.CitationClass, {&#039;journal&#039;, &#039;citation&#039;}) and&lt;br /&gt;
			(utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) and&lt;br /&gt;
			(&#039;journal&#039; == Periodical_origin or &#039;script-journal&#039; == ScriptPeriodical_origin) then	-- special case for journal cites&lt;br /&gt;
				Title = &#039;&#039;;														-- set title to empty string&lt;br /&gt;
				utilities.set_message (&#039;maint_untitled&#039;);						-- add maint cat&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- COinS metadata (see &amp;lt;http://ocoins.info/&amp;gt;) for automated parsing of citation information.&lt;br /&gt;
	-- handle the oddity that is cite encyclopedia and {{citation |encyclopedia=something}}. Here we presume that&lt;br /&gt;
	-- when Periodical, Title, and Chapter are all set, then Periodical is the book (encyclopedia) title, Title&lt;br /&gt;
	-- is the article title, and Chapter is a section within the article.  So, we remap &lt;br /&gt;
	&lt;br /&gt;
	local coins_chapter = Chapter;												-- default assuming that remapping not required&lt;br /&gt;
	local coins_title = Title;													-- et tu&lt;br /&gt;
	if &#039;encyclopaedia&#039; == config.CitationClass or (&#039;citation&#039; == config.CitationClass and utilities.is_set (Encyclopedia)) then&lt;br /&gt;
		if utilities.is_set (Chapter) and utilities.is_set (Title) and utilities.is_set (Periodical) then		-- if all are used then&lt;br /&gt;
			coins_chapter = Title;												-- remap&lt;br /&gt;
			coins_title = Periodical;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local coins_author = a;														-- default for coins rft.au &lt;br /&gt;
	if 0 &amp;lt; #c then																-- but if contributor list&lt;br /&gt;
		coins_author = c;														-- use that instead&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local QuotePage = A[&#039;QuotePage&#039;];&lt;br /&gt;
	local QuotePages = utilities.hyphen_to_dash (A[&#039;QuotePages&#039;]);&lt;br /&gt;
&lt;br /&gt;
	-- this is the function call to COinS()&lt;br /&gt;
	local OCinSoutput = metadata.COinS({&lt;br /&gt;
		[&#039;Periodical&#039;] = utilities.strip_apostrophe_markup (Periodical),		-- no markup in the metadata&lt;br /&gt;
		[&#039;Encyclopedia&#039;] = Encyclopedia,										-- just a flag; content ignored by ~/COinS&lt;br /&gt;
		[&#039;Chapter&#039;] = metadata.make_coins_title (coins_chapter, ScriptChapter),	-- Chapter and ScriptChapter stripped of bold / italic / accept-as-written markup&lt;br /&gt;
		[&#039;Degree&#039;] = Degree;													-- cite thesis only&lt;br /&gt;
		[&#039;Title&#039;] = metadata.make_coins_title (coins_title, ScriptTitle),		-- Title and ScriptTitle stripped of bold / italic / accept-as-written markup&lt;br /&gt;
		[&#039;PublicationPlace&#039;] = PublicationPlace,&lt;br /&gt;
		[&#039;Date&#039;] = COinS_date.rftdate,											-- COinS_date has correctly formatted date if Date is valid;&lt;br /&gt;
		[&#039;Season&#039;] = COinS_date.rftssn,&lt;br /&gt;
		[&#039;Quarter&#039;] = COinS_date.rftquarter,&lt;br /&gt;
		[&#039;Chron&#039;] =  COinS_date.rftchron or (not COinS_date.rftdate and Date) or &#039;&#039;,	-- chron but if not set and invalid date format use Date; keep this last bit?&lt;br /&gt;
		[&#039;Series&#039;] = Series,&lt;br /&gt;
		[&#039;Volume&#039;] = Volume,&lt;br /&gt;
		[&#039;Issue&#039;] = Issue,&lt;br /&gt;
		[&#039;Pages&#039;] = coins_pages or metadata.get_coins_pages (first_set ({Sheet, Sheets, Page, Pages, At, QuotePage, QuotePages}, 7)),	-- pages stripped of external links&lt;br /&gt;
		[&#039;Edition&#039;] = Edition,&lt;br /&gt;
		[&#039;PublisherName&#039;] = PublisherName or Newsgroup,							-- any apostrophe markup already removed from PublisherName&lt;br /&gt;
		[&#039;URL&#039;] = first_set ({ChapterURL, URL}, 2),&lt;br /&gt;
		[&#039;Authors&#039;] = coins_author,&lt;br /&gt;
		[&#039;ID_list&#039;] = ID_list_coins,&lt;br /&gt;
		[&#039;RawPage&#039;] = this_page.prefixedText,&lt;br /&gt;
	}, config.CitationClass);&lt;br /&gt;
&lt;br /&gt;
	-- Account for the oddities that are {{cite arxiv}}, {{cite biorxiv}}, {{cite citeseerx}}, and {{cite ssrn}} AFTER generation of COinS data.&lt;br /&gt;
	if utilities.in_array (config.CitationClass, whitelist.preprint_template_list) then	-- we have set rft.jtitle in COinS to arXiv, bioRxiv, CiteSeerX, or ssrn now unset so it isn&#039;t displayed&lt;br /&gt;
		Periodical = &#039;&#039;;														-- periodical not allowed in these templates; if article has been published, use cite journal&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- special case for cite newsgroup.  Do this after COinS because we are modifying Publishername to include some static text&lt;br /&gt;
	if &#039;newsgroup&#039; == config.CitationClass and utilities.is_set (Newsgroup) then&lt;br /&gt;
		PublisherName = utilities.substitute (cfg.messages[&#039;newsgroup&#039;], external_link( &#039;news:&#039; .. Newsgroup, Newsgroup, Newsgroup_origin, nil ));&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local Editors;&lt;br /&gt;
	local EditorCount;															-- used only for choosing {ed.) or (eds.) annotation at end of editor name-list&lt;br /&gt;
	local Contributors;															-- assembled contributors name list&lt;br /&gt;
	local contributor_etal;&lt;br /&gt;
	local Translators;															-- assembled translators name list&lt;br /&gt;
	local translator_etal;&lt;br /&gt;
	local t = {};																-- translators list from |translator-lastn= / translator-firstn= pairs&lt;br /&gt;
	t = extract_names (args, &#039;TranslatorList&#039;);									-- fetch translator list from |translatorn= / |translator-lastn=, -firstn=, -linkn=, -maskn=&lt;br /&gt;
	local Interviewers;															&lt;br /&gt;
	local interviewers_list = {};					&lt;br /&gt;
	interviewers_list = extract_names (args, &#039;InterviewerList&#039;);				-- process preferred interviewers parameters&lt;br /&gt;
	local interviewer_etal;&lt;br /&gt;
	&lt;br /&gt;
	-- Now perform various field substitutions.&lt;br /&gt;
	-- We also add leading spaces and surrounding markup and punctuation to the&lt;br /&gt;
	-- various parts of the citation, but only when they are non-nil.&lt;br /&gt;
	do&lt;br /&gt;
		local last_first_list;&lt;br /&gt;
		local control = { &lt;br /&gt;
			format = NameListStyle,												-- empty string or &#039;vanc&#039;&lt;br /&gt;
			maximum = nil,														-- as if display-authors or display-editors not set&lt;br /&gt;
			mode = Mode&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
		do																		-- do editor name list first because the now unsupported coauthors used to modify control table&lt;br /&gt;
			control.maximum , editor_etal = get_display_names (A[&#039;DisplayEditors&#039;], #e, &#039;editors&#039;, editor_etal, A:ORIGIN (&#039;DisplayEditors&#039;));&lt;br /&gt;
			Editors, EditorCount = list_people (control, e, editor_etal);&lt;br /&gt;
&lt;br /&gt;
			if 1 == EditorCount and (true == editor_etal or 1 &amp;lt; #e) then		-- only one editor displayed but includes etal then &lt;br /&gt;
				EditorCount = 2;												-- spoof to display (eds.) annotation&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		do																		-- now do interviewers&lt;br /&gt;
			control.maximum, interviewer_etal = get_display_names (A[&#039;DisplayInterviewers&#039;], #interviewers_list, &#039;interviewers&#039;, interviewer_etal, A:ORIGIN (&#039;DisplayInterviewers&#039;));&lt;br /&gt;
			Interviewers = list_people (control, interviewers_list, interviewer_etal);&lt;br /&gt;
		end&lt;br /&gt;
		do																		-- now do translators&lt;br /&gt;
			control.maximum, translator_etal = get_display_names (A[&#039;DisplayTranslators&#039;], #t, &#039;translators&#039;, translator_etal, A:ORIGIN (&#039;DisplayTranslators&#039;));&lt;br /&gt;
			Translators = list_people (control, t, translator_etal);&lt;br /&gt;
		end&lt;br /&gt;
		do																		-- now do contributors&lt;br /&gt;
			control.maximum, contributor_etal = get_display_names (A[&#039;DisplayContributors&#039;], #c, &#039;contributors&#039;, contributor_etal, A:ORIGIN (&#039;DisplayContributors&#039;));&lt;br /&gt;
			Contributors = list_people (control, c, contributor_etal);&lt;br /&gt;
		end&lt;br /&gt;
		do																		-- now do authors&lt;br /&gt;
			control.maximum, author_etal = get_display_names (A[&#039;DisplayAuthors&#039;], #a, &#039;authors&#039;, author_etal, A:ORIGIN (&#039;DisplayAuthors&#039;));&lt;br /&gt;
&lt;br /&gt;
			last_first_list = list_people (control, a, author_etal);&lt;br /&gt;
&lt;br /&gt;
			if utilities.is_set (Authors) then&lt;br /&gt;
				Authors, author_etal = name_has_etal (Authors, author_etal, false, &#039;authors&#039;);	-- find and remove variations on et al.&lt;br /&gt;
				if author_etal then&lt;br /&gt;
					Authors = Authors .. &#039; &#039; .. cfg.messages[&#039;et al&#039;];			-- add et al. to authors parameter&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				Authors = last_first_list;										-- either an author name list or an empty string&lt;br /&gt;
			end&lt;br /&gt;
		end																		-- end of do&lt;br /&gt;
	&lt;br /&gt;
		if utilities.is_set (Authors) and utilities.is_set (Collaboration) then&lt;br /&gt;
			Authors = Authors .. &#039; (&#039; .. Collaboration .. &#039;)&#039;;					-- add collaboration after et al.&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local ConferenceFormat = A[&#039;ConferenceFormat&#039;];&lt;br /&gt;
	local ConferenceURL = A[&#039;ConferenceURL&#039;];&lt;br /&gt;
	ConferenceFormat = style_format (ConferenceFormat, ConferenceURL, &#039;conference-format&#039;, &#039;conference-url&#039;);&lt;br /&gt;
	Format = style_format (Format, URL, &#039;format&#039;, &#039;url&#039;);&lt;br /&gt;
&lt;br /&gt;
	-- special case for chapter format so no error message or cat when chapter not supported&lt;br /&gt;
	if not (utilities.in_array (config.CitationClass, {&#039;web&#039;, &#039;news&#039;, &#039;journal&#039;, &#039;magazine&#039;, &#039;pressrelease&#039;, &#039;podcast&#039;, &#039;newsgroup&#039;, &#039;arxiv&#039;, &#039;biorxiv&#039;, &#039;citeseerx&#039;, &#039;ssrn&#039;}) or&lt;br /&gt;
		(&#039;citation&#039; == config.CitationClass and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) and not utilities.is_set (Encyclopedia))) then&lt;br /&gt;
			ChapterFormat = style_format (ChapterFormat, ChapterURL, &#039;chapter-format&#039;, &#039;chapter-url&#039;);&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if not utilities.is_set (URL) then&lt;br /&gt;
		if utilities.in_array (config.CitationClass, {&amp;quot;web&amp;quot;, &amp;quot;podcast&amp;quot;, &amp;quot;mailinglist&amp;quot;}) or		-- |url= required for cite web, cite podcast, and cite mailinglist&lt;br /&gt;
			(&#039;citation&#039; == config.CitationClass and (&#039;website&#039; == Periodical_origin or &#039;script-website&#039; == ScriptPeriodical_origin)) then	-- and required for {{citation}} with |website= or |script-website=&lt;br /&gt;
				utilities.set_message (&#039;err_cite_web_url&#039;);&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		-- do we have |accessdate= without either |url= or |chapter-url=?&lt;br /&gt;
		if utilities.is_set (AccessDate) and not utilities.is_set (ChapterURL) then		-- ChapterURL may be set when URL is not set;&lt;br /&gt;
			utilities.set_message (&#039;err_accessdate_missing_url&#039;);&lt;br /&gt;
			AccessDate = &#039;&#039;;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local UrlStatus = is_valid_parameter_value (A[&#039;UrlStatus&#039;], A:ORIGIN(&#039;UrlStatus&#039;), cfg.keywords_lists[&#039;url-status&#039;], &#039;&#039;);&lt;br /&gt;
	local OriginalURL&lt;br /&gt;
	local OriginalURL_origin&lt;br /&gt;
	local OriginalFormat&lt;br /&gt;
	local OriginalAccess;&lt;br /&gt;
	UrlStatus = UrlStatus:lower();												-- used later when assembling archived text&lt;br /&gt;
	if utilities.is_set ( ArchiveURL ) then&lt;br /&gt;
		if utilities.is_set (ChapterURL) then 									-- if chapter-url= is set apply archive url to it&lt;br /&gt;
			OriginalURL = ChapterURL;											-- save copy of source chapter&#039;s url for archive text&lt;br /&gt;
			OriginalURL_origin = ChapterURL_origin;								-- name of |chapter-url= parameter for error messages&lt;br /&gt;
			OriginalFormat = ChapterFormat;										-- and original |chapter-format=&lt;br /&gt;
&lt;br /&gt;
			if &#039;live&#039; ~= UrlStatus then&lt;br /&gt;
				ChapterURL = ArchiveURL											-- swap-in the archive&#039;s URL&lt;br /&gt;
				ChapterURL_origin = A:ORIGIN(&#039;ArchiveURL&#039;)						-- name of |archive-url= parameter for error messages&lt;br /&gt;
				ChapterFormat = ArchiveFormat or &#039;&#039;;							-- swap in archive&#039;s format&lt;br /&gt;
				ChapterUrlAccess = nil;											-- restricted access levels do not make sense for archived URLs&lt;br /&gt;
			end&lt;br /&gt;
		elseif utilities.is_set (URL) then&lt;br /&gt;
			OriginalURL = URL;													-- save copy of original source URL&lt;br /&gt;
			OriginalURL_origin = URL_origin;									-- name of URL parameter for error messages&lt;br /&gt;
			OriginalFormat = Format; 											-- and original |format=&lt;br /&gt;
			OriginalAccess = UrlAccess;&lt;br /&gt;
&lt;br /&gt;
			if &#039;live&#039; ~= UrlStatus then											-- if URL set then |archive-url= applies to it&lt;br /&gt;
				URL = ArchiveURL												-- swap-in the archive&#039;s URL&lt;br /&gt;
				URL_origin = A:ORIGIN(&#039;ArchiveURL&#039;)								-- name of archive URL parameter for error messages&lt;br /&gt;
				Format = ArchiveFormat or &#039;&#039;;									-- swap in archive&#039;s format&lt;br /&gt;
				UrlAccess = nil;												-- restricted access levels do not make sense for archived URLs&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	elseif utilities.is_set (UrlStatus) then									-- if |url-status= is set when |archive-url= is not set&lt;br /&gt;
 		utilities.set_message (&#039;maint_url_status&#039;);								-- add maint cat&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if utilities.in_array (config.CitationClass, {&#039;web&#039;, &#039;news&#039;, &#039;journal&#039;, &#039;magazine&#039;, &#039;pressrelease&#039;, &#039;podcast&#039;, &#039;newsgroup&#039;, &#039;arxiv&#039;, &#039;biorxiv&#039;, &#039;citeseerx&#039;, &#039;ssrn&#039;}) or	-- if any of the &#039;periodical&#039; cites except encyclopedia&lt;br /&gt;
		(&#039;citation&#039; == config.CitationClass and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) and not utilities.is_set (Encyclopedia)) then&lt;br /&gt;
			local chap_param;&lt;br /&gt;
			if utilities.is_set (Chapter) then									-- get a parameter name from one of these chapter related meta-parameters&lt;br /&gt;
				chap_param = A:ORIGIN (&#039;Chapter&#039;)&lt;br /&gt;
			elseif utilities.is_set (TransChapter) then&lt;br /&gt;
				chap_param = A:ORIGIN (&#039;TransChapter&#039;)&lt;br /&gt;
			elseif utilities.is_set (ChapterURL) then&lt;br /&gt;
				chap_param = A:ORIGIN (&#039;ChapterURL&#039;)&lt;br /&gt;
			elseif utilities.is_set (ScriptChapter) then&lt;br /&gt;
				chap_param = ScriptChapter_origin;&lt;br /&gt;
			else utilities.is_set (ChapterFormat)&lt;br /&gt;
				chap_param = A:ORIGIN (&#039;ChapterFormat&#039;)&lt;br /&gt;
			end&lt;br /&gt;
&lt;br /&gt;
			if utilities.is_set (chap_param) then								-- if we found one&lt;br /&gt;
				utilities.set_message (&#039;err_chapter_ignored&#039;, {chap_param});	-- add error message&lt;br /&gt;
				Chapter = &#039;&#039;;													-- and set them to empty string to be safe with concatenation&lt;br /&gt;
				TransChapter = &#039;&#039;;&lt;br /&gt;
				ChapterURL = &#039;&#039;;&lt;br /&gt;
				ScriptChapter = &#039;&#039;;&lt;br /&gt;
				ChapterFormat = &#039;&#039;;&lt;br /&gt;
			end&lt;br /&gt;
	else																		-- otherwise, format chapter / article title&lt;br /&gt;
		local no_quotes = false;												-- default assume that we will be quoting the chapter parameter value&lt;br /&gt;
		if utilities.is_set (Contribution) and 0 &amp;lt; #c then						-- if this is a contribution with contributor(s)&lt;br /&gt;
			if utilities.in_array (Contribution:lower(), cfg.keywords_lists.contribution) then	-- and a generic contribution title&lt;br /&gt;
				no_quotes = true;												-- then render it unquoted&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		Chapter = format_chapter_title (ScriptChapter, ScriptChapter_origin, Chapter, Chapter_origin, TransChapter, TransChapter_origin, ChapterURL, ChapterURL_origin, no_quotes, ChapterUrlAccess);		-- Contribution is also in Chapter&lt;br /&gt;
		if utilities.is_set (Chapter) then&lt;br /&gt;
			Chapter = Chapter .. ChapterFormat ;&lt;br /&gt;
			if &#039;map&#039; == config.CitationClass and utilities.is_set (TitleType) then&lt;br /&gt;
				Chapter = Chapter .. &#039; &#039; .. TitleType;							-- map annotation here; not after title&lt;br /&gt;
			end&lt;br /&gt;
			Chapter = Chapter .. sepc .. &#039; &#039;;&lt;br /&gt;
		elseif utilities.is_set (ChapterFormat) then							-- |chapter= not set but |chapter-format= is so ...&lt;br /&gt;
			Chapter = ChapterFormat .. sepc .. &#039; &#039;;								-- ... ChapterFormat has error message, we want to see it&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Format main title&lt;br /&gt;
	local plain_title = false;&lt;br /&gt;
	local accept_title;&lt;br /&gt;
	Title, accept_title = utilities.has_accept_as_written (Title, true);		-- remove accept-this-as-written markup when it wraps all of &amp;lt;Title&amp;gt;&lt;br /&gt;
	if accept_title and (&#039;&#039; == Title) then										-- only support forced empty for now &amp;quot;(())&amp;quot;&lt;br /&gt;
		Title = cfg.messages[&#039;notitle&#039;];										-- replace by predefined &amp;quot;No title&amp;quot; message&lt;br /&gt;
			-- TODO: utilities.set_message ( &#039;err_redundant_parameters&#039;, ...);	-- issue proper error message instead of muting	 &lt;br /&gt;
			ScriptTitle = &#039;&#039;;													-- just mute for now	 &lt;br /&gt;
			TransTitle = &#039;&#039;;													-- just mute for now&lt;br /&gt;
 		plain_title = true;														-- suppress text decoration for descriptive title&lt;br /&gt;
		utilities.set_message (&#039;maint_untitled&#039;);								-- add maint cat&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if not accept_title then													-- &amp;lt;Title&amp;gt; not wrapped in accept-as-written markup&lt;br /&gt;
		if &#039;...&#039; == Title:sub (-3) then											-- if ellipsis is the last three characters of |title=&lt;br /&gt;
			Title = Title:gsub (&#039;(%.%.%.)%.+$&#039;, &#039;%1&#039;);							-- limit the number of dots to three&lt;br /&gt;
		elseif not mw.ustring.find (Title, &#039;%.%s*%a%.$&#039;) and					-- end of title is not a &#039;dot-(optional space-)letter-dot&#039; initialism ...&lt;br /&gt;
			not mw.ustring.find (Title, &#039;%s+%a%.$&#039;) then						-- ...and not a &#039;space-letter-dot&#039; initial (&#039;&#039;Allium canadense&#039;&#039; L.)&lt;br /&gt;
				Title = mw.ustring.gsub(Title, &#039;%&#039; .. sepc .. &#039;$&#039;, &#039;&#039;);			-- remove any trailing separator character; sepc and ms.ustring() here for languages that use multibyte separator characters&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		if utilities.is_set (ArchiveURL) and is_archived_copy (Title) then&lt;br /&gt;
			utilities.set_message (&#039;maint_archived_copy&#039;);						-- add maintenance category before we modify the content of Title&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		if is_generic (&#039;generic_titles&#039;, Title) then&lt;br /&gt;
			utilities.set_message (&#039;err_generic_title&#039;);						-- set an error message&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if (not plain_title) and (utilities.in_array (config.CitationClass, {&#039;web&#039;, &#039;news&#039;, &#039;journal&#039;, &#039;magazine&#039;, &#039;pressrelease&#039;, &#039;podcast&#039;, &#039;newsgroup&#039;, &#039;mailinglist&#039;, &#039;interview&#039;, &#039;arxiv&#039;, &#039;biorxiv&#039;, &#039;citeseerx&#039;, &#039;ssrn&#039;}) or&lt;br /&gt;
		(&#039;citation&#039; == config.CitationClass and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) and not utilities.is_set (Encyclopedia)) or&lt;br /&gt;
		(&#039;map&#039; == config.CitationClass and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)))) then		-- special case for cite map when the map is in a periodical treat as an article&lt;br /&gt;
			Title = kern_quotes (Title);										-- if necessary, separate title&#039;s leading and trailing quote marks from module provided quote marks&lt;br /&gt;
			Title = utilities.wrap_style (&#039;quoted-title&#039;, Title);&lt;br /&gt;
			Title = script_concatenate (Title, ScriptTitle, &#039;script-title&#039;);	-- &amp;lt;bdi&amp;gt; tags, lang attribute, categorization, etc.; must be done after title is wrapped&lt;br /&gt;
			TransTitle = utilities.wrap_style (&#039;trans-quoted-title&#039;, TransTitle );&lt;br /&gt;
	elseif plain_title or (&#039;report&#039; == config.CitationClass) then				-- no styling for cite report and descriptive titles (otherwise same as above)&lt;br /&gt;
		Title = script_concatenate (Title, ScriptTitle, &#039;script-title&#039;);		-- &amp;lt;bdi&amp;gt; tags, lang attribute, categorization, etc.; must be done after title is wrapped&lt;br /&gt;
		TransTitle = utilities.wrap_style (&#039;trans-quoted-title&#039;, TransTitle );	-- for cite report, use this form for trans-title&lt;br /&gt;
	else&lt;br /&gt;
		Title = utilities.wrap_style (&#039;italic-title&#039;, Title);&lt;br /&gt;
		Title = script_concatenate (Title, ScriptTitle, &#039;script-title&#039;);		-- &amp;lt;bdi&amp;gt; tags, lang attribute, categorization, etc.; must be done after title is wrapped&lt;br /&gt;
		TransTitle = utilities.wrap_style (&#039;trans-italic-title&#039;, TransTitle);&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if utilities.is_set (TransTitle) then&lt;br /&gt;
		if utilities.is_set (Title) then&lt;br /&gt;
			TransTitle = &amp;quot; &amp;quot; .. TransTitle;&lt;br /&gt;
		else&lt;br /&gt;
			utilities.set_message (&#039;err_trans_missing_title&#039;, {&#039;title&#039;});&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if utilities.is_set (Title) then											-- TODO: is this the right place to be making Wikisource URLs?&lt;br /&gt;
		if utilities.is_set (TitleLink) and utilities.is_set (URL) then&lt;br /&gt;
			utilities.set_message (&#039;err_wikilink_in_url&#039;);						-- set an error message because we can&#039;t have both&lt;br /&gt;
			TitleLink = &#039;&#039;;														-- unset&lt;br /&gt;
		end&lt;br /&gt;
	&lt;br /&gt;
		if not utilities.is_set (TitleLink) and utilities.is_set (URL) then&lt;br /&gt;
			Title = external_link (URL, Title, URL_origin, UrlAccess) .. TransTitle .. Format;&lt;br /&gt;
			URL = &#039;&#039;;															-- unset these because no longer needed&lt;br /&gt;
			Format = &amp;quot;&amp;quot;;&lt;br /&gt;
		elseif utilities.is_set (TitleLink) and not utilities.is_set (URL) then&lt;br /&gt;
			local ws_url;&lt;br /&gt;
			ws_url = wikisource_url_make (TitleLink);							-- ignore ws_label return; not used here&lt;br /&gt;
			if ws_url then&lt;br /&gt;
				Title = external_link (ws_url, Title .. &#039;&amp;amp;nbsp;&#039;, &#039;ws link in title-link&#039;);	-- space char after Title to move icon away from italic text; TODO: a better way to do this?&lt;br /&gt;
				Title = utilities.substitute (cfg.presentation[&#039;interwiki-icon&#039;], {cfg.presentation[&#039;class-wikisource&#039;], TitleLink, Title});				&lt;br /&gt;
				Title = Title .. TransTitle;&lt;br /&gt;
			else&lt;br /&gt;
				Title = utilities.make_wikilink (TitleLink, Title) .. TransTitle;&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			local ws_url, ws_label, L;											-- Title has italic or quote markup by the time we get here which causes is_wikilink() to return 0 (not a wikilink)&lt;br /&gt;
			ws_url, ws_label, L = wikisource_url_make (Title:gsub(&#039;^[\&#039;&amp;quot;]*(.-)[\&#039;&amp;quot;]*$&#039;, &#039;%1&#039;));	-- make ws URL from |title= interwiki link (strip italic or quote markup); link portion L becomes tooltip label&lt;br /&gt;
			if ws_url then&lt;br /&gt;
				Title = Title:gsub (&#039;%b[]&#039;, ws_label);							-- replace interwiki link with ws_label to retain markup&lt;br /&gt;
				Title = external_link (ws_url, Title .. &#039;&amp;amp;nbsp;&#039;, &#039;ws link in title&#039;);	-- space char after Title to move icon away from italic text; TODO: a better way to do this?&lt;br /&gt;
				Title = utilities.substitute (cfg.presentation[&#039;interwiki-icon&#039;], {cfg.presentation[&#039;class-wikisource&#039;], L, Title});				&lt;br /&gt;
				Title = Title .. TransTitle;&lt;br /&gt;
			else&lt;br /&gt;
				Title = Title .. TransTitle;&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		Title = TransTitle;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if utilities.is_set (Place) then&lt;br /&gt;
		Place = &amp;quot; &amp;quot; .. wrap_msg (&#039;written&#039;, Place, use_lowercase) .. sepc .. &amp;quot; &amp;quot;;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local ConferenceURL_origin = A:ORIGIN(&#039;ConferenceURL&#039;);						-- get name of parameter that holds ConferenceURL&lt;br /&gt;
	if utilities.is_set (Conference) then&lt;br /&gt;
		if utilities.is_set (ConferenceURL) then&lt;br /&gt;
			Conference = external_link( ConferenceURL, Conference, ConferenceURL_origin, nil );&lt;br /&gt;
		end&lt;br /&gt;
		Conference = sepc .. &amp;quot; &amp;quot; .. Conference .. ConferenceFormat;&lt;br /&gt;
	elseif utilities.is_set (ConferenceURL) then&lt;br /&gt;
		Conference = sepc .. &amp;quot; &amp;quot; .. external_link( ConferenceURL, nil, ConferenceURL_origin, nil );&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local Position = &#039;&#039;;&lt;br /&gt;
	if not utilities.is_set (Position) then&lt;br /&gt;
		local Minutes = A[&#039;Minutes&#039;];&lt;br /&gt;
		local Time = A[&#039;Time&#039;];&lt;br /&gt;
&lt;br /&gt;
		if utilities.is_set (Minutes) then&lt;br /&gt;
			if utilities.is_set (Time) then		--TODO: make a function for this and similar?&lt;br /&gt;
				utilities.set_message (&#039;err_redundant_parameters&#039;, {utilities.wrap_style (&#039;parameter&#039;, &#039;minutes&#039;) .. &#039; and &#039; .. utilities.wrap_style (&#039;parameter&#039;, &#039;time&#039;)});&lt;br /&gt;
			end&lt;br /&gt;
			Position = &amp;quot; &amp;quot; .. Minutes .. &amp;quot; &amp;quot; .. cfg.messages[&#039;minutes&#039;];&lt;br /&gt;
		else&lt;br /&gt;
			if utilities.is_set (Time) then&lt;br /&gt;
				local TimeCaption = A[&#039;TimeCaption&#039;]&lt;br /&gt;
				if not utilities.is_set (TimeCaption) then&lt;br /&gt;
					TimeCaption = cfg.messages[&#039;event&#039;];&lt;br /&gt;
					if sepc ~= &#039;.&#039; then&lt;br /&gt;
						TimeCaption = TimeCaption:lower();&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
				Position = &amp;quot; &amp;quot; .. TimeCaption .. &amp;quot; &amp;quot; .. Time;&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		Position = &amp;quot; &amp;quot; .. Position;&lt;br /&gt;
		At = &#039;&#039;;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	Page, Pages, Sheet, Sheets = format_pages_sheets (Page, Pages, Sheet, Sheets, config.CitationClass, Periodical_origin, sepc, NoPP, use_lowercase);&lt;br /&gt;
&lt;br /&gt;
	At = utilities.is_set (At) and (sepc .. &amp;quot; &amp;quot; .. At) or &amp;quot;&amp;quot;;&lt;br /&gt;
	Position = utilities.is_set (Position) and (sepc .. &amp;quot; &amp;quot; .. Position) or &amp;quot;&amp;quot;;&lt;br /&gt;
	if config.CitationClass == &#039;map&#039; then&lt;br /&gt;
		local Sections = A[&#039;Sections&#039;];											-- Section (singular) is an alias of Chapter so set earlier&lt;br /&gt;
		local Inset = A[&#039;Inset&#039;];&lt;br /&gt;
		&lt;br /&gt;
		if utilities.is_set ( Inset ) then&lt;br /&gt;
			Inset = sepc .. &amp;quot; &amp;quot; .. wrap_msg (&#039;inset&#039;, Inset, use_lowercase);&lt;br /&gt;
		end			&lt;br /&gt;
&lt;br /&gt;
		if utilities.is_set ( Sections ) then&lt;br /&gt;
			Section = sepc .. &amp;quot; &amp;quot; .. wrap_msg (&#039;sections&#039;, Sections, use_lowercase);&lt;br /&gt;
		elseif utilities.is_set ( Section ) then&lt;br /&gt;
			Section = sepc .. &amp;quot; &amp;quot; .. wrap_msg (&#039;section&#039;, Section, use_lowercase);&lt;br /&gt;
		end&lt;br /&gt;
		At = At .. Inset .. Section;		&lt;br /&gt;
	end	&lt;br /&gt;
&lt;br /&gt;
	local Others = A[&#039;Others&#039;];&lt;br /&gt;
	if utilities.is_set (Others) and 0 == #a and 0 == #e then					-- add maint cat when |others= has value and used without |author=, |editor=&lt;br /&gt;
		if config.CitationClass == &amp;quot;AV-media-notes&amp;quot;&lt;br /&gt;
		or config.CitationClass == &amp;quot;audio-visual&amp;quot; then							-- special maint for AV/M which has a lot of &#039;false&#039; positives right now&lt;br /&gt;
			utilities.set_message (&#039;maint_others_avm&#039;)&lt;br /&gt;
		else&lt;br /&gt;
			utilities.set_message (&#039;maint_others&#039;);&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	Others = utilities.is_set (Others) and (sepc .. &amp;quot; &amp;quot; .. Others) or &amp;quot;&amp;quot;;&lt;br /&gt;
	&lt;br /&gt;
	if utilities.is_set (Translators) then&lt;br /&gt;
		Others = safe_join ({sepc .. &#039; &#039;, wrap_msg (&#039;translated&#039;, Translators, use_lowercase), Others}, sepc);&lt;br /&gt;
	end&lt;br /&gt;
	if utilities.is_set (Interviewers) then&lt;br /&gt;
		Others = safe_join ({sepc .. &#039; &#039;, wrap_msg (&#039;interview&#039;, Interviewers, use_lowercase), Others}, sepc);&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local TitleNote = A[&#039;TitleNote&#039;];&lt;br /&gt;
	TitleNote = utilities.is_set (TitleNote) and (sepc .. &amp;quot; &amp;quot; .. TitleNote) or &amp;quot;&amp;quot;;&lt;br /&gt;
	if utilities.is_set (Edition) then&lt;br /&gt;
		if Edition:match (&#039;%f[%a][Ee]d%n?%.?$&#039;) or Edition:match (&#039;%f[%a][Ee]dition$&#039;) then -- Ed, ed, Ed., ed., Edn, edn, Edn., edn.&lt;br /&gt;
			utilities.set_message (&#039;err_extra_text_edition&#039;);					 -- add error message&lt;br /&gt;
		end&lt;br /&gt;
		Edition = &amp;quot; &amp;quot; .. wrap_msg (&#039;edition&#039;, Edition);&lt;br /&gt;
	else&lt;br /&gt;
		Edition = &#039;&#039;;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	Series = utilities.is_set (Series) and wrap_msg (&#039;series&#039;, {sepc, Series}) or &amp;quot;&amp;quot;;	-- not the same as SeriesNum&lt;br /&gt;
	local Agency = A[&#039;Agency&#039;];&lt;br /&gt;
	Agency = utilities.is_set (Agency) and wrap_msg (&#039;agency&#039;, {sepc, Agency}) or &amp;quot;&amp;quot;;&lt;br /&gt;
	Volume = format_volume_issue (Volume, Issue, config.CitationClass, Periodical_origin, sepc, use_lowercase);&lt;br /&gt;
&lt;br /&gt;
	if utilities.is_set (AccessDate) then&lt;br /&gt;
		local retrv_text = &amp;quot; &amp;quot; .. cfg.messages[&#039;retrieved&#039;]&lt;br /&gt;
&lt;br /&gt;
		AccessDate = nowrap_date (AccessDate);									-- wrap in nowrap span if date in appropriate format&lt;br /&gt;
		if (sepc ~= &amp;quot;.&amp;quot;) then retrv_text = retrv_text:lower() end				-- if mode is cs2, lower case&lt;br /&gt;
		AccessDate = utilities.substitute (retrv_text, AccessDate);				-- add retrieved text&lt;br /&gt;
&lt;br /&gt;
		AccessDate = utilities.substitute (cfg.presentation[&#039;accessdate&#039;], {sepc, AccessDate});	-- allow editors to hide accessdates&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if utilities.is_set (ID) then ID = sepc .. &amp;quot; &amp;quot; .. ID; end&lt;br /&gt;
	&lt;br /&gt;
	local Docket = A[&#039;Docket&#039;];&lt;br /&gt;
   	if &amp;quot;thesis&amp;quot; == config.CitationClass and utilities.is_set (Docket) then&lt;br /&gt;
		ID = sepc .. &amp;quot; Docket &amp;quot; .. Docket .. ID;&lt;br /&gt;
	end&lt;br /&gt;
   	if &amp;quot;report&amp;quot; == config.CitationClass and utilities.is_set (Docket) then		-- for cite report when |docket= is set&lt;br /&gt;
		ID = sepc .. &#039; &#039; .. Docket;												-- overwrite ID even if |id= is set&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if utilities.is_set (URL) then&lt;br /&gt;
		URL = &amp;quot; &amp;quot; .. external_link( URL, nil, URL_origin, UrlAccess );&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local Quote = A[&#039;Quote&#039;];&lt;br /&gt;
	local TransQuote = A[&#039;TransQuote&#039;];&lt;br /&gt;
	local ScriptQuote = A[&#039;ScriptQuote&#039;];&lt;br /&gt;
	if utilities.is_set (Quote) or utilities.is_set (TransQuote) or utilities.is_set (ScriptQuote) then&lt;br /&gt;
&lt;br /&gt;
		if utilities.is_set (Quote) then&lt;br /&gt;
			if Quote:sub(1, 1) == &#039;&amp;quot;&#039; and Quote:sub(-1, -1) == &#039;&amp;quot;&#039; then			-- if first and last characters of quote are quote marks&lt;br /&gt;
				Quote = Quote:sub(2, -2);										-- strip them off&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		Quote = utilities.wrap_style (&#039;quoted-text&#039;, Quote );					-- wrap in &amp;lt;q&amp;gt;...&amp;lt;/q&amp;gt; tags&lt;br /&gt;
	&lt;br /&gt;
		if utilities.is_set (ScriptQuote) then&lt;br /&gt;
			Quote = script_concatenate (Quote, ScriptQuote, &#039;script-quote&#039;);	-- &amp;lt;bdi&amp;gt; tags, lang attribute, categorization, etc.; must be done after quote is wrapped&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		if utilities.is_set (TransQuote) then&lt;br /&gt;
			if TransQuote:sub(1, 1) == &#039;&amp;quot;&#039; and TransQuote:sub(-1, -1) == &#039;&amp;quot;&#039; then -- if first and last characters of |trans-quote are quote marks&lt;br /&gt;
				TransQuote = TransQuote:sub(2, -2); -- strip them off&lt;br /&gt;
			end&lt;br /&gt;
			Quote = Quote .. &amp;quot; &amp;quot; .. utilities.wrap_style (&#039;trans-quoted-title&#039;, TransQuote );&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		if utilities.is_set (QuotePage) or utilities.is_set (QuotePages) then	-- add page prefix&lt;br /&gt;
			local quote_prefix = &#039;&#039;;&lt;br /&gt;
			if utilities.is_set (QuotePage) then&lt;br /&gt;
				extra_text_in_page_check (QuotePage, &#039;quote-page&#039;);				-- add to maint cat if |quote-page= value begins with what looks like p., pp., etc.&lt;br /&gt;
				if not NoPP then&lt;br /&gt;
					quote_prefix = utilities.substitute (cfg.messages[&#039;p-prefix&#039;], {sepc, QuotePage}), &#039;&#039;, &#039;&#039;, &#039;&#039;;&lt;br /&gt;
				else&lt;br /&gt;
					quote_prefix = utilities.substitute (cfg.messages[&#039;nopp&#039;], {sepc, QuotePage}), &#039;&#039;, &#039;&#039;, &#039;&#039;;&lt;br /&gt;
				end&lt;br /&gt;
			elseif utilities.is_set (QuotePages) then&lt;br /&gt;
				extra_text_in_page_check (QuotePages, &#039;quote-pages&#039;);			-- add to maint cat if |quote-pages= value begins with what looks like p., pp., etc.&lt;br /&gt;
				if tonumber(QuotePages) ~= nil and not NoPP then				-- if only digits, assume single page&lt;br /&gt;
					quote_prefix = utilities.substitute (cfg.messages[&#039;p-prefix&#039;], {sepc, QuotePages}), &#039;&#039;, &#039;&#039;;&lt;br /&gt;
				elseif not NoPP then&lt;br /&gt;
					quote_prefix = utilities.substitute (cfg.messages[&#039;pp-prefix&#039;], {sepc, QuotePages}), &#039;&#039;, &#039;&#039;;&lt;br /&gt;
				else&lt;br /&gt;
					quote_prefix = utilities.substitute (cfg.messages[&#039;nopp&#039;], {sepc, QuotePages}), &#039;&#039;, &#039;&#039;;&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
                        &lt;br /&gt;
			Quote = quote_prefix .. &amp;quot;: &amp;quot; .. Quote;&lt;br /&gt;
		else&lt;br /&gt;
			Quote = sepc .. &amp;quot; &amp;quot; .. Quote;&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		PostScript = &amp;quot;&amp;quot;;														-- cs1|2 does not supply terminal punctuation when |quote= is set&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- We check length of PostScript here because it will have been nuked by&lt;br /&gt;
	-- the quote parameters. We&#039;d otherwise emit a message even if there wasn&#039;t&lt;br /&gt;
	-- a displayed postscript.&lt;br /&gt;
	-- TODO: Should the max size (1) be configurable?&lt;br /&gt;
	-- TODO: Should we check a specific pattern?&lt;br /&gt;
	if utilities.is_set(PostScript) and mw.ustring.len(PostScript) &amp;gt; 1 then&lt;br /&gt;
		utilities.set_message (&#039;maint_postscript&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local Archived;&lt;br /&gt;
	if utilities.is_set (ArchiveURL) then&lt;br /&gt;
		local arch_text;&lt;br /&gt;
		if not utilities.is_set (ArchiveDate) then&lt;br /&gt;
			utilities.set_message (&#039;err_archive_missing_date&#039;);&lt;br /&gt;
			ArchiveDate = &#039;&#039;;													-- empty string for concatenation&lt;br /&gt;
		end&lt;br /&gt;
		if &amp;quot;live&amp;quot; == UrlStatus then&lt;br /&gt;
			arch_text = cfg.messages[&#039;archived&#039;];&lt;br /&gt;
			if sepc ~= &amp;quot;.&amp;quot; then arch_text = arch_text:lower() end&lt;br /&gt;
			if utilities.is_set (ArchiveDate) then&lt;br /&gt;
				Archived = sepc .. &#039; &#039; .. utilities.substitute ( cfg.messages[&#039;archived-live&#039;],&lt;br /&gt;
					{external_link( ArchiveURL, arch_text, A:ORIGIN(&#039;ArchiveURL&#039;), nil) .. ArchiveFormat, ArchiveDate } );&lt;br /&gt;
			else&lt;br /&gt;
				Archived = &#039;&#039;;&lt;br /&gt;
			end&lt;br /&gt;
			if not utilities.is_set (OriginalURL) then&lt;br /&gt;
				utilities.set_message (&#039;err_archive_missing_url&#039;);&lt;br /&gt;
				Archived = &#039;&#039;;													-- empty string for concatenation&lt;br /&gt;
			end&lt;br /&gt;
		elseif utilities.is_set (OriginalURL) then								-- UrlStatus is empty, &#039;dead&#039;, &#039;unfit&#039;, &#039;usurped&#039;, &#039;bot: unknown&#039;&lt;br /&gt;
			if utilities.in_array (UrlStatus, {&#039;unfit&#039;, &#039;usurped&#039;, &#039;bot: unknown&#039;}) then&lt;br /&gt;
				arch_text = cfg.messages[&#039;archived-unfit&#039;];&lt;br /&gt;
				if sepc ~= &amp;quot;.&amp;quot; then arch_text = arch_text:lower() end&lt;br /&gt;
				Archived = sepc .. &#039; &#039; .. arch_text .. ArchiveDate;				-- format already styled&lt;br /&gt;
				if &#039;bot: unknown&#039; == UrlStatus then&lt;br /&gt;
					utilities.set_message (&#039;maint_bot_unknown&#039;);				-- and add a category if not already added&lt;br /&gt;
				else&lt;br /&gt;
					utilities.set_message (&#039;maint_unfit&#039;);						-- and add a category if not already added&lt;br /&gt;
				end&lt;br /&gt;
			else																-- UrlStatus is empty, &#039;dead&#039;&lt;br /&gt;
				arch_text = cfg.messages[&#039;archived-dead&#039;];&lt;br /&gt;
				if sepc ~= &amp;quot;.&amp;quot; then arch_text = arch_text:lower() end&lt;br /&gt;
				if utilities.is_set (ArchiveDate) then&lt;br /&gt;
					Archived = sepc .. &amp;quot; &amp;quot; .. utilities.substitute ( arch_text,&lt;br /&gt;
						{ external_link( OriginalURL, cfg.messages[&#039;original&#039;], OriginalURL_origin, OriginalAccess ) .. OriginalFormat, ArchiveDate } );	-- format already styled&lt;br /&gt;
				else&lt;br /&gt;
					Archived = &#039;&#039;;												-- unset for concatenation&lt;br /&gt;
				end&lt;br /&gt;
			end	&lt;br /&gt;
		else																	-- OriginalUrl not set&lt;br /&gt;
			arch_text = cfg.messages[&#039;archived-missing&#039;];&lt;br /&gt;
			if sepc ~= &amp;quot;.&amp;quot; then arch_text = arch_text:lower() end&lt;br /&gt;
			utilities.set_message (&#039;err_archive_missing_url&#039;);&lt;br /&gt;
			Archived = &#039;&#039;;														-- empty string for concatenation&lt;br /&gt;
		end&lt;br /&gt;
	elseif utilities.is_set (ArchiveFormat) then&lt;br /&gt;
		Archived = ArchiveFormat;												-- if set and ArchiveURL not set ArchiveFormat has error message&lt;br /&gt;
	else&lt;br /&gt;
		Archived = &#039;&#039;;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local Lay = &#039;&#039;;&lt;br /&gt;
	local LaySource = A[&#039;LaySource&#039;];&lt;br /&gt;
	local LayURL = A[&#039;LayURL&#039;];&lt;br /&gt;
	local LayFormat = A[&#039;LayFormat&#039;];&lt;br /&gt;
	LayFormat = style_format (LayFormat, LayURL, &#039;lay-format&#039;, &#039;lay-url&#039;);&lt;br /&gt;
	if utilities.is_set (LayURL) then&lt;br /&gt;
		if utilities.is_set (LayDate) then LayDate = &amp;quot; (&amp;quot; .. LayDate .. &amp;quot;)&amp;quot; end&lt;br /&gt;
		if utilities.is_set (LaySource) then &lt;br /&gt;
			LaySource = &amp;quot; &amp;amp;ndash; &#039;&#039;&amp;quot; .. utilities.safe_for_italics (LaySource) .. &amp;quot;&#039;&#039;&amp;quot;;&lt;br /&gt;
		else&lt;br /&gt;
			LaySource = &amp;quot;&amp;quot;;&lt;br /&gt;
		end&lt;br /&gt;
		if sepc == &#039;.&#039; then&lt;br /&gt;
			Lay = sepc .. &amp;quot; &amp;quot; .. external_link( LayURL, cfg.messages[&#039;lay summary&#039;], A:ORIGIN(&#039;LayURL&#039;), nil ) .. LayFormat .. LaySource .. LayDate&lt;br /&gt;
		else&lt;br /&gt;
			Lay = sepc .. &amp;quot; &amp;quot; .. external_link( LayURL, cfg.messages[&#039;lay summary&#039;]:lower(), A:ORIGIN(&#039;LayURL&#039;), nil ) .. LayFormat .. LaySource .. LayDate&lt;br /&gt;
		end			&lt;br /&gt;
	elseif utilities.is_set (LayFormat) then									-- Test if |lay-format= is given without giving a |lay-url=&lt;br /&gt;
		Lay = sepc .. LayFormat;												-- if set and LayURL not set, then LayFormat has error message&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local TranscriptURL = A[&#039;TranscriptURL&#039;]&lt;br /&gt;
	local TranscriptFormat = A[&#039;TranscriptFormat&#039;];&lt;br /&gt;
	TranscriptFormat = style_format (TranscriptFormat, TranscriptURL, &#039;transcript-format&#039;, &#039;transcripturl&#039;);&lt;br /&gt;
	local Transcript = A[&#039;Transcript&#039;];&lt;br /&gt;
	local TranscriptURL_origin = A:ORIGIN(&#039;TranscriptURL&#039;);						-- get name of parameter that holds TranscriptURL&lt;br /&gt;
	if utilities.is_set (Transcript) then&lt;br /&gt;
		if utilities.is_set (TranscriptURL) then&lt;br /&gt;
			Transcript = external_link( TranscriptURL, Transcript, TranscriptURL_origin, nil );&lt;br /&gt;
		end&lt;br /&gt;
		Transcript = sepc .. &#039; &#039; .. Transcript .. TranscriptFormat;&lt;br /&gt;
	elseif utilities.is_set (TranscriptURL) then&lt;br /&gt;
		Transcript = external_link( TranscriptURL, nil, TranscriptURL_origin, nil );&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local Publisher;&lt;br /&gt;
	if utilities.is_set (PublicationDate) then&lt;br /&gt;
		PublicationDate = wrap_msg (&#039;published&#039;, PublicationDate);&lt;br /&gt;
	end&lt;br /&gt;
	if utilities.is_set (PublisherName) then&lt;br /&gt;
		if utilities.is_set (PublicationPlace) then&lt;br /&gt;
			Publisher = sepc .. &amp;quot; &amp;quot; .. PublicationPlace .. &amp;quot;: &amp;quot; .. PublisherName .. PublicationDate;&lt;br /&gt;
		else&lt;br /&gt;
			Publisher = sepc .. &amp;quot; &amp;quot; .. PublisherName .. PublicationDate;  &lt;br /&gt;
		end			&lt;br /&gt;
	elseif utilities.is_set (PublicationPlace) then &lt;br /&gt;
		Publisher= sepc .. &amp;quot; &amp;quot; .. PublicationPlace .. PublicationDate;&lt;br /&gt;
	else &lt;br /&gt;
		Publisher = PublicationDate;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local TransPeriodical =  A[&#039;TransPeriodical&#039;];&lt;br /&gt;
	local TransPeriodical_origin =  A:ORIGIN (&#039;TransPeriodical&#039;);&lt;br /&gt;
	-- Several of the above rely upon detecting this as nil, so do it last.&lt;br /&gt;
	if (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical) or utilities.is_set (TransPeriodical)) then&lt;br /&gt;
		if utilities.is_set (Title) or utilities.is_set (TitleNote) then &lt;br /&gt;
			Periodical = sepc .. &amp;quot; &amp;quot; .. format_periodical (ScriptPeriodical, ScriptPeriodical_origin, Periodical, TransPeriodical, TransPeriodical_origin);&lt;br /&gt;
		else &lt;br /&gt;
			Periodical = format_periodical (ScriptPeriodical, ScriptPeriodical_origin, Periodical, TransPeriodical, TransPeriodical_origin);&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local Language = A[&#039;Language&#039;];&lt;br /&gt;
	if utilities.is_set (Language) then&lt;br /&gt;
		Language = language_parameter (Language);								-- format, categories, name from ISO639-1, etc.&lt;br /&gt;
	else&lt;br /&gt;
		Language=&#039;&#039;;															-- language not specified so make sure this is an empty string;&lt;br /&gt;
	--[[ TODO: need to extract the wrap_msg from language_parameter&lt;br /&gt;
	so that we can solve parentheses bunching problem with Format/Language/TitleType&lt;br /&gt;
	]]&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	--[[&lt;br /&gt;
	Handle the oddity that is cite speech.  This code overrides whatever may be the value assigned to TitleNote (through |department=) and forces it to be &amp;quot; (Speech)&amp;quot; so that&lt;br /&gt;
	the annotation directly follows the |title= parameter value in the citation rather than the |event= parameter value (if provided).&lt;br /&gt;
	]]&lt;br /&gt;
	if &amp;quot;speech&amp;quot; == config.CitationClass then									-- cite speech only&lt;br /&gt;
		TitleNote = TitleType;													-- move TitleType to TitleNote so that it renders ahead of |event=&lt;br /&gt;
		TitleType = &#039;&#039;;															-- and unset&lt;br /&gt;
&lt;br /&gt;
		if utilities.is_set (Periodical) then									-- if Periodical, perhaps because of an included |website= or |journal= parameter &lt;br /&gt;
			if utilities.is_set (Conference) then								-- and if |event= is set&lt;br /&gt;
				Conference = Conference .. sepc .. &amp;quot; &amp;quot;;							-- then add appropriate punctuation to the end of the Conference variable before rendering&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Piece all bits together at last.  Here, all should be non-nil.&lt;br /&gt;
	-- We build things this way because it is more efficient in LUA&lt;br /&gt;
	-- not to keep reassigning to the same string variable over and over.&lt;br /&gt;
&lt;br /&gt;
	local tcommon;&lt;br /&gt;
	local tcommon2;																-- used for book cite when |contributor= is set&lt;br /&gt;
	&lt;br /&gt;
	if utilities.in_array (config.CitationClass, {&amp;quot;journal&amp;quot;, &amp;quot;citation&amp;quot;}) and utilities.is_set (Periodical) then&lt;br /&gt;
		if utilities.is_set (Others) then Others = safe_join ({Others, sepc .. &amp;quot; &amp;quot;}, sepc) end		-- add terminal punctuation &amp;amp; space; check for dup sepc; TODO why do we need to do this here?&lt;br /&gt;
		tcommon = safe_join( {Others, Title, TitleNote, Conference, Periodical, Format, TitleType, Series, Language, Edition, Publisher, Agency, Volume}, sepc );&lt;br /&gt;
	elseif utilities.in_array (config.CitationClass, {&amp;quot;book&amp;quot;, &amp;quot;citation&amp;quot;}) and not utilities.is_set (Periodical) then		-- special cases for book cites&lt;br /&gt;
		if utilities.is_set (Contributors) then									-- when we are citing foreword, preface, introduction, etc.&lt;br /&gt;
			tcommon = safe_join( {Title, TitleNote}, sepc );					-- author and other stuff will come after this and before tcommon2&lt;br /&gt;
			tcommon2 = safe_join( {Conference, Periodical, Format, TitleType, Series, Language, Volume, Others, Edition, Publisher, Agency}, sepc );&lt;br /&gt;
		else&lt;br /&gt;
			tcommon = safe_join( {Title, TitleNote, Conference, Periodical, Format, TitleType, Series, Language, Volume, Others, Edition, Publisher, Agency}, sepc );&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
	elseif &#039;map&#039; == config.CitationClass then									-- special cases for cite map&lt;br /&gt;
		if utilities.is_set (Chapter) then										-- map in a book; TitleType is part of Chapter&lt;br /&gt;
			tcommon = safe_join( {Title, Format, Edition, Scale, Series, Language, Cartography, Others, Publisher, Volume}, sepc );&lt;br /&gt;
		elseif utilities.is_set (Periodical) then								-- map in a periodical&lt;br /&gt;
			tcommon = safe_join( {Title, TitleType, Format, Periodical, Scale, Series, Language, Cartography, Others, Publisher, Volume}, sepc );&lt;br /&gt;
		else																	-- a sheet or stand-alone map&lt;br /&gt;
			tcommon = safe_join( {Title, TitleType, Format, Edition, Scale, Series, Language, Cartography, Others, Publisher}, sepc );&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
	elseif &#039;episode&#039; == config.CitationClass then								-- special case for cite episode&lt;br /&gt;
		tcommon = safe_join( {Title, TitleNote, TitleType, Series, Language, Edition, Publisher}, sepc );&lt;br /&gt;
&lt;br /&gt;
	else																		-- all other CS1 templates&lt;br /&gt;
		tcommon = safe_join( {Title, TitleNote, Conference, Periodical, Format, TitleType, Series, Language, &lt;br /&gt;
			Volume, Others, Edition, Publisher, Agency}, sepc );&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if #ID_list &amp;gt; 0 then&lt;br /&gt;
		ID_list = safe_join( { sepc .. &amp;quot; &amp;quot;,  table.concat( ID_list, sepc .. &amp;quot; &amp;quot; ), ID }, sepc );&lt;br /&gt;
	else&lt;br /&gt;
		ID_list = ID;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local Via = A[&#039;Via&#039;];&lt;br /&gt;
	Via = utilities.is_set (Via) and  wrap_msg (&#039;via&#039;, Via) or &#039;&#039;;&lt;br /&gt;
	local idcommon;&lt;br /&gt;
	if &#039;audio-visual&#039; == config.CitationClass or &#039;episode&#039; == config.CitationClass then	-- special case for cite AV media &amp;amp; cite episode position transcript&lt;br /&gt;
		idcommon = safe_join( { ID_list, URL, Archived, Transcript, AccessDate, Via, Lay, Quote }, sepc );&lt;br /&gt;
	else&lt;br /&gt;
		idcommon = safe_join( { ID_list, URL, Archived, AccessDate, Via, Lay, Quote }, sepc );&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local text;&lt;br /&gt;
	local pgtext = Position .. Sheet .. Sheets .. Page .. Pages .. At;&lt;br /&gt;
&lt;br /&gt;
	local OrigDate = A[&#039;OrigDate&#039;];&lt;br /&gt;
	OrigDate = utilities.is_set (OrigDate) and wrap_msg (&#039;origdate&#039;, OrigDate) or &#039;&#039;;&lt;br /&gt;
	if utilities.is_set (Date) then&lt;br /&gt;
		if utilities.is_set (Authors) or utilities.is_set (Editors) then		-- date follows authors or editors when authors not set&lt;br /&gt;
			Date = &amp;quot; (&amp;quot; .. Date .. &amp;quot;)&amp;quot; .. OrigDate .. sepc .. &amp;quot; &amp;quot;;				-- in parentheses&lt;br /&gt;
		else																	-- neither of authors and editors set&lt;br /&gt;
			if (string.sub(tcommon, -1, -1) == sepc) then						-- if the last character of tcommon is sepc&lt;br /&gt;
				Date = &amp;quot; &amp;quot; .. Date .. OrigDate;									-- Date does not begin with sepc&lt;br /&gt;
			else&lt;br /&gt;
				Date = sepc .. &amp;quot; &amp;quot; .. Date .. OrigDate;							-- Date begins with sepc&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end	&lt;br /&gt;
	if utilities.is_set (Authors) then&lt;br /&gt;
		if (not utilities.is_set (Date)) then									-- when date is set it&#039;s in parentheses; no Authors termination&lt;br /&gt;
			Authors = terminate_name_list (Authors, sepc);						-- when no date, terminate with 0 or 1 sepc and a space&lt;br /&gt;
		end&lt;br /&gt;
		if utilities.is_set (Editors) then&lt;br /&gt;
			local in_text = &amp;quot; &amp;quot;;&lt;br /&gt;
			local post_text = &amp;quot;&amp;quot;;&lt;br /&gt;
			if utilities.is_set (Chapter) and 0 == #c then&lt;br /&gt;
				in_text = in_text .. cfg.messages[&#039;in&#039;] .. &amp;quot; &amp;quot;&lt;br /&gt;
				if (sepc ~= &#039;.&#039;) then&lt;br /&gt;
					in_text = in_text:lower()									-- lowercase for cs2&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			if EditorCount &amp;lt;= 1 then&lt;br /&gt;
				post_text = &amp;quot; (&amp;quot; .. cfg.messages[&#039;editor&#039;] .. &amp;quot;)&amp;quot;;				-- be consistent with no-author, no-date case&lt;br /&gt;
			else&lt;br /&gt;
				post_text = &amp;quot; (&amp;quot; .. cfg.messages[&#039;editors&#039;] .. &amp;quot;)&amp;quot;;&lt;br /&gt;
			end&lt;br /&gt;
			Editors = terminate_name_list (in_text .. Editors .. post_text, sepc);	-- terminate with 0 or 1 sepc and a space&lt;br /&gt;
		end&lt;br /&gt;
		if utilities.is_set (Contributors) then									-- book cite and we&#039;re citing the intro, preface, etc.&lt;br /&gt;
			local by_text = sepc .. &#039; &#039; .. cfg.messages[&#039;by&#039;] .. &#039; &#039;;&lt;br /&gt;
			if (sepc ~= &#039;.&#039;) then by_text = by_text:lower() end					-- lowercase for cs2&lt;br /&gt;
			Authors = by_text .. Authors;										-- author follows title so tweak it here&lt;br /&gt;
			if utilities.is_set (Editors) and utilities.is_set (Date) then		-- when Editors make sure that Authors gets terminated&lt;br /&gt;
				Authors = terminate_name_list (Authors, sepc);					-- terminate with 0 or 1 sepc and a space&lt;br /&gt;
			end&lt;br /&gt;
			if (not utilities.is_set (Date)) then								-- when date is set it&#039;s in parentheses; no Contributors termination&lt;br /&gt;
				Contributors = terminate_name_list (Contributors, sepc);		-- terminate with 0 or 1 sepc and a space&lt;br /&gt;
			end&lt;br /&gt;
			text = safe_join( {Contributors, Date, Chapter, tcommon, Authors, Place, Editors, tcommon2, pgtext, idcommon }, sepc );&lt;br /&gt;
		else&lt;br /&gt;
			text = safe_join( {Authors, Date, Chapter, Place, Editors, tcommon, pgtext, idcommon }, sepc );&lt;br /&gt;
		end&lt;br /&gt;
	elseif utilities.is_set (Editors) then&lt;br /&gt;
		if utilities.is_set (Date) then&lt;br /&gt;
			if EditorCount &amp;lt;= 1 then&lt;br /&gt;
				Editors = Editors .. &amp;quot;, &amp;quot; .. cfg.messages[&#039;editor&#039;];&lt;br /&gt;
			else&lt;br /&gt;
				Editors = Editors .. &amp;quot;, &amp;quot; .. cfg.messages[&#039;editors&#039;];&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			if EditorCount &amp;lt;= 1 then&lt;br /&gt;
				Editors = Editors .. &amp;quot; (&amp;quot; .. cfg.messages[&#039;editor&#039;] .. &amp;quot;)&amp;quot; .. sepc .. &amp;quot; &amp;quot;&lt;br /&gt;
			else&lt;br /&gt;
				Editors = Editors .. &amp;quot; (&amp;quot; .. cfg.messages[&#039;editors&#039;] .. &amp;quot;)&amp;quot; .. sepc .. &amp;quot; &amp;quot;&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		text = safe_join( {Editors, Date, Chapter, Place, tcommon, pgtext, idcommon}, sepc );&lt;br /&gt;
	else&lt;br /&gt;
		if utilities.in_array (config.CitationClass, {&amp;quot;journal&amp;quot;, &amp;quot;citation&amp;quot;}) and utilities.is_set (Periodical) then&lt;br /&gt;
			text = safe_join( {Chapter, Place, tcommon, pgtext, Date, idcommon}, sepc );&lt;br /&gt;
		else&lt;br /&gt;
			text = safe_join( {Chapter, Place, tcommon, Date, pgtext, idcommon}, sepc );&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if utilities.is_set (PostScript) and PostScript ~= sepc then&lt;br /&gt;
		text = safe_join( {text, sepc}, sepc ); 								-- Deals with italics, spaces, etc.&lt;br /&gt;
		text = text:sub(1, -sepc:len() - 1);&lt;br /&gt;
	end	&lt;br /&gt;
	&lt;br /&gt;
	text = safe_join( {text, PostScript}, sepc );&lt;br /&gt;
&lt;br /&gt;
	-- Now enclose the whole thing in a &amp;lt;cite&amp;gt; element&lt;br /&gt;
	local options_t = {};&lt;br /&gt;
	options_t.class = cite_class_attribute_make (config.CitationClass, Mode);&lt;br /&gt;
&lt;br /&gt;
	local Ref = is_valid_parameter_value (A[&#039;Ref&#039;], A:ORIGIN(&#039;Ref&#039;), cfg.keywords_lists[&#039;ref&#039;], nil, true);	-- nil when |ref=harv; A[&#039;Ref&#039;] else&lt;br /&gt;
&lt;br /&gt;
	if &#039;none&#039; ~= cfg.keywords_xlate[(Ref and Ref:lower()) or &#039;&#039;] then&lt;br /&gt;
		local namelist_t = {};													-- holds selected contributor, author, editor name list&lt;br /&gt;
		local year = first_set ({Year, anchor_year}, 2);						-- Year first for legacy citations and for YMD dates that require disambiguation&lt;br /&gt;
&lt;br /&gt;
		if #c &amp;gt; 0 then															-- if there is a contributor list&lt;br /&gt;
			namelist_t = c;														-- select it&lt;br /&gt;
		elseif #a &amp;gt; 0 then														-- or an author list&lt;br /&gt;
			namelist_t = a;&lt;br /&gt;
		elseif #e &amp;gt; 0 then														-- or an editor list&lt;br /&gt;
			namelist_t = e;&lt;br /&gt;
		end&lt;br /&gt;
		local citeref_id;&lt;br /&gt;
		if #namelist_t &amp;gt; 0 then													-- if there are names in namelist_t&lt;br /&gt;
			citeref_id = make_citeref_id (namelist_t, year);					-- go make the CITEREF anchor&lt;br /&gt;
			if mw.uri.anchorEncode (citeref_id) == ((Ref and mw.uri.anchorEncode (Ref)) or &#039;&#039;) then	-- Ref may already be encoded (by {{sfnref}}) so citeref_id must be encoded before comparison&lt;br /&gt;
				utilities.set_message (&#039;maint_ref_duplicates_default&#039;);&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			citeref_id = &#039;&#039;;													-- unset&lt;br /&gt;
		end&lt;br /&gt;
		options_t.id = Ref or citeref_id;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if string.len (text:gsub(&#039;%b&amp;lt;&amp;gt;&#039;, &#039;&#039;)) &amp;lt;= 2 then								-- remove html and html-like tags; then get length of what remains; &lt;br /&gt;
		z.error_cats_t = {};													-- blank the categories list&lt;br /&gt;
		z.error_msgs_t = {};													-- blank the error messages list&lt;br /&gt;
		OCinSoutput = nil;														-- blank the metadata string&lt;br /&gt;
		text = &#039;&#039;;																-- blank the the citation&lt;br /&gt;
		utilities.set_message (&#039;err_empty_citation&#039;);							-- set empty citation message and category&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local render_t = {};														-- here we collect the final bits for concatenation into the rendered citation&lt;br /&gt;
&lt;br /&gt;
	if utilities.is_set (options_t.id) then										-- here we wrap the rendered citation in &amp;lt;cite ...&amp;gt;...&amp;lt;/cite&amp;gt; tags&lt;br /&gt;
		table.insert (render_t, utilities.substitute (cfg.presentation[&#039;cite-id&#039;], {mw.uri.anchorEncode(options_t.id), mw.text.nowiki(options_t.class), text}));	-- when |ref= is set or when there is a namelist&lt;br /&gt;
	else&lt;br /&gt;
		table.insert (render_t, utilities.substitute (cfg.presentation[&#039;cite&#039;], {mw.text.nowiki(options_t.class), text}));	-- when |ref=none or when namelist_t empty and |ref= is missing or is empty&lt;br /&gt;
	end		&lt;br /&gt;
&lt;br /&gt;
	if OCinSoutput then															-- blanked when citation is &#039;empty&#039; so don&#039;t bother to add boilerplate metadata span&lt;br /&gt;
		table.insert (render_t, utilities.substitute (cfg.presentation[&#039;ocins&#039;], OCinSoutput));	-- format and append metadata to the citation&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local template_name = (&#039;citation&#039; == config.CitationClass) and &#039;citation&#039; or &#039;cite &#039; .. (cfg.citation_class_map_t[config.CitationClass] or config.CitationClass);&lt;br /&gt;
	local template_link = &#039;[[Template:&#039; .. template_name .. &#039;|&#039; .. template_name .. &#039;]]&#039;;&lt;br /&gt;
	local msg_prefix = &#039;&amp;lt;code class=&amp;quot;cs1-code&amp;quot;&amp;gt;{{&#039; .. template_link .. &#039;}}&amp;lt;/code&amp;gt;: &#039;;&lt;br /&gt;
&lt;br /&gt;
	if 0 ~= #z.error_msgs_t then&lt;br /&gt;
		mw.addWarning (utilities.substitute (cfg.messages.warning_msg_e, template_link));&lt;br /&gt;
&lt;br /&gt;
		table.insert (render_t, &#039; &#039;);											-- insert a space between citation and its error messages&lt;br /&gt;
		table.sort (z.error_msgs_t);											-- sort the error messages list; sorting includes wrapping &amp;lt;span&amp;gt; and &amp;lt;code&amp;gt; tags; hidden-error sorts ahead of visible-error&lt;br /&gt;
&lt;br /&gt;
		local hidden = true;													-- presume that the only error messages emited by this template are hidden&lt;br /&gt;
		for _, v in ipairs (z.error_msgs_t) do									-- spin through the list of error messages&lt;br /&gt;
			if v:find (&#039;cs1-visible-error&#039;, 1, true) then						-- look for the visible error class name&lt;br /&gt;
				hidden = false;													-- found one; so don&#039;t hide the error message prefix&lt;br /&gt;
				break;															-- and done because no need to look further&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		z.error_msgs_t[1] = table.concat ({utilities.error_comment (msg_prefix, hidden), z.error_msgs_t[1]});	-- add error message prefix to first error message to prevent extraneous punctuation&lt;br /&gt;
		table.insert (render_t, table.concat (z.error_msgs_t, &#039;; &#039;));			-- make a big string of error messages and add it to the rendering&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if 0 ~= #z.maint_cats_t then&lt;br /&gt;
		mw.addWarning (utilities.substitute (cfg.messages.warning_msg_m, template_link));&lt;br /&gt;
&lt;br /&gt;
		table.sort (z.maint_cats_t);											-- sort the maintenance messages list&lt;br /&gt;
&lt;br /&gt;
		local maint_msgs_t = {};												-- here we collect all of the maint messages&lt;br /&gt;
&lt;br /&gt;
		if 0 == #z.error_msgs_t then											-- if no error messages&lt;br /&gt;
			table.insert (maint_msgs_t, msg_prefix);							-- insert message prefix in maint message livery&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		for _, v in ipairs( z.maint_cats_t ) do									-- append maintenance categories&lt;br /&gt;
			table.insert (maint_msgs_t, 										-- assemble new maint message and add it to the maint_msgs_t table&lt;br /&gt;
				table.concat ({v, &#039; (&#039;, utilities.substitute (cfg.messages[&#039;:cat wikilink&#039;], v), &#039;)&#039;})&lt;br /&gt;
				);&lt;br /&gt;
		end&lt;br /&gt;
		table.insert (render_t, utilities.substitute (cfg.presentation[&#039;hidden-maint&#039;], table.concat (maint_msgs_t, &#039; &#039;)));	-- wrap the group of maint messages with proper presentation and save&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if not no_tracking_cats then&lt;br /&gt;
		for _, v in ipairs (z.error_cats_t) do									-- append error categories&lt;br /&gt;
			table.insert (render_t, utilities.substitute (cfg.messages[&#039;cat wikilink&#039;], v));&lt;br /&gt;
		end&lt;br /&gt;
		for _, v in ipairs (z.maint_cats_t) do									-- append maintenance categories&lt;br /&gt;
			table.insert (render_t, utilities.substitute (cfg.messages[&#039;cat wikilink&#039;], v));&lt;br /&gt;
		end&lt;br /&gt;
		for _, v in ipairs (z.prop_cats_t) do									-- append properties categories&lt;br /&gt;
			table.insert (render_t, utilities.substitute (cfg.messages[&#039;cat wikilink&#039;], v));&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return table.concat (render_t);												-- make a big string and done&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; V A L I D A T E &amp;gt;--------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Looks for a parameter&#039;s name in one of several whitelists.&lt;br /&gt;
&lt;br /&gt;
Parameters in the whitelist can have three values:&lt;br /&gt;
	true - active, supported parameters&lt;br /&gt;
	false - deprecated, supported parameters&lt;br /&gt;
	nil - unsupported parameters&lt;br /&gt;
	&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function validate (name, cite_class, empty)&lt;br /&gt;
	local name = tostring (name);&lt;br /&gt;
	local enum_name;															-- for enumerated parameters, is name with enumerator replaced with &#039;#&#039;&lt;br /&gt;
	local state;&lt;br /&gt;
	local function state_test (state, name)										-- local function to do testing of state values&lt;br /&gt;
		if true == state then return true; end									-- valid actively supported parameter&lt;br /&gt;
		if false == state then&lt;br /&gt;
			if empty then return nil; end										-- empty deprecated parameters are treated as unknowns&lt;br /&gt;
			deprecated_parameter (name);										-- parameter is deprecated but still supported&lt;br /&gt;
			return true;&lt;br /&gt;
		end&lt;br /&gt;
		if &#039;tracked&#039; == state then&lt;br /&gt;
			local base_name = name:gsub (&#039;%d&#039;, &#039;&#039;);								-- strip enumerators from parameter names that have them to get the base name&lt;br /&gt;
			utilities.add_prop_cat (&#039;tracked-param&#039;, {base_name}, base_name);	-- add a properties category; &amp;lt;base_name&amp;gt; modifies &amp;lt;key&amp;gt;&lt;br /&gt;
			return true;&lt;br /&gt;
		end&lt;br /&gt;
		return nil;&lt;br /&gt;
	end		&lt;br /&gt;
&lt;br /&gt;
	if name:find (&#039;#&#039;) then														-- # is a cs1|2 reserved character so parameters with # not permitted&lt;br /&gt;
		return nil;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if utilities.in_array (cite_class, whitelist.preprint_template_list ) then	-- limited parameter sets allowed for these templates&lt;br /&gt;
		state = whitelist.limited_basic_arguments[name];&lt;br /&gt;
		if true == state_test (state, name) then return true; end&lt;br /&gt;
&lt;br /&gt;
		state = whitelist.preprint_arguments[cite_class][name];					-- look in the parameter-list for the template identified by cite_class&lt;br /&gt;
		if true == state_test (state, name) then return true; end&lt;br /&gt;
&lt;br /&gt;
																				-- limited enumerated parameters list&lt;br /&gt;
		enum_name = name:gsub(&amp;quot;%d+&amp;quot;, &amp;quot;#&amp;quot; );										-- replace digit(s) with # (last25 becomes last#) (mw.ustring because non-Western &#039;local&#039; digits)&lt;br /&gt;
		state = whitelist.limited_numbered_arguments[enum_name];&lt;br /&gt;
		if true == state_test (state, name) then return true; end&lt;br /&gt;
&lt;br /&gt;
		return false;															-- not supported because not found or name is set to nil&lt;br /&gt;
	end																			-- end limited parameter-set templates&lt;br /&gt;
&lt;br /&gt;
	if utilities.in_array (cite_class, whitelist.unique_param_template_list) then 	-- experiment for template-specific parameters for templates that accept parameters from the basic argument list&lt;br /&gt;
		state = whitelist.unique_arguments[cite_class][name];					-- look in the template-specific parameter-lists for the template identified by cite_class&lt;br /&gt;
		if true == state_test (state, name) then return true; end&lt;br /&gt;
	end																			-- if here, fall into general validation&lt;br /&gt;
		&lt;br /&gt;
	state = whitelist.basic_arguments[name];									-- all other templates; all normal parameters allowed&lt;br /&gt;
	if true == state_test (state, name) then return true; end&lt;br /&gt;
&lt;br /&gt;
																				-- all enumerated parameters allowed&lt;br /&gt;
	enum_name = name:gsub(&amp;quot;%d+&amp;quot;, &amp;quot;#&amp;quot; );											-- replace digit(s) with # (last25 becomes last#) (mw.ustring because non-Western &#039;local&#039; digits)&lt;br /&gt;
	state = whitelist.numbered_arguments[enum_name];&lt;br /&gt;
	if true == state_test (state, name) then return true; end&lt;br /&gt;
&lt;br /&gt;
	return false;																-- not supported because not found or name is set to nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[=[-------------------------&amp;lt; I N T E R _ W I K I _ C H E C K &amp;gt;----------------------------------------------&lt;br /&gt;
&lt;br /&gt;
check &amp;lt;value&amp;gt; for inter-language interwiki-link markup.  &amp;lt;prefix&amp;gt; must be a MediaWiki-recognized language&lt;br /&gt;
code.  when these values have the form (without leading colon):&lt;br /&gt;
	[[&amp;lt;prefix&amp;gt;:link|label]] return label as plain-text&lt;br /&gt;
	[[&amp;lt;prefix&amp;gt;:link]] return &amp;lt;prefix&amp;gt;:link as plain-text&lt;br /&gt;
&lt;br /&gt;
return value as is else&lt;br /&gt;
&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local function inter_wiki_check (parameter, value)&lt;br /&gt;
	local prefix = value:match (&#039;%[%[(%a+):&#039;);									-- get an interwiki prefix if one exists&lt;br /&gt;
	local _;&lt;br /&gt;
	&lt;br /&gt;
	if prefix and cfg.inter_wiki_map[prefix:lower()] then						-- if prefix is in the map, needs preceding colon so&lt;br /&gt;
		utilities.set_message (&#039;err_bad_paramlink&#039;, parameter);					-- emit an error message&lt;br /&gt;
		_, value, _ = utilities.is_wikilink (value);							-- extract label portion from wikilink&lt;br /&gt;
	end&lt;br /&gt;
	return value;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; M I S S I N G _ P I P E _ C H E C K &amp;gt;------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Look at the contents of a parameter. If the content has a string of characters and digits followed by an equal&lt;br /&gt;
sign, compare the alphanumeric string to the list of cs1|2 parameters.  If found, then the string is possibly a&lt;br /&gt;
parameter that is missing its pipe.  There are two tests made:&lt;br /&gt;
	{{cite ... |title=Title access-date=2016-03-17}}	-- the first parameter has a value and whitespace separates that value from the missing pipe parameter name&lt;br /&gt;
	{{cite ... |title=access-date=2016-03-17}}			-- the first parameter has no value (whitespace after the first = is trimmed by MediaWiki)&lt;br /&gt;
cs1|2 shares some parameter names with XML/HTML attributes: class=, title=, etc.  To prevent false positives XML/HTML&lt;br /&gt;
tags are removed before the search.&lt;br /&gt;
&lt;br /&gt;
If a missing pipe is detected, this function adds the missing pipe maintenance category.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function missing_pipe_check (parameter, value)&lt;br /&gt;
	local capture;&lt;br /&gt;
	value = value:gsub (&#039;%b&amp;lt;&amp;gt;&#039;, &#039;&#039;);											-- remove XML/HTML tags because attributes: class=, title=, etc.&lt;br /&gt;
&lt;br /&gt;
	capture = value:match (&#039;%s+(%a[%w%-]+)%s*=&#039;) or value:match (&#039;^(%a[%w%-]+)%s*=&#039;);	-- find and categorize parameters with possible missing pipes&lt;br /&gt;
	if capture and validate (capture) then										-- if the capture is a valid parameter name&lt;br /&gt;
		utilities.set_message (&#039;err_missing_pipe&#039;, parameter);&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; H A S _ E X T R A N E O U S _ P U N C T &amp;gt;--------------------------------------&lt;br /&gt;
&lt;br /&gt;
look for extraneous terminal punctuation in most parameter values; parameters listed in skip table are not checked&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function has_extraneous_punc (param, value)&lt;br /&gt;
	if &#039;number&#039; == type (param) then&lt;br /&gt;
		return;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	param = param:gsub (&#039;%d+&#039;, &#039;#&#039;);											-- enumerated name-list mask params allow terminal punct; normalize &lt;br /&gt;
	if cfg.punct_skip[param] then&lt;br /&gt;
		return;																	-- parameter name found in the skip table so done&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if value:match (&#039;[,;:]$&#039;) then&lt;br /&gt;
		utilities.set_message (&#039;maint_extra_punct&#039;);							-- has extraneous punctuation; add maint cat&lt;br /&gt;
	end&lt;br /&gt;
	if value:match (&#039;^=&#039;) then													-- sometimes an extraneous &#039;=&#039; character appears ...&lt;br /&gt;
		utilities.set_message (&#039;maint_extra_punct&#039;);							-- has extraneous punctuation; add maint cat&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; H A S _ E X T R A N E O U S _ U R L &amp;gt;------------------------------------------&lt;br /&gt;
&lt;br /&gt;
look for extraneous url parameter values; parameters listed in skip table are not checked&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function has_extraneous_url (url_param_t)&lt;br /&gt;
	local url_error_t = {};&lt;br /&gt;
	&lt;br /&gt;
	check_for_url (url_param_t, url_error_t);									-- extraneous url check&lt;br /&gt;
	if 0 ~= #url_error_t then													-- non-zero when there are errors&lt;br /&gt;
		table.sort (url_error_t);&lt;br /&gt;
		utilities.set_message (&#039;err_param_has_ext_link&#039;, {utilities.make_sep_list (#url_error_t, url_error_t)});	-- add this error message&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; C I T A T I O N &amp;gt;--------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
This is used by templates such as {{cite book}} to create the actual citation text.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function citation(frame)&lt;br /&gt;
	Frame = frame;																-- save a copy in case we need to display an error message in preview mode&lt;br /&gt;
	local sandbox = &#039;/sandbox&#039;													-- i18n: replace this rvalue with the name that your wiki uses to identify sandbox subpages&lt;br /&gt;
	is_sandbox = nil ~= string.find (frame:getTitle(), sandbox, 1, true);		-- is this invoke the sandbox module?&lt;br /&gt;
	sandbox = is_sandbox and sandbox or &#039;&#039;;										-- use i18n sandbox to load sandbox modules when this module is the sandox; live modules else&lt;br /&gt;
&lt;br /&gt;
	local pframe = frame:getParent()&lt;br /&gt;
	local styles;&lt;br /&gt;
	&lt;br /&gt;
	cfg = mw.loadData (&#039;Module:Citation/CS1/Configuration&#039; .. sandbox);			-- load sandbox versions of support modules when {{#invoke:Citation/CS1/sandbox|...}}; live modules else&lt;br /&gt;
	whitelist = mw.loadData (&#039;Module:Citation/CS1/Whitelist&#039; .. sandbox);&lt;br /&gt;
	utilities = require (&#039;Module:Citation/CS1/Utilities&#039; .. sandbox);&lt;br /&gt;
	validation = require (&#039;Module:Citation/CS1/Date_validation&#039; .. sandbox);&lt;br /&gt;
	identifiers = require (&#039;Module:Citation/CS1/Identifiers&#039; .. sandbox);&lt;br /&gt;
	metadata = require (&#039;Module:Citation/CS1/COinS&#039; .. sandbox);&lt;br /&gt;
	styles = &#039;Module:Citation/CS1&#039; .. sandbox .. &#039;/styles.css&#039;;&lt;br /&gt;
&lt;br /&gt;
	utilities.set_selected_modules (cfg);										-- so that functions in Utilities can see the selected cfg tables&lt;br /&gt;
	identifiers.set_selected_modules (cfg, utilities);							-- so that functions in Identifiers can see the selected cfg tables and selected Utilities module&lt;br /&gt;
	validation.set_selected_modules (cfg, utilities);							-- so that functions in Date validataion can see selected cfg tables and the selected Utilities module&lt;br /&gt;
	metadata.set_selected_modules (cfg, utilities);								-- so that functions in COinS can see the selected cfg tables and selected Utilities module&lt;br /&gt;
&lt;br /&gt;
	z = utilities.z;															-- table of error and category tables in Module:Citation/CS1/Utilities&lt;br /&gt;
&lt;br /&gt;
	is_preview_mode = not utilities.is_set (frame:preprocess (&#039;{{REVISIONID}}&#039;));&lt;br /&gt;
&lt;br /&gt;
	local args = {};															-- table where we store all of the template&#039;s arguments&lt;br /&gt;
	local suggestions = {};														-- table where we store suggestions if we need to loadData them&lt;br /&gt;
	local error_text;															-- used as a flag&lt;br /&gt;
&lt;br /&gt;
	local config = {};															-- table to store parameters from the module {{#invoke:}}&lt;br /&gt;
	for k, v in pairs( frame.args ) do											-- get parameters from the {{#invoke}} frame&lt;br /&gt;
		config[k] = v;&lt;br /&gt;
	--	args[k] = v;															-- crude debug support that allows us to render a citation from module {{#invoke:}}; skips parameter validation; TODO: keep?&lt;br /&gt;
	end	&lt;br /&gt;
&lt;br /&gt;
	local capture;																-- the single supported capture when matching unknown parameters using patterns&lt;br /&gt;
	local empty_unknowns = {};													-- sequence table to hold empty unknown params for error message listing&lt;br /&gt;
	for k, v in pairs( pframe.args ) do											-- get parameters from the parent (template) frame&lt;br /&gt;
		v = mw.ustring.gsub (v, &#039;^%s*(.-)%s*$&#039;, &#039;%1&#039;);							-- trim leading/trailing whitespace; when v is only whitespace, becomes empty string&lt;br /&gt;
		if v ~= &#039;&#039; then&lt;br /&gt;
			if (&#039;string&#039; == type (k)) then&lt;br /&gt;
				k = mw.ustring.gsub (k, &#039;%d&#039;, cfg.date_names.local_digits);		-- for enumerated parameters, translate &#039;local&#039; digits to Western 0-9&lt;br /&gt;
			end&lt;br /&gt;
			if not validate( k, config.CitationClass ) then			&lt;br /&gt;
				if type (k) ~= &#039;string&#039; then									-- exclude empty numbered parameters&lt;br /&gt;
					if v:match(&amp;quot;%S+&amp;quot;) ~= nil then&lt;br /&gt;
						error_text = utilities.set_message (&#039;err_text_ignored&#039;, {v});&lt;br /&gt;
					end&lt;br /&gt;
				elseif validate (k:lower(), config.CitationClass) then &lt;br /&gt;
					error_text = utilities.set_message (&#039;err_parameter_ignored_suggest&#039;, {k, k:lower()});	-- suggest the lowercase version of the parameter&lt;br /&gt;
				else&lt;br /&gt;
					if nil == suggestions.suggestions then						-- if this table is nil then we need to load it&lt;br /&gt;
						if is_sandbox then										-- did the {{#invoke:}} use sandbox version?&lt;br /&gt;
							suggestions = mw.loadData( &#039;Module:Citation/CS1/Suggestions/sandbox&#039; );	-- use the sandbox version&lt;br /&gt;
						else&lt;br /&gt;
							suggestions = mw.loadData( &#039;Module:Citation/CS1/Suggestions&#039; );			-- use the live version&lt;br /&gt;
						end&lt;br /&gt;
					end&lt;br /&gt;
					for pattern, param in pairs (suggestions.patterns) do		-- loop through the patterns to see if we can suggest a proper parameter&lt;br /&gt;
						capture = k:match (pattern);							-- the whole match if no capture in pattern else the capture if a match&lt;br /&gt;
						if capture then											-- if the pattern matches &lt;br /&gt;
							param = utilities.substitute (param, capture);		-- add the capture to the suggested parameter (typically the enumerator)&lt;br /&gt;
							if validate (param, config.CitationClass) then		-- validate the suggestion to make sure that the suggestion is supported by this template (necessary for limited parameter lists)&lt;br /&gt;
								error_text = utilities.set_message (&#039;err_parameter_ignored_suggest&#039;, {k, param});	-- set the suggestion error message&lt;br /&gt;
							else&lt;br /&gt;
								error_text = utilities.set_message (&#039;err_parameter_ignored&#039;, {k});	-- suggested param not supported by this template&lt;br /&gt;
								v = &#039;&#039;;											-- unset&lt;br /&gt;
							end&lt;br /&gt;
						end&lt;br /&gt;
					end&lt;br /&gt;
					if not utilities.is_set (error_text) then					-- couldn&#039;t match with a pattern, is there an explicit suggestion?						&lt;br /&gt;
						if (suggestions.suggestions[ k:lower() ] ~= nil) and validate (suggestions.suggestions[ k:lower() ], config.CitationClass) then&lt;br /&gt;
							utilities.set_message (&#039;err_parameter_ignored_suggest&#039;, {k, suggestions.suggestions[ k:lower() ]});&lt;br /&gt;
						else&lt;br /&gt;
							utilities.set_message (&#039;err_parameter_ignored&#039;, {k});&lt;br /&gt;
							v = &#039;&#039;;												-- unset value assigned to unrecognized parameters (this for the limited parameter lists)&lt;br /&gt;
						end&lt;br /&gt;
					end&lt;br /&gt;
				end				  &lt;br /&gt;
			end&lt;br /&gt;
&lt;br /&gt;
			args[k] = v;														-- save this parameter and its value&lt;br /&gt;
&lt;br /&gt;
		elseif not utilities.is_set (v) then									-- for empty parameters&lt;br /&gt;
			if not validate (k, config.CitationClass, true) then				-- is this empty parameter a valid parameter&lt;br /&gt;
				k = (&#039;&#039; == k) and &#039;(empty string)&#039; or k;						-- when k is empty string (or was space(s) trimmed to empty string), replace with descriptive text&lt;br /&gt;
				table.insert (empty_unknowns, utilities.wrap_style (&#039;parameter&#039;, k));	-- format for error message and add to the list&lt;br /&gt;
			end&lt;br /&gt;
																				-- crude debug support that allows us to render a citation from module {{#invoke:}} TODO: keep?&lt;br /&gt;
	--	elseif args[k] ~= nil or (k == &#039;postscript&#039;) then						-- when args[k] has a value from {{#invoke}} frame (we don&#039;t normally do that)&lt;br /&gt;
	--		args[k] = v;														-- overwrite args[k] with empty string from pframe.args[k] (template frame); v is empty string here&lt;br /&gt;
		end																		-- not sure about the postscript bit; that gets handled in parameter validation; historical artifact?&lt;br /&gt;
	end	&lt;br /&gt;
&lt;br /&gt;
	if 0 ~= #empty_unknowns then												-- create empty unknown error message&lt;br /&gt;
		utilities.set_message (&#039;err_param_unknown_empty&#039;, {&lt;br /&gt;
			1 == #empty_unknowns and &#039;&#039; or &#039;s&#039;,&lt;br /&gt;
			utilities.make_sep_list (#empty_unknowns, empty_unknowns)&lt;br /&gt;
			});&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local url_param_t = {};&lt;br /&gt;
&lt;br /&gt;
	for k, v in pairs( args ) do&lt;br /&gt;
		if &#039;string&#039; == type (k) then											-- don&#039;t evaluate positional parameters&lt;br /&gt;
			has_invisible_chars (k, v);											-- look for invisible characters&lt;br /&gt;
		end&lt;br /&gt;
		has_extraneous_punc (k, v);												-- look for extraneous terminal punctuation in parameter values&lt;br /&gt;
		missing_pipe_check (k, v);												-- do we think that there is a parameter that is missing a pipe?&lt;br /&gt;
		args[k] = inter_wiki_check (k, v);										-- when language interwiki-linked parameter missing leading colon replace with wiki-link label&lt;br /&gt;
&lt;br /&gt;
		if &#039;string&#039; == type (k) and not cfg.url_skip[k] then					-- when parameter k is not positional and not in url skip table&lt;br /&gt;
			url_param_t[k] = v;													-- make a parameter/value list for extraneous url check&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	has_extraneous_url (url_param_t);											-- look for url in parameter values where a url does not belong&lt;br /&gt;
&lt;br /&gt;
	return table.concat ({&lt;br /&gt;
		frame:extensionTag (&#039;templatestyles&#039;, &#039;&#039;, {src=styles}),&lt;br /&gt;
		citation0( config, args)&lt;br /&gt;
	});&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; E X P O R T E D   F U N C T I O N S &amp;gt;------------------------------------------&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
return {citation = citation};&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Modul:Check_for_unknown_parameters&amp;diff=1515</id>
		<title>Modul:Check for unknown parameters</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Modul:Check_for_unknown_parameters&amp;diff=1515"/>
		<updated>2022-08-12T16:59:10Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module may be used to compare the arguments passed to the parent&lt;br /&gt;
-- with a list of arguments, returning a specified result if an argument is&lt;br /&gt;
-- not on the list&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
local function trim(s)&lt;br /&gt;
	return s:match(&#039;^%s*(.-)%s*$&#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function isnotempty(s)&lt;br /&gt;
	return s and s:match(&#039;%S&#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function clean(text)&lt;br /&gt;
	-- Return text cleaned for display and truncated if too long.&lt;br /&gt;
	-- Strip markers are replaced with dummy text representing the original wikitext.&lt;br /&gt;
	local pos, truncated&lt;br /&gt;
	local function truncate(text)&lt;br /&gt;
		if truncated then&lt;br /&gt;
			return &#039;&#039;&lt;br /&gt;
		end&lt;br /&gt;
		if mw.ustring.len(text) &amp;gt; 25 then&lt;br /&gt;
			truncated = true&lt;br /&gt;
			text = mw.ustring.sub(text, 1, 25) .. &#039;...&#039;&lt;br /&gt;
		end&lt;br /&gt;
		return mw.text.nowiki(text)&lt;br /&gt;
	end&lt;br /&gt;
	local parts = {}&lt;br /&gt;
	for before, tag, remainder in text:gmatch(&#039;([^\127]*)\127[^\127]*%-(%l+)%-[^\127]*\127()&#039;) do&lt;br /&gt;
		pos = remainder&lt;br /&gt;
		table.insert(parts, truncate(before) .. &#039;&amp;amp;lt;&#039; .. tag .. &#039;&amp;amp;gt;...&amp;amp;lt;/&#039; .. tag .. &#039;&amp;amp;gt;&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	table.insert(parts, truncate(text:sub(pos or 1)))&lt;br /&gt;
	return table.concat(parts)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._check(args, pargs)&lt;br /&gt;
	if type(args) ~= &amp;quot;table&amp;quot; or type(pargs) ~= &amp;quot;table&amp;quot; then&lt;br /&gt;
		-- TODO: error handling&lt;br /&gt;
		return&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- create the list of known args, regular expressions, and the return string&lt;br /&gt;
	local knownargs = {}&lt;br /&gt;
	local regexps = {}&lt;br /&gt;
	for k, v in pairs(args) do&lt;br /&gt;
		if type(k) == &#039;number&#039; then&lt;br /&gt;
			v = trim(v)&lt;br /&gt;
			knownargs[v] = 1&lt;br /&gt;
		elseif k:find(&#039;^regexp[1-9][0-9]*$&#039;) then&lt;br /&gt;
			table.insert(regexps, &#039;^&#039; .. v .. &#039;$&#039;)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- loop over the parent args, and make sure they are on the list&lt;br /&gt;
	local ignoreblank = isnotempty(args[&#039;ignoreblank&#039;])&lt;br /&gt;
	local showblankpos = isnotempty(args[&#039;showblankpositional&#039;])&lt;br /&gt;
	local values = {}&lt;br /&gt;
	for k, v in pairs(pargs) do&lt;br /&gt;
		if type(k) == &#039;string&#039; and knownargs[k] == nil then&lt;br /&gt;
			local knownflag = false&lt;br /&gt;
			for _, regexp in ipairs(regexps) do&lt;br /&gt;
				if mw.ustring.match(k, regexp) then&lt;br /&gt;
					knownflag = true&lt;br /&gt;
					break&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			if not knownflag and ( not ignoreblank or isnotempty(v) )  then&lt;br /&gt;
				table.insert(values, clean(k))&lt;br /&gt;
			end&lt;br /&gt;
		elseif type(k) == &#039;number&#039; and knownargs[tostring(k)] == nil then&lt;br /&gt;
			local knownflag = false&lt;br /&gt;
			for _, regexp in ipairs(regexps) do&lt;br /&gt;
				if mw.ustring.match(tostring(k), regexp) then&lt;br /&gt;
					knownflag = true&lt;br /&gt;
					break&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			if not knownflag and ( showblankpos or isnotempty(v) ) then&lt;br /&gt;
				table.insert(values, k .. &#039; = &#039; .. clean(v))&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- add results to the output tables&lt;br /&gt;
	local res = {}&lt;br /&gt;
	if #values &amp;gt; 0 then&lt;br /&gt;
		local unknown_text = args[&#039;unknown&#039;] or &#039;Found _VALUE_, &#039;&lt;br /&gt;
&lt;br /&gt;
		if mw.getCurrentFrame():preprocess( &amp;quot;{{REVISIONID}}&amp;quot; ) == &amp;quot;&amp;quot; then&lt;br /&gt;
			local preview_text = args[&#039;preview&#039;]&lt;br /&gt;
			if isnotempty(preview_text) then&lt;br /&gt;
				preview_text = require(&#039;Module:If preview&#039;)._warning({preview_text})&lt;br /&gt;
			elseif preview == nil then&lt;br /&gt;
				preview_text = unknown_text&lt;br /&gt;
			end&lt;br /&gt;
			unknown_text = preview_text&lt;br /&gt;
		end&lt;br /&gt;
		for _, v in pairs(values) do&lt;br /&gt;
			-- Fix odd bug for | = which gets stripped to the empty string and&lt;br /&gt;
			-- breaks category links&lt;br /&gt;
			if v == &#039;&#039; then v = &#039; &#039; end&lt;br /&gt;
&lt;br /&gt;
			-- avoid error with v = &#039;example%2&#039; (&amp;quot;invalid capture index&amp;quot;)&lt;br /&gt;
			local r = unknown_text:gsub(&#039;_VALUE_&#039;, {_VALUE_ = v})&lt;br /&gt;
			table.insert(res, r)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return table.concat(res)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.check(frame)&lt;br /&gt;
	local args = frame.args&lt;br /&gt;
	local pargs = frame:getParent().args&lt;br /&gt;
	return p._check(args, pargs)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Modul:Age&amp;diff=1513</id>
		<title>Modul:Age</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Modul:Age&amp;diff=1513"/>
		<updated>2022-08-12T16:59:07Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- Implement various &amp;quot;age of&amp;quot; and other date-related templates.&lt;br /&gt;
&lt;br /&gt;
local mtext = {&lt;br /&gt;
	-- Message and other text that should be localized.&lt;br /&gt;
	-- Also need to localize text in table names in function dateDifference.&lt;br /&gt;
	[&#039;mt-bad-param1&#039;] =             &#039;Invalid parameter $1&#039;,&lt;br /&gt;
	[&#039;mt-bad-param2&#039;] =             &#039;Parameter $1=$2 is invalid&#039;,&lt;br /&gt;
	[&#039;mt-bad-show&#039;] =               &#039;Parameter show=$1 is not supported here&#039;,&lt;br /&gt;
	[&#039;mt-cannot-add&#039;] =             &#039;Cannot add &amp;quot;$1&amp;quot;&#039;,&lt;br /&gt;
	[&#039;mt-conflicting-show&#039;] =       &#039;Parameter show=$1 conflicts with round=$2&#039;,&lt;br /&gt;
	[&#039;mt-date-wrong-order&#039;] =       &#039;The second date must be later in time than the first date&#039;,&lt;br /&gt;
	[&#039;mt-dd-future&#039;] =              &#039;Death date (first date) must not be in the future&#039;,&lt;br /&gt;
	[&#039;mt-dd-wrong-order&#039;] =         &#039;Death date (first date) must be later in time than the birth date (second date)&#039;,&lt;br /&gt;
	[&#039;mt-invalid-bd-age&#039;] =         &#039;Invalid birth date for calculating age&#039;,&lt;br /&gt;
	[&#039;mt-invalid-dates-age&#039;] =      &#039;Invalid dates for calculating age&#039;,&lt;br /&gt;
	[&#039;mt-invalid-end&#039;] =            &#039;Invalid end date in second parameter&#039;,&lt;br /&gt;
	[&#039;mt-invalid-start&#039;] =          &#039;Invalid start date in first parameter&#039;,&lt;br /&gt;
	[&#039;mt-need-jdn&#039;] =               &#039;Need valid Julian date number&#039;,&lt;br /&gt;
	[&#039;mt-need-valid-bd&#039;] =          &#039;Need valid birth date: year, month, day&#039;,&lt;br /&gt;
	[&#039;mt-need-valid-bd2&#039;] =         &#039;Need valid birth date (second date): year, month, day&#039;,&lt;br /&gt;
	[&#039;mt-need-valid-date&#039;] =        &#039;Need valid date&#039;,&lt;br /&gt;
	[&#039;mt-need-valid-dd&#039;] =          &#039;Need valid death date (first date): year, month, day&#039;,&lt;br /&gt;
	[&#039;mt-need-valid-ymd&#039;] =         &#039;Need valid year, month, day&#039;,&lt;br /&gt;
	[&#039;mt-need-valid-ymd-current&#039;] = &#039;Need valid year|month|day or &amp;quot;currentdate&amp;quot;&#039;,&lt;br /&gt;
	[&#039;mt-need-valid-ymd2&#039;] =        &#039;Second date should be year, month, day&#039;,&lt;br /&gt;
	[&#039;mt-template-bad-name&#039;] =      &#039;The specified template name is not valid&#039;,&lt;br /&gt;
	[&#039;mt-template-x&#039;] =             &#039;The template invoking this must have &amp;quot;|template=x&amp;quot; where x is the wanted operation&#039;,&lt;br /&gt;
	[&#039;txt-and&#039;] =                   &#039; and &#039;,&lt;br /&gt;
	[&#039;txt-or&#039;] =                    &#039;&amp;amp;nbsp;or &#039;,&lt;br /&gt;
	[&#039;txt-category&#039;] =              &#039;Category:Age error&#039;,&lt;br /&gt;
	[&#039;txt-comma-and&#039;] =             &#039;, and &#039;,&lt;br /&gt;
	[&#039;txt-error&#039;] =                 &#039;Error: &#039;,&lt;br /&gt;
	[&#039;txt-format-default&#039;] =        &#039;mf&#039;,  -- &#039;df&#039; (day first = dmy) or &#039;mf&#039; (month first = mdy)&lt;br /&gt;
	[&#039;txt-module-convertnumeric&#039;] = &#039;Module:ConvertNumeric&#039;,&lt;br /&gt;
	[&#039;txt-module-date&#039;] =           &#039;Module:Date&#039;,&lt;br /&gt;
	[&#039;txt-sandbox&#039;] =               &#039;sandbox&#039;,&lt;br /&gt;
	[&#039;txt-bda&#039;] = &#039;&amp;lt;span style=&amp;quot;display:none&amp;quot;&amp;gt; (&amp;lt;span class=&amp;quot;bday&amp;quot;&amp;gt;$1&amp;lt;/span&amp;gt;) &amp;lt;/span&amp;gt;$2&amp;lt;span class=&amp;quot;noprint ForceAgeToShow&amp;quot;&amp;gt; (age&amp;amp;nbsp;$3)&amp;lt;/span&amp;gt;&#039;,&lt;br /&gt;
	[&#039;txt-dda&#039;] = &#039;$2&amp;lt;span style=&amp;quot;display:none&amp;quot;&amp;gt;($1)&amp;lt;/span&amp;gt; (aged&amp;amp;nbsp;$3)&#039;,&lt;br /&gt;
	[&#039;txt-bda-disp&#039;] = &#039;disp_raw&#039;,  -- disp_raw → age is a number only; disp_age → age is a number and unit (normally years but months or days if very young)&lt;br /&gt;
	[&#039;txt-dda-disp&#039;] = &#039;disp_raw&#039;,&lt;br /&gt;
	[&#039;txt-dmy&#039;] = &#039;%-d %B %-Y&#039;,&lt;br /&gt;
	[&#039;txt-mdy&#039;] = &#039;%B %-d, %-Y&#039;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local isWarning = {&lt;br /&gt;
	[&#039;mt-bad-param1&#039;] = true,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local translate, from_en, to_en, isZero&lt;br /&gt;
if translate then&lt;br /&gt;
	-- Functions to translate from en to local language and reverse go here.&lt;br /&gt;
	-- See example at [[:bn:Module:বয়স]].&lt;br /&gt;
else&lt;br /&gt;
	from_en = function (text)&lt;br /&gt;
		return text&lt;br /&gt;
	end&lt;br /&gt;
	isZero = function (text)&lt;br /&gt;
		return tonumber(text) == 0&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local _Date, _currentDate&lt;br /&gt;
local function getExports(frame)&lt;br /&gt;
	-- Return objects exported from the date module or its sandbox.&lt;br /&gt;
	if not _Date then&lt;br /&gt;
		local sandbox = frame:getTitle():find(mtext[&#039;txt-sandbox&#039;], 1, true) and (&#039;/&#039; .. mtext[&#039;txt-sandbox&#039;]) or &#039;&#039;&lt;br /&gt;
		local datemod = require(mtext[&#039;txt-module-date&#039;] .. sandbox)&lt;br /&gt;
		local realDate = datemod._Date&lt;br /&gt;
		_currentDate = datemod._current&lt;br /&gt;
		if to_en then&lt;br /&gt;
			_Date = function (...)&lt;br /&gt;
				local args = {}&lt;br /&gt;
				for i, v in ipairs({...}) do&lt;br /&gt;
					args[i] = to_en(v)&lt;br /&gt;
				end&lt;br /&gt;
				return realDate(unpack(args))&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			_Date = realDate&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return _Date, _currentDate&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local Collection  -- a table to hold items&lt;br /&gt;
Collection = {&lt;br /&gt;
	add = function (self, item)&lt;br /&gt;
		if item ~= nil then&lt;br /&gt;
			self.n = self.n + 1&lt;br /&gt;
			self[self.n] = item&lt;br /&gt;
		end&lt;br /&gt;
	end,&lt;br /&gt;
	join = function (self, sep)&lt;br /&gt;
		return table.concat(self, sep)&lt;br /&gt;
	end,&lt;br /&gt;
	remove = function (self, pos)&lt;br /&gt;
		if self.n &amp;gt; 0 and (pos == nil or (0 &amp;lt; pos and pos &amp;lt;= self.n)) then&lt;br /&gt;
			self.n = self.n - 1&lt;br /&gt;
			return table.remove(self, pos)&lt;br /&gt;
		end&lt;br /&gt;
	end,&lt;br /&gt;
	sort = function (self, comp)&lt;br /&gt;
		table.sort(self, comp)&lt;br /&gt;
	end,&lt;br /&gt;
	new = function ()&lt;br /&gt;
		return setmetatable({n = 0}, Collection)&lt;br /&gt;
	end&lt;br /&gt;
}&lt;br /&gt;
Collection.__index = Collection&lt;br /&gt;
&lt;br /&gt;
local function stripToNil(text)&lt;br /&gt;
	-- If text is a string, return its trimmed content, or nil if empty.&lt;br /&gt;
	-- Otherwise return text (which may, for example, be nil).&lt;br /&gt;
	if type(text) == &#039;string&#039; then&lt;br /&gt;
		text = text:match(&#039;(%S.-)%s*$&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	return text&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function dateFormat(args)&lt;br /&gt;
	-- Return string for wanted date format.&lt;br /&gt;
	local default = mtext[&#039;txt-format-default&#039;]&lt;br /&gt;
	local other = default == &#039;df&#039; and &#039;mf&#039; or &#039;df&#039;&lt;br /&gt;
	local wanted = stripToNil(args[other]) and other or default&lt;br /&gt;
	return wanted == &#039;df&#039; and mtext[&#039;txt-dmy&#039;] or mtext[&#039;txt-mdy&#039;]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function substituteParameters(text, ...)&lt;br /&gt;
	-- Return text after substituting any given parameters for $1, $2, etc.&lt;br /&gt;
	return mw.message.newRawMessage(text, ...):plain()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function yes(parameter)&lt;br /&gt;
	-- Return true if parameter should be interpreted as &amp;quot;yes&amp;quot;.&lt;br /&gt;
	-- Do not want to accept mixed upper/lowercase unless done by current templates.&lt;br /&gt;
	-- Need to accept &amp;quot;on&amp;quot; because &amp;quot;round=on&amp;quot; is wanted.&lt;br /&gt;
	return ({ y = true, yes = true, on = true })[parameter]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function message(msg, ...)&lt;br /&gt;
	-- Return formatted message text for an error or warning.&lt;br /&gt;
	local function getText(msg)&lt;br /&gt;
		return mtext[msg] or error(&#039;Bug: message &amp;quot;&#039; .. tostring(msg) .. &#039;&amp;quot; not defined&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	local categories = {&lt;br /&gt;
		error = mtext[&#039;txt-category&#039;],&lt;br /&gt;
		warning = mtext[&#039;txt-category&#039;],&lt;br /&gt;
	}&lt;br /&gt;
	local a, b, k, category&lt;br /&gt;
	local text = substituteParameters(getText(msg), ...)&lt;br /&gt;
	if isWarning[msg] then&lt;br /&gt;
		a = &#039;&amp;lt;sup&amp;gt;[&amp;lt;i&amp;gt;&#039;&lt;br /&gt;
		b = &#039;&amp;lt;/i&amp;gt;]&amp;lt;/sup&amp;gt;&#039;&lt;br /&gt;
		k = &#039;warning&#039;&lt;br /&gt;
	else&lt;br /&gt;
		a = &#039;&amp;lt;strong class=&amp;quot;error&amp;quot;&amp;gt;&#039; .. getText(&#039;txt-error&#039;)&lt;br /&gt;
		b = &#039;&amp;lt;/strong&amp;gt;&#039;&lt;br /&gt;
		k = &#039;error&#039;&lt;br /&gt;
	end&lt;br /&gt;
	if mw.title.getCurrentTitle():inNamespaces(0) then&lt;br /&gt;
		-- Category only in namespaces: 0=article.&lt;br /&gt;
		category = &#039;[[&#039; .. categories[k] .. &#039;]]&#039;&lt;br /&gt;
	end&lt;br /&gt;
	return&lt;br /&gt;
		a ..&lt;br /&gt;
		mw.text.nowiki(text) ..&lt;br /&gt;
		b ..&lt;br /&gt;
		(category or &#039;&#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function formatNumber(number)&lt;br /&gt;
	-- Return the given number formatted with commas as group separators,&lt;br /&gt;
	-- given that the number is an integer.&lt;br /&gt;
	local numstr = tostring(number)&lt;br /&gt;
	local length = #numstr&lt;br /&gt;
	local places = Collection.new()&lt;br /&gt;
	local pos = 0&lt;br /&gt;
	repeat&lt;br /&gt;
		places:add(pos)&lt;br /&gt;
		pos = pos + 3&lt;br /&gt;
	until pos &amp;gt;= length&lt;br /&gt;
	places:add(length)&lt;br /&gt;
	local groups = Collection.new()&lt;br /&gt;
	for i = places.n, 2, -1 do&lt;br /&gt;
		local p1 = length - places[i] + 1&lt;br /&gt;
		local p2 = length - places[i - 1]&lt;br /&gt;
		groups:add(numstr:sub(p1, p2))&lt;br /&gt;
	end&lt;br /&gt;
	return groups:join(&#039;,&#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function spellNumber(number, options, i)&lt;br /&gt;
	-- Return result of spelling number, or&lt;br /&gt;
	-- return number (as a string) if cannot spell it.&lt;br /&gt;
	-- i == 1 for the first number which can optionally start with an uppercase letter.&lt;br /&gt;
	number = tostring(number)&lt;br /&gt;
	return require(mtext[&#039;txt-module-convertnumeric&#039;]).spell_number(&lt;br /&gt;
		number,&lt;br /&gt;
		nil,                       -- fraction numerator&lt;br /&gt;
		nil,                       -- fraction denominator&lt;br /&gt;
		i == 1 and options.upper,  -- true: &#039;One&#039; instead of &#039;one&#039;&lt;br /&gt;
		not options.us,            -- true: use &#039;and&#039; between tens/ones etc&lt;br /&gt;
		options.adj,               -- true: hyphenated&lt;br /&gt;
		options.ordinal            -- true: &#039;first&#039; instead of &#039;one&#039;&lt;br /&gt;
	) or number&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function makeExtra(args, flagCurrent)&lt;br /&gt;
	-- Return extra text that will be inserted before the visible result&lt;br /&gt;
	-- but after any sort key.&lt;br /&gt;
	local extra = args.prefix or &#039;&#039;&lt;br /&gt;
	if mw.ustring.len(extra) &amp;gt; 1 then&lt;br /&gt;
		-- Parameter &amp;quot;~&amp;quot; gives &amp;quot;~3&amp;quot; whereas &amp;quot;over&amp;quot; gives &amp;quot;over 3&amp;quot;.&lt;br /&gt;
		if extra:sub(-6, -1) ~= &#039;&amp;amp;nbsp;&#039; then&lt;br /&gt;
			extra = extra .. &#039; &#039;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if flagCurrent then&lt;br /&gt;
		extra = &#039;&amp;lt;span class=&amp;quot;currentage&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039; .. extra&lt;br /&gt;
	end&lt;br /&gt;
	return extra&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function makeSort(value, sortable)&lt;br /&gt;
	-- Return a sort key if requested.&lt;br /&gt;
	-- Assume value is a valid number which has not overflowed.&lt;br /&gt;
	if sortable == &#039;sortable_table&#039; or sortable == &#039;sortable_on&#039; or sortable == &#039;sortable_debug&#039; then&lt;br /&gt;
		local sortKey&lt;br /&gt;
		if value == 0 then&lt;br /&gt;
			sortKey = &#039;5000000000000000000&#039;&lt;br /&gt;
		else&lt;br /&gt;
			local mag = math.floor(math.log10(math.abs(value)) + 1e-14)&lt;br /&gt;
			if value &amp;gt; 0 then&lt;br /&gt;
				sortKey = 7000 + mag&lt;br /&gt;
			else&lt;br /&gt;
				sortKey = 2999 - mag&lt;br /&gt;
				value = value + 10^(mag+1)&lt;br /&gt;
			end&lt;br /&gt;
			sortKey = string.format(&#039;%d&#039;, sortKey) .. string.format(&#039;%015.0f&#039;, math.floor(value * 10^(14-mag)))&lt;br /&gt;
		end&lt;br /&gt;
		local result&lt;br /&gt;
		if sortable == &#039;sortable_table&#039; then&lt;br /&gt;
			result = &#039;data-sort-value=&amp;quot;_SORTKEY_&amp;quot;|&#039;&lt;br /&gt;
		elseif sortable == &#039;sortable_debug&#039; then&lt;br /&gt;
			result = &#039;&amp;lt;span data-sort-value=&amp;quot;_SORTKEY_♠&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;border:1px solid&amp;quot;&amp;gt;_SORTKEY_♠&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
		else&lt;br /&gt;
			result = &#039;&amp;lt;span data-sort-value=&amp;quot;_SORTKEY_♠&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
		end&lt;br /&gt;
		return (result:gsub(&#039;_SORTKEY_&#039;, sortKey))&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local translateParameters = {&lt;br /&gt;
	abbr = {&lt;br /&gt;
		off = &#039;abbr_off&#039;,&lt;br /&gt;
		on = &#039;abbr_on&#039;,&lt;br /&gt;
	},&lt;br /&gt;
	disp = {&lt;br /&gt;
		age = &#039;disp_age&#039;,&lt;br /&gt;
		raw = &#039;disp_raw&#039;,&lt;br /&gt;
	},&lt;br /&gt;
	format = {&lt;br /&gt;
		raw = &#039;format_raw&#039;,&lt;br /&gt;
		commas = &#039;format_commas&#039;,&lt;br /&gt;
	},&lt;br /&gt;
	round = {&lt;br /&gt;
		on = &#039;on&#039;,&lt;br /&gt;
		yes = &#039;on&#039;,&lt;br /&gt;
		months = &#039;ym&#039;,&lt;br /&gt;
		weeks = &#039;ymw&#039;,&lt;br /&gt;
		days = &#039;ymd&#039;,&lt;br /&gt;
		hours = &#039;ymdh&#039;,&lt;br /&gt;
	},&lt;br /&gt;
	sep = {&lt;br /&gt;
		comma = &#039;sep_comma&#039;,&lt;br /&gt;
		[&#039;,&#039;] = &#039;sep_comma&#039;,&lt;br /&gt;
		serialcomma = &#039;sep_serialcomma&#039;,&lt;br /&gt;
		space = &#039;sep_space&#039;,&lt;br /&gt;
	},&lt;br /&gt;
	show = {&lt;br /&gt;
		hide = { id = &#039;hide&#039; },&lt;br /&gt;
		y = { &#039;y&#039;, id = &#039;y&#039; },&lt;br /&gt;
		ym = { &#039;y&#039;, &#039;m&#039;, id = &#039;ym&#039; },&lt;br /&gt;
		ymd = { &#039;y&#039;, &#039;m&#039;, &#039;d&#039;, id = &#039;ymd&#039; },&lt;br /&gt;
		ymw = { &#039;y&#039;, &#039;m&#039;, &#039;w&#039;, id = &#039;ymw&#039; },&lt;br /&gt;
		ymwd = { &#039;y&#039;, &#039;m&#039;, &#039;w&#039;, &#039;d&#039;, id = &#039;ymwd&#039; },&lt;br /&gt;
		yd = { &#039;y&#039;, &#039;d&#039;, id = &#039;yd&#039;, keepZero = true },&lt;br /&gt;
		m = { &#039;m&#039;, id = &#039;m&#039; },&lt;br /&gt;
		md = { &#039;m&#039;, &#039;d&#039;, id = &#039;md&#039; },&lt;br /&gt;
		w = { &#039;w&#039;, id = &#039;w&#039; },&lt;br /&gt;
		wd = { &#039;w&#039;, &#039;d&#039;, id = &#039;wd&#039; },&lt;br /&gt;
		h = { &#039;H&#039;, id = &#039;h&#039; },&lt;br /&gt;
		hm = { &#039;H&#039;, &#039;M&#039;, id = &#039;hm&#039; },&lt;br /&gt;
		hms = { &#039;H&#039;, &#039;M&#039;, &#039;S&#039;, id = &#039;hms&#039; },&lt;br /&gt;
		M = { &#039;M&#039;, id = &#039;M&#039; },&lt;br /&gt;
		s = { &#039;S&#039;, id = &#039;s&#039; },&lt;br /&gt;
		d = { &#039;d&#039;, id = &#039;d&#039; },&lt;br /&gt;
		dh = { &#039;d&#039;, &#039;H&#039;, id = &#039;dh&#039; },&lt;br /&gt;
		dhm = { &#039;d&#039;, &#039;H&#039;, &#039;M&#039;, id = &#039;dhm&#039; },&lt;br /&gt;
		dhms = { &#039;d&#039;, &#039;H&#039;, &#039;M&#039;, &#039;S&#039;, id = &#039;dhms&#039; },&lt;br /&gt;
		ymdh = { &#039;y&#039;, &#039;m&#039;, &#039;d&#039;, &#039;H&#039;, id = &#039;ymdh&#039; },&lt;br /&gt;
		ymdhm = { &#039;y&#039;, &#039;m&#039;, &#039;d&#039;, &#039;H&#039;, &#039;M&#039;, id = &#039;ymdhm&#039; },&lt;br /&gt;
		ymwdh = { &#039;y&#039;, &#039;m&#039;, &#039;w&#039;, &#039;d&#039;, &#039;H&#039;, id = &#039;ymwdh&#039; },&lt;br /&gt;
		ymwdhm = { &#039;y&#039;, &#039;m&#039;, &#039;w&#039;, &#039;d&#039;, &#039;H&#039;, &#039;M&#039;, id = &#039;ymwdhm&#039; },&lt;br /&gt;
	},&lt;br /&gt;
	sortable = {&lt;br /&gt;
		off = false,&lt;br /&gt;
		on = &#039;sortable_on&#039;,&lt;br /&gt;
		table = &#039;sortable_table&#039;,&lt;br /&gt;
		debug = &#039;sortable_debug&#039;,&lt;br /&gt;
	},&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local spellOptions = {&lt;br /&gt;
	cardinal = {},&lt;br /&gt;
	Cardinal = { upper = true },&lt;br /&gt;
	cardinal_us = { us = true },&lt;br /&gt;
	Cardinal_us = { us = true, upper = true },&lt;br /&gt;
	ordinal = { ordinal = true },&lt;br /&gt;
	Ordinal = { ordinal = true, upper = true },&lt;br /&gt;
	ordinal_us = { ordinal = true, us = true },&lt;br /&gt;
	Ordinal_us = { ordinal = true, us = true, upper = true },&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local function dateExtract(frame)&lt;br /&gt;
	-- Return part of a date after performing an optional operation.&lt;br /&gt;
	local Date = getExports(frame)&lt;br /&gt;
	local args = frame:getParent().args&lt;br /&gt;
	local parms = {}&lt;br /&gt;
	for i, v in ipairs(args) do&lt;br /&gt;
		parms[i] = v&lt;br /&gt;
	end&lt;br /&gt;
	if yes(args.fix) then&lt;br /&gt;
		table.insert(parms, &#039;fix&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	if yes(args.partial) then&lt;br /&gt;
		table.insert(parms, &#039;partial&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	local show = stripToNil(args.show) or &#039;dmy&#039;&lt;br /&gt;
	local date = Date(unpack(parms))&lt;br /&gt;
	if not date then&lt;br /&gt;
		if show == &#039;format&#039; then&lt;br /&gt;
			return &#039;error&#039;&lt;br /&gt;
		end&lt;br /&gt;
		return message(&#039;mt-need-valid-date&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	local add = stripToNil(args.add)&lt;br /&gt;
	if add then&lt;br /&gt;
		for item in add:gmatch(&#039;%S+&#039;) do&lt;br /&gt;
			date = date + item&lt;br /&gt;
			if not date then&lt;br /&gt;
				return message(&#039;mt-cannot-add&#039;, item)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local sortKey, result&lt;br /&gt;
	local sortable = translateParameters.sortable[args.sortable]&lt;br /&gt;
	if sortable then&lt;br /&gt;
		local value = (date.partial and date.partial.first or date).jdz&lt;br /&gt;
		sortKey = makeSort(value, sortable)&lt;br /&gt;
	end&lt;br /&gt;
	if show ~= &#039;hide&#039; then&lt;br /&gt;
		result = date[show]&lt;br /&gt;
		if result == nil then&lt;br /&gt;
			result = from_en(date:text(show))&lt;br /&gt;
		elseif type(result) == &#039;boolean&#039; then&lt;br /&gt;
			result = result and &#039;1&#039; or &#039;0&#039;&lt;br /&gt;
		else&lt;br /&gt;
			result = from_en(tostring(result))&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return (sortKey or &#039;&#039;) .. makeExtra(args) .. (result or &#039;&#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function rangeJoin(range)&lt;br /&gt;
	-- Return text to be used between a range of ages.&lt;br /&gt;
	return range == &#039;dash&#039; and &#039;–&#039; or mtext[&#039;txt-or&#039;]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function makeText(values, components, names, options, noUpper)&lt;br /&gt;
	-- Return wikitext representing an age or duration.&lt;br /&gt;
	local text = Collection.new()&lt;br /&gt;
	local count = #values&lt;br /&gt;
	local sep = names.sep or &#039;&#039;&lt;br /&gt;
	for i, v in ipairs(values) do&lt;br /&gt;
		-- v is a number (say 4 for 4 years), or a table ({4,5} for 4 or 5 years).&lt;br /&gt;
		local islist = type(v) == &#039;table&#039;&lt;br /&gt;
		if (islist or v &amp;gt; 0) or (text.n == 0 and i == count) or (text.n &amp;gt; 0 and components.keepZero) then&lt;br /&gt;
			local fmt, vstr&lt;br /&gt;
			if options.spell then&lt;br /&gt;
				fmt = function(number)&lt;br /&gt;
					return spellNumber(number, options.spell, noUpper or i)&lt;br /&gt;
				end&lt;br /&gt;
			elseif i == 1 and options.format == &#039;format_commas&#039; then&lt;br /&gt;
				-- Numbers after the first should be small and not need formatting.&lt;br /&gt;
				fmt = formatNumber&lt;br /&gt;
			else&lt;br /&gt;
				fmt = tostring&lt;br /&gt;
			end&lt;br /&gt;
			if islist then&lt;br /&gt;
				vstr = fmt(v[1]) .. rangeJoin(options.range)&lt;br /&gt;
				noUpper = true&lt;br /&gt;
				vstr = vstr .. fmt(v[2])&lt;br /&gt;
			else&lt;br /&gt;
				vstr = fmt(v)&lt;br /&gt;
			end&lt;br /&gt;
			local name = names[components[i]]&lt;br /&gt;
			if name then&lt;br /&gt;
				if type(name) == &#039;table&#039; then&lt;br /&gt;
					name = mw.getContentLanguage():plural(islist and v[2] or v, name)&lt;br /&gt;
				end&lt;br /&gt;
				text:add(vstr .. sep .. name)&lt;br /&gt;
			else&lt;br /&gt;
				text:add(vstr)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local first, last&lt;br /&gt;
	if options.join == &#039;sep_space&#039; then&lt;br /&gt;
		first = &#039; &#039;&lt;br /&gt;
		last = &#039; &#039;&lt;br /&gt;
	elseif options.join == &#039;sep_comma&#039; then&lt;br /&gt;
		first = &#039;, &#039;&lt;br /&gt;
		last = &#039;, &#039;&lt;br /&gt;
	elseif options.join == &#039;sep_serialcomma&#039; and text.n &amp;gt; 2 then&lt;br /&gt;
		first = &#039;, &#039;&lt;br /&gt;
		last = mtext[&#039;txt-comma-and&#039;]&lt;br /&gt;
	else&lt;br /&gt;
		first = &#039;, &#039;&lt;br /&gt;
		last = mtext[&#039;txt-and&#039;]&lt;br /&gt;
	end&lt;br /&gt;
	for i, v in ipairs(text) do&lt;br /&gt;
		if i &amp;lt; text.n then&lt;br /&gt;
			text[i] = v .. (i + 1 &amp;lt; text.n and first or last)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local sign = &#039;&#039;&lt;br /&gt;
	if options.isnegative then&lt;br /&gt;
		-- Do not display negative zero.&lt;br /&gt;
		if text.n &amp;gt; 1 or (text.n == 1 and text[1]:sub(1, 1) ~= &#039;0&#039; ) then&lt;br /&gt;
			if options.format == &#039;format_raw&#039; then&lt;br /&gt;
				sign = &#039;-&#039;  -- plain hyphen so result can be used in a calculation&lt;br /&gt;
			else&lt;br /&gt;
				sign = &#039;−&#039;  -- Unicode U+2212 MINUS SIGN&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return&lt;br /&gt;
		(options.sortKey or &#039;&#039;) ..&lt;br /&gt;
		(options.extra or &#039;&#039;) ..&lt;br /&gt;
		sign ..&lt;br /&gt;
		text:join() ..&lt;br /&gt;
		(options.suffix or &#039;&#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function dateDifference(parms)&lt;br /&gt;
	-- Return a formatted date difference using the given parameters&lt;br /&gt;
	-- which have been validated.&lt;br /&gt;
	local names = {&lt;br /&gt;
		-- Each name is:&lt;br /&gt;
		-- * a string if no plural form of the name is used; or&lt;br /&gt;
		-- * a table of strings, one of which is selected using the rules at&lt;br /&gt;
		--   https://translatewiki.net/wiki/Plural/Mediawiki_plural_rules&lt;br /&gt;
		abbr_off = {&lt;br /&gt;
			sep = &#039;&amp;amp;nbsp;&#039;,&lt;br /&gt;
			y = {&#039;year&#039;, &#039;years&#039;},&lt;br /&gt;
			m = {&#039;month&#039;, &#039;months&#039;},&lt;br /&gt;
			w = {&#039;week&#039;, &#039;weeks&#039;},&lt;br /&gt;
			d = {&#039;day&#039;, &#039;days&#039;},&lt;br /&gt;
			H = {&#039;hour&#039;, &#039;hours&#039;},&lt;br /&gt;
			M = {&#039;minute&#039;, &#039;minutes&#039;},&lt;br /&gt;
			S = {&#039;second&#039;, &#039;seconds&#039;},&lt;br /&gt;
		},&lt;br /&gt;
		abbr_on = {&lt;br /&gt;
			y = &#039;y&#039;,&lt;br /&gt;
			m = &#039;m&#039;,&lt;br /&gt;
			w = &#039;w&#039;,&lt;br /&gt;
			d = &#039;d&#039;,&lt;br /&gt;
			H = &#039;h&#039;,&lt;br /&gt;
			M = &#039;m&#039;,&lt;br /&gt;
			S = &#039;s&#039;,&lt;br /&gt;
		},&lt;br /&gt;
		abbr_infant = {      -- for {{age for infant}}&lt;br /&gt;
			sep = &#039;&amp;amp;nbsp;&#039;,&lt;br /&gt;
			y = {&#039;yr&#039;, &#039;yrs&#039;},&lt;br /&gt;
			m = {&#039;mo&#039;, &#039;mos&#039;},&lt;br /&gt;
			w = {&#039;wk&#039;, &#039;wks&#039;},&lt;br /&gt;
			d = {&#039;day&#039;, &#039;days&#039;},&lt;br /&gt;
			H = {&#039;hr&#039;, &#039;hrs&#039;},&lt;br /&gt;
			M = {&#039;min&#039;, &#039;mins&#039;},&lt;br /&gt;
			S = {&#039;sec&#039;, &#039;secs&#039;},&lt;br /&gt;
		},&lt;br /&gt;
		abbr_raw = {},&lt;br /&gt;
	}&lt;br /&gt;
	local diff = parms.diff  -- must be a valid date difference&lt;br /&gt;
	local show = parms.show  -- may be nil; default is set below&lt;br /&gt;
	local abbr = parms.abbr or &#039;abbr_off&#039;&lt;br /&gt;
	local defaultJoin&lt;br /&gt;
	if abbr ~= &#039;abbr_off&#039; then&lt;br /&gt;
		defaultJoin = &#039;sep_space&#039;&lt;br /&gt;
	end&lt;br /&gt;
	if not show then&lt;br /&gt;
		show = &#039;ymd&#039;&lt;br /&gt;
		if parms.disp == &#039;disp_age&#039; then&lt;br /&gt;
			if diff.years &amp;lt; 3 then&lt;br /&gt;
				defaultJoin = &#039;sep_space&#039;&lt;br /&gt;
				if diff.years &amp;gt;= 1 then&lt;br /&gt;
					show = &#039;ym&#039;&lt;br /&gt;
				else&lt;br /&gt;
					show = &#039;md&#039;&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				show = &#039;y&#039;&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if type(show) ~= &#039;table&#039; then&lt;br /&gt;
		show = translateParameters.show[show]&lt;br /&gt;
	end&lt;br /&gt;
	if parms.disp == &#039;disp_raw&#039; then&lt;br /&gt;
		defaultJoin = &#039;sep_space&#039;&lt;br /&gt;
		abbr = &#039;abbr_raw&#039;&lt;br /&gt;
	elseif parms.wantSc then&lt;br /&gt;
		defaultJoin = &#039;sep_serialcomma&#039;&lt;br /&gt;
	end&lt;br /&gt;
	local diffOptions = {&lt;br /&gt;
		round = parms.round,&lt;br /&gt;
		duration = parms.wantDuration,&lt;br /&gt;
		range = parms.range and true or nil,&lt;br /&gt;
	}&lt;br /&gt;
	local sortKey&lt;br /&gt;
	if parms.sortable then&lt;br /&gt;
		local value = diff.age_days + (parms.wantDuration and 1 or 0)  -- days and fraction of a day&lt;br /&gt;
		if diff.isnegative then&lt;br /&gt;
			value = -value&lt;br /&gt;
		end&lt;br /&gt;
		sortKey = makeSort(value, parms.sortable)&lt;br /&gt;
	end&lt;br /&gt;
	local textOptions = {&lt;br /&gt;
		extra = parms.extra,&lt;br /&gt;
		format = parms.format,&lt;br /&gt;
		join = parms.sep or defaultJoin,&lt;br /&gt;
		isnegative = diff.isnegative,&lt;br /&gt;
		range = parms.range,&lt;br /&gt;
		sortKey = sortKey,&lt;br /&gt;
		spell = parms.spell,&lt;br /&gt;
		suffix = parms.suffix,  -- not currently used&lt;br /&gt;
	}&lt;br /&gt;
	if show.id == &#039;hide&#039; then&lt;br /&gt;
		return sortKey or &#039;&#039;&lt;br /&gt;
	end&lt;br /&gt;
	local values = { diff:age(show.id, diffOptions) }&lt;br /&gt;
	if values[1] then&lt;br /&gt;
		return makeText(values, show, names[abbr], textOptions)&lt;br /&gt;
	end&lt;br /&gt;
	if diff.partial then&lt;br /&gt;
		-- Handle a more complex range such as&lt;br /&gt;
		-- {{age_yd|20 Dec 2001|2003|range=yes}} → 1 year, 12 days or 2 years, 11 days&lt;br /&gt;
		local opt = {&lt;br /&gt;
			format = textOptions.format,&lt;br /&gt;
			join = textOptions.join,&lt;br /&gt;
			isnegative = textOptions.isnegative,&lt;br /&gt;
			spell = textOptions.spell,&lt;br /&gt;
		}&lt;br /&gt;
		return&lt;br /&gt;
			(textOptions.sortKey or &#039;&#039;) ..&lt;br /&gt;
			makeText({ diff.partial.mindiff:age(show.id, diffOptions) }, show, names[abbr], opt) ..&lt;br /&gt;
			rangeJoin(textOptions.range) ..&lt;br /&gt;
			makeText({ diff.partial.maxdiff:age(show.id, diffOptions) }, show, names[abbr], opt, true) ..&lt;br /&gt;
			(textOptions.suffix or &#039;&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	return message(&#039;mt-bad-show&#039;, show.id)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function getDates(frame, getopt)&lt;br /&gt;
	-- Parse template parameters and return one of:&lt;br /&gt;
	-- * date         (a date table, if single)&lt;br /&gt;
	-- * date1, date2 (two date tables, if not single)&lt;br /&gt;
	-- * text         (a string error message)&lt;br /&gt;
	-- A missing date is optionally replaced with the current date.&lt;br /&gt;
	-- If wantMixture is true, a missing date component is replaced&lt;br /&gt;
	-- from the current date, so can get a bizarre mixture of&lt;br /&gt;
	-- specified/current y/m/d as has been done by some &amp;quot;age&amp;quot; templates.&lt;br /&gt;
	-- Some results may be placed in table getopt.&lt;br /&gt;
	local Date, currentDate = getExports(frame)&lt;br /&gt;
	getopt = getopt or {}&lt;br /&gt;
	local function flagCurrent(text)&lt;br /&gt;
		-- This allows the calling template to detect if the current date has been used,&lt;br /&gt;
		-- that is, whether both dates have been entered in a template expecting two.&lt;br /&gt;
		-- For example, an infobox may want the age when an event occurred, not the current age.&lt;br /&gt;
		-- Don&#039;t bother detecting if wantMixture is used because not needed and it is a poor option.&lt;br /&gt;
		if not text then&lt;br /&gt;
			if getopt.noMissing then&lt;br /&gt;
				return nil  -- this gives a nil date which gives an error&lt;br /&gt;
			end&lt;br /&gt;
			text = &#039;currentdate&#039;&lt;br /&gt;
			if getopt.flag == &#039;usesCurrent&#039; then&lt;br /&gt;
				getopt.usesCurrent = true&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		return text&lt;br /&gt;
	end&lt;br /&gt;
	local args = frame:getParent().args&lt;br /&gt;
	local fields = {}&lt;br /&gt;
	local isNamed = args.year or args.year1 or args.year2 or&lt;br /&gt;
		args.month or args.month1 or args.month2 or&lt;br /&gt;
		args.day or args.day1 or args.day2&lt;br /&gt;
	if isNamed then&lt;br /&gt;
		fields[1] = args.year1 or args.year&lt;br /&gt;
		fields[2] = args.month1 or args.month&lt;br /&gt;
		fields[3] = args.day1 or args.day&lt;br /&gt;
		fields[4] = args.year2&lt;br /&gt;
		fields[5] = args.month2&lt;br /&gt;
		fields[6] = args.day2&lt;br /&gt;
	else&lt;br /&gt;
		for i = 1, 6 do&lt;br /&gt;
			fields[i] = args[i]&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local imax = 0&lt;br /&gt;
	for i = 1, 6 do&lt;br /&gt;
		fields[i] = stripToNil(fields[i])&lt;br /&gt;
		if fields[i] then&lt;br /&gt;
			imax = i&lt;br /&gt;
		end&lt;br /&gt;
		if getopt.omitZero and i % 3 ~= 1 then  -- omit zero months and days as unknown values but keep year 0 which is 1 BCE&lt;br /&gt;
			if isZero(fields[i]) then&lt;br /&gt;
				fields[i] = nil&lt;br /&gt;
				getopt.partial = true&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local fix = getopt.fix and &#039;fix&#039; or &#039;&#039;&lt;br /&gt;
	local partialText = getopt.partial and &#039;partial&#039; or &#039;&#039;&lt;br /&gt;
	local dates = {}&lt;br /&gt;
	if isNamed or imax &amp;gt;= 3 then&lt;br /&gt;
		local nrDates = getopt.single and 1 or 2&lt;br /&gt;
		if getopt.wantMixture then&lt;br /&gt;
			-- Cannot be partial since empty fields are set from current.&lt;br /&gt;
			local components = { &#039;year&#039;, &#039;month&#039;, &#039;day&#039; }&lt;br /&gt;
			for i = 1, nrDates * 3 do&lt;br /&gt;
				fields[i] = fields[i] or currentDate[components[i &amp;gt; 3 and i - 3 or i]]&lt;br /&gt;
			end&lt;br /&gt;
			for i = 1, nrDates do&lt;br /&gt;
				local index = i == 1 and 1 or 4&lt;br /&gt;
				local y, m, d = fields[index], fields[index+1], fields[index+2]&lt;br /&gt;
				if (m == 2 or m == &#039;2&#039;) and (d == 29 or d == &#039;29&#039;) then&lt;br /&gt;
					-- Workaround error with following which attempt to use invalid date 2001-02-29.&lt;br /&gt;
					-- {{age_ymwd|year1=2001|year2=2004|month2=2|day2=29}}&lt;br /&gt;
					-- {{age_ymwd|year1=2001|month1=2|year2=2004|month2=1|day2=29}}&lt;br /&gt;
					-- TODO Get rid of wantMixture because even this ugly code does not handle&lt;br /&gt;
					-- &#039;Feb&#039; or &#039;February&#039; or &#039;feb&#039; or &#039;february&#039;.&lt;br /&gt;
					if not ((y % 4 == 0 and y % 100 ~= 0) or y % 400 == 0) then&lt;br /&gt;
						d = 28&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
				dates[i] = Date(y, m, d)&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			-- If partial dates are allowed, accept&lt;br /&gt;
			--     year only, or&lt;br /&gt;
			--     year and month only&lt;br /&gt;
			-- Do not accept year and day without a month because that makes no sense&lt;br /&gt;
			-- (and because, for example, Date(&#039;partial&#039;, 2001, nil, 12) sets day = nil, not 12).&lt;br /&gt;
			for i = 1, nrDates do&lt;br /&gt;
				local index = i == 1 and 1 or 4&lt;br /&gt;
				local y, m, d = fields[index], fields[index+1], fields[index+2]&lt;br /&gt;
				if (getopt.partial and y and (m or not d)) or (y and m and d) then&lt;br /&gt;
					dates[i] = Date(fix, partialText, y, m, d)&lt;br /&gt;
				elseif not y and not m and not d then&lt;br /&gt;
					dates[i] = Date(flagCurrent())&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		getopt.textdates = true  -- have parsed each date from a single text field&lt;br /&gt;
		dates[1] = Date(fix, partialText, flagCurrent(fields[1]))&lt;br /&gt;
		if not getopt.single then&lt;br /&gt;
			dates[2] = Date(fix, partialText, flagCurrent(fields[2]))&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if not dates[1] then&lt;br /&gt;
		return message(getopt.missing1 or &#039;mt-need-valid-ymd&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	if getopt.single then&lt;br /&gt;
		return dates[1]&lt;br /&gt;
	end&lt;br /&gt;
	if not dates[2] then&lt;br /&gt;
		return message(getopt.missing2 or &#039;mt-need-valid-ymd2&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	return dates[1], dates[2]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function ageGeneric(frame)&lt;br /&gt;
	-- Return the result required by the specified template.&lt;br /&gt;
	-- Can use sortable=x where x = on/table/off/debug in any supported template.&lt;br /&gt;
	-- Some templates default to sortable=on but can be overridden.&lt;br /&gt;
	local name = frame.args.template&lt;br /&gt;
	if not name then&lt;br /&gt;
		return message(&#039;mt-template-x&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	local args = frame:getParent().args&lt;br /&gt;
	local specs = {&lt;br /&gt;
		age_days = {                -- {{age in days}}&lt;br /&gt;
			show = &#039;d&#039;,&lt;br /&gt;
			disp = &#039;disp_raw&#039;,&lt;br /&gt;
		},&lt;br /&gt;
		age_days_nts = {            -- {{age in days nts}}&lt;br /&gt;
			show = &#039;d&#039;,&lt;br /&gt;
			disp = &#039;disp_raw&#039;,&lt;br /&gt;
			format = &#039;format_commas&#039;,&lt;br /&gt;
			sortable = &#039;on&#039;,&lt;br /&gt;
		},&lt;br /&gt;
		duration_days = {           -- {{duration in days}}&lt;br /&gt;
			show = &#039;d&#039;,&lt;br /&gt;
			disp = &#039;disp_raw&#039;,&lt;br /&gt;
			duration = true,&lt;br /&gt;
		},&lt;br /&gt;
		duration_days_nts = {       -- {{duration in days nts}}&lt;br /&gt;
			show = &#039;d&#039;,&lt;br /&gt;
			disp = &#039;disp_raw&#039;,&lt;br /&gt;
			format = &#039;format_commas&#039;,&lt;br /&gt;
			sortable = &#039;on&#039;,&lt;br /&gt;
			duration = true,&lt;br /&gt;
		},&lt;br /&gt;
		age_full_years = {          -- {{age}}&lt;br /&gt;
			show = &#039;y&#039;,&lt;br /&gt;
			abbr = &#039;abbr_raw&#039;,&lt;br /&gt;
			flag = &#039;usesCurrent&#039;,&lt;br /&gt;
			omitZero = true,&lt;br /&gt;
			range = &#039;no&#039;,&lt;br /&gt;
		},&lt;br /&gt;
		age_full_years_nts = {      -- {{age nts}}&lt;br /&gt;
			show = &#039;y&#039;,&lt;br /&gt;
			abbr = &#039;abbr_raw&#039;,&lt;br /&gt;
			format = &#039;format_commas&#039;,&lt;br /&gt;
			sortable = &#039;on&#039;,&lt;br /&gt;
		},&lt;br /&gt;
		age_in_years = {            -- {{age in years}}&lt;br /&gt;
			show = &#039;y&#039;,&lt;br /&gt;
			abbr = &#039;abbr_raw&#039;,&lt;br /&gt;
			negative = &#039;error&#039;,&lt;br /&gt;
			range = &#039;dash&#039;,&lt;br /&gt;
		},&lt;br /&gt;
		age_in_years_nts = {        -- {{age in years nts}}&lt;br /&gt;
			show = &#039;y&#039;,&lt;br /&gt;
			abbr = &#039;abbr_raw&#039;,&lt;br /&gt;
			negative = &#039;error&#039;,&lt;br /&gt;
			range = &#039;dash&#039;,&lt;br /&gt;
			format = &#039;format_commas&#039;,&lt;br /&gt;
			sortable = &#039;on&#039;,&lt;br /&gt;
		},&lt;br /&gt;
		age_infant = {              -- {{age for infant}}&lt;br /&gt;
			-- Do not set show because special processing is done later.&lt;br /&gt;
			abbr = yes(args.abbr) and &#039;abbr_infant&#039; or &#039;abbr_off&#039;,&lt;br /&gt;
			disp = &#039;disp_age&#039;,&lt;br /&gt;
			sep = &#039;sep_space&#039;,&lt;br /&gt;
			sortable = &#039;on&#039;,&lt;br /&gt;
		},&lt;br /&gt;
		age_m = {                   -- {{age in months}}&lt;br /&gt;
			show = &#039;m&#039;,&lt;br /&gt;
			disp = &#039;disp_raw&#039;,&lt;br /&gt;
		},&lt;br /&gt;
		age_w = {                   -- {{age in weeks}}&lt;br /&gt;
			show = &#039;w&#039;,&lt;br /&gt;
			disp = &#039;disp_raw&#039;,&lt;br /&gt;
		},&lt;br /&gt;
		age_wd = {                  -- {{age in weeks and days}}&lt;br /&gt;
			show = &#039;wd&#039;,&lt;br /&gt;
		},&lt;br /&gt;
		age_yd = {                  -- {{age in years and days}}&lt;br /&gt;
			show = &#039;yd&#039;,&lt;br /&gt;
			format = &#039;format_commas&#039;,&lt;br /&gt;
			sep = args.sep ~= &#039;and&#039; and &#039;sep_comma&#039; or nil,&lt;br /&gt;
		},&lt;br /&gt;
		age_yd_nts = {              -- {{age in years and days nts}}&lt;br /&gt;
			show = &#039;yd&#039;,&lt;br /&gt;
			format = &#039;format_commas&#039;,&lt;br /&gt;
			sep = args.sep ~= &#039;and&#039; and &#039;sep_comma&#039; or nil,&lt;br /&gt;
			sortable = &#039;on&#039;,&lt;br /&gt;
		},&lt;br /&gt;
		age_ym = {                  -- {{age in years and months}}&lt;br /&gt;
			show = &#039;ym&#039;,&lt;br /&gt;
			sep = &#039;sep_comma&#039;,&lt;br /&gt;
		},&lt;br /&gt;
		age_ymd = {                 -- {{age in years, months and days}}&lt;br /&gt;
			show = &#039;ymd&#039;,&lt;br /&gt;
			range = true,&lt;br /&gt;
		},&lt;br /&gt;
		age_ymwd = {                -- {{age in years, months, weeks and days}}&lt;br /&gt;
			show = &#039;ymwd&#039;,&lt;br /&gt;
			wantMixture = true,&lt;br /&gt;
		},&lt;br /&gt;
	}&lt;br /&gt;
	local spec = specs[name]&lt;br /&gt;
	if not spec then&lt;br /&gt;
		return message(&#039;mt-template-bad-name&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	if name == &#039;age_days&#039; then&lt;br /&gt;
		local su = stripToNil(args[&#039;show unit&#039;])&lt;br /&gt;
		if su then&lt;br /&gt;
			if su == &#039;abbr&#039; or su == &#039;full&#039; then&lt;br /&gt;
				spec.disp = nil&lt;br /&gt;
				spec.abbr = su == &#039;abbr&#039; and &#039;abbr_on&#039; or nil&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local partial, autofill&lt;br /&gt;
	local range = stripToNil(args.range) or spec.range&lt;br /&gt;
	if range then&lt;br /&gt;
		-- Suppose partial dates are used and age could be 11 or 12 years.&lt;br /&gt;
		-- &amp;quot;|range=&amp;quot; (empty value) has no effect (spec is used).&lt;br /&gt;
		-- &amp;quot;|range=yes&amp;quot; or spec.range == true sets range = true (gives &amp;quot;11 or 12&amp;quot;)&lt;br /&gt;
		-- &amp;quot;|range=dash&amp;quot; or spec.range == &#039;dash&#039; sets range = &#039;dash&#039; (gives &amp;quot;11–12&amp;quot;).&lt;br /&gt;
		-- &amp;quot;|range=no&amp;quot; or spec.range == &#039;no&#039; sets range = nil and fills each date in the diff (gives &amp;quot;12&amp;quot;).&lt;br /&gt;
		--     (&amp;quot;on&amp;quot; is equivalent to &amp;quot;yes&amp;quot;, and &amp;quot;off&amp;quot; is equivalent to &amp;quot;no&amp;quot;).&lt;br /&gt;
		-- &amp;quot;|range=OTHER&amp;quot; sets range = nil and rejects partial dates.&lt;br /&gt;
		range = ({ dash = &#039;dash&#039;, off = &#039;no&#039;, no = &#039;no&#039;, [true] = true })[range] or yes(range)&lt;br /&gt;
		if range then&lt;br /&gt;
			partial = true  -- accept partial dates with a possible age range for the result&lt;br /&gt;
			if range == &#039;no&#039; then&lt;br /&gt;
				autofill = true  -- missing month/day in first or second date are filled from other date or 1&lt;br /&gt;
				range = nil&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local getopt = {&lt;br /&gt;
		fix = yes(args.fix),&lt;br /&gt;
		flag = stripToNil(args.flag) or spec.flag,&lt;br /&gt;
		omitZero = spec.omitZero,&lt;br /&gt;
		partial = partial,&lt;br /&gt;
		wantMixture = spec.wantMixture,&lt;br /&gt;
	}&lt;br /&gt;
	local date1, date2 = getDates(frame, getopt)&lt;br /&gt;
	if type(date1) == &#039;string&#039; then&lt;br /&gt;
		return date1&lt;br /&gt;
	end&lt;br /&gt;
	local format = stripToNil(args.format)&lt;br /&gt;
	local spell = spellOptions[format]&lt;br /&gt;
	if format then&lt;br /&gt;
		format = &#039;format_&#039; .. format&lt;br /&gt;
	elseif name == &#039;age_days&#039; and getopt.textdates then&lt;br /&gt;
		format = &#039;format_commas&#039;&lt;br /&gt;
	end&lt;br /&gt;
	local parms = {&lt;br /&gt;
		diff = date2:subtract(date1, { fill = autofill }),&lt;br /&gt;
		wantDuration = spec.duration or yes(args.duration),&lt;br /&gt;
		range = range,&lt;br /&gt;
		wantSc = yes(args.sc),&lt;br /&gt;
		show = args.show == &#039;hide&#039; and &#039;hide&#039; or spec.show,&lt;br /&gt;
		abbr = spec.abbr,&lt;br /&gt;
		disp = spec.disp,&lt;br /&gt;
		extra = makeExtra(args, getopt.usesCurrent and format ~= &#039;format_raw&#039;),&lt;br /&gt;
		format = format or spec.format,&lt;br /&gt;
		round = yes(args.round),&lt;br /&gt;
		sep = spec.sep,&lt;br /&gt;
		sortable = translateParameters.sortable[args.sortable or spec.sortable],&lt;br /&gt;
		spell = spell,&lt;br /&gt;
	}&lt;br /&gt;
	if (spec.negative or frame.args.negative) == &#039;error&#039; and parms.diff.isnegative then&lt;br /&gt;
		return message(&#039;mt-date-wrong-order&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	return from_en(dateDifference(parms))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function bda(frame)&lt;br /&gt;
	-- Implement [[Template:Birth date and age]].&lt;br /&gt;
	local args = frame:getParent().args&lt;br /&gt;
	local options = {&lt;br /&gt;
		missing1 = &#039;mt-need-valid-bd&#039;,&lt;br /&gt;
		noMissing = true,&lt;br /&gt;
		single = true,&lt;br /&gt;
	}&lt;br /&gt;
	local date = getDates(frame, options)&lt;br /&gt;
	if type(date) == &#039;string&#039; then&lt;br /&gt;
		return date  -- error text&lt;br /&gt;
	end&lt;br /&gt;
	local Date = getExports(frame)&lt;br /&gt;
	local diff = Date(&#039;currentdate&#039;) - date&lt;br /&gt;
	if diff.isnegative or diff.years &amp;gt; 150 then&lt;br /&gt;
		return message(&#039;mt-invalid-bd-age&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	local disp = mtext[&#039;txt-bda-disp&#039;]&lt;br /&gt;
	local show = &#039;y&#039;&lt;br /&gt;
	if diff.years &amp;lt; 2 then&lt;br /&gt;
		disp = &#039;disp_age&#039;&lt;br /&gt;
		if diff.years == 0 and diff.months == 0 then&lt;br /&gt;
			show = &#039;d&#039;&lt;br /&gt;
		else&lt;br /&gt;
			show = &#039;m&#039;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local result = substituteParameters(&lt;br /&gt;
		mtext[&#039;txt-bda&#039;],&lt;br /&gt;
		date:text(&#039;%-Y-%m-%d&#039;),&lt;br /&gt;
		from_en(date:text(dateFormat(args))),&lt;br /&gt;
		from_en(dateDifference({&lt;br /&gt;
			diff = diff,&lt;br /&gt;
			show = show,&lt;br /&gt;
			abbr = &#039;abbr_off&#039;,&lt;br /&gt;
			disp = disp,&lt;br /&gt;
			sep = &#039;sep_space&#039;,&lt;br /&gt;
		}))&lt;br /&gt;
	)&lt;br /&gt;
	local warnings = tonumber(frame.args.warnings)&lt;br /&gt;
	if warnings and warnings &amp;gt; 0 then&lt;br /&gt;
		local good = {&lt;br /&gt;
			df = true,&lt;br /&gt;
			mf = true,&lt;br /&gt;
			day = true,&lt;br /&gt;
			day1 = true,&lt;br /&gt;
			month = true,&lt;br /&gt;
			month1 = true,&lt;br /&gt;
			year = true,&lt;br /&gt;
			year1 = true,&lt;br /&gt;
		}&lt;br /&gt;
		local invalid&lt;br /&gt;
		local imax = options.textdates and 1 or 3&lt;br /&gt;
		for k, _ in pairs(args) do&lt;br /&gt;
			if type(k) == &#039;number&#039; then&lt;br /&gt;
				if k &amp;gt; imax then&lt;br /&gt;
					invalid = tostring(k)&lt;br /&gt;
					break&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				if not good[k] then&lt;br /&gt;
					invalid = k&lt;br /&gt;
					break&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		if invalid then&lt;br /&gt;
			result = result .. message(&#039;mt-bad-param1&#039;, invalid)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function dda(frame)&lt;br /&gt;
	-- Implement [[Template:Death date and age]].&lt;br /&gt;
	local args = frame:getParent().args&lt;br /&gt;
	local options = {&lt;br /&gt;
		missing1 = &#039;mt-need-valid-dd&#039;,&lt;br /&gt;
		missing2 = &#039;mt-need-valid-bd2&#039;,&lt;br /&gt;
		noMissing = true,&lt;br /&gt;
		partial = true,&lt;br /&gt;
	}&lt;br /&gt;
	local date1, date2 = getDates(frame, options)&lt;br /&gt;
	if type(date1) == &#039;string&#039; then&lt;br /&gt;
		return date1&lt;br /&gt;
	end&lt;br /&gt;
	local diff = date1 - date2&lt;br /&gt;
	if diff.isnegative then&lt;br /&gt;
		return message(&#039;mt-dd-wrong-order&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	local Date = getExports(frame)&lt;br /&gt;
	local today = Date(&#039;currentdate&#039;) + 1  -- one day in future allows for timezones&lt;br /&gt;
	if date1 &amp;gt; today then&lt;br /&gt;
		return message(&#039;mt-dd-future&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	local years&lt;br /&gt;
	if diff.partial then&lt;br /&gt;
		years = diff.partial.years&lt;br /&gt;
		years = type(years) == &#039;table&#039; and years[2] or years&lt;br /&gt;
	else&lt;br /&gt;
		years = diff.years&lt;br /&gt;
	end&lt;br /&gt;
	if years &amp;gt; 150 then&lt;br /&gt;
		return message(&#039;mt-invalid-dates-age&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	local fmt_date, fmt_ymd&lt;br /&gt;
	if date1.day then  -- y, m, d known&lt;br /&gt;
		fmt_date = dateFormat(args)&lt;br /&gt;
		fmt_ymd = &#039;%-Y-%m-%d&#039;&lt;br /&gt;
	elseif date1.month then  -- y, m known; d unknown&lt;br /&gt;
		fmt_date = &#039;%B %-Y&#039;&lt;br /&gt;
		fmt_ymd = &#039;%-Y-%m-00&#039;&lt;br /&gt;
	else  -- y known; m, d unknown&lt;br /&gt;
		fmt_date = &#039;%-Y&#039;&lt;br /&gt;
		fmt_ymd = &#039;%-Y-00-00&#039;&lt;br /&gt;
	end&lt;br /&gt;
	local sortKey&lt;br /&gt;
	local sortable = translateParameters.sortable[args.sortable]&lt;br /&gt;
	if sortable then&lt;br /&gt;
		local value = (date1.partial and date1.partial.first or date1).jdz&lt;br /&gt;
		sortKey = makeSort(value, sortable)&lt;br /&gt;
	end&lt;br /&gt;
	local result = (sortKey or &#039;&#039;) .. substituteParameters(&lt;br /&gt;
		mtext[&#039;txt-dda&#039;],&lt;br /&gt;
		date1:text(fmt_ymd),&lt;br /&gt;
		from_en(date1:text(fmt_date)),&lt;br /&gt;
		from_en(dateDifference({&lt;br /&gt;
			diff = diff,&lt;br /&gt;
			show = &#039;y&#039;,&lt;br /&gt;
			abbr = &#039;abbr_off&#039;,&lt;br /&gt;
			disp = mtext[&#039;txt-dda-disp&#039;],&lt;br /&gt;
			range = &#039;dash&#039;,&lt;br /&gt;
			sep = &#039;sep_space&#039;,&lt;br /&gt;
		}))&lt;br /&gt;
	)&lt;br /&gt;
	local warnings = tonumber(frame.args.warnings)&lt;br /&gt;
	if warnings and warnings &amp;gt; 0 then&lt;br /&gt;
		local good = {&lt;br /&gt;
			df = true,&lt;br /&gt;
			mf = true,&lt;br /&gt;
		}&lt;br /&gt;
		local invalid&lt;br /&gt;
		local imax = options.textdates and 2 or 6&lt;br /&gt;
		for k, _ in pairs(args) do&lt;br /&gt;
			if type(k) == &#039;number&#039; then&lt;br /&gt;
				if k &amp;gt; imax then&lt;br /&gt;
					invalid = tostring(k)&lt;br /&gt;
					break&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				if not good[k] then&lt;br /&gt;
					invalid = k&lt;br /&gt;
					break&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		if invalid then&lt;br /&gt;
			result = result .. message(&#039;mt-bad-param1&#039;, invalid)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function dateToGsd(frame)&lt;br /&gt;
	-- Implement [[Template:Gregorian serial date]].&lt;br /&gt;
	-- Return Gregorian serial date of the given date, or the current date.&lt;br /&gt;
	-- The returned value is negative for dates before 1 January 1 AD&lt;br /&gt;
	-- despite the fact that GSD is not defined for such dates.&lt;br /&gt;
	local date = getDates(frame, { wantMixture=true, single=true })&lt;br /&gt;
	if type(date) == &#039;string&#039; then&lt;br /&gt;
		return date&lt;br /&gt;
	end&lt;br /&gt;
	return tostring(date.gsd)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function jdToDate(frame)&lt;br /&gt;
	-- Return formatted date from a Julian date.&lt;br /&gt;
	-- The result includes a time if the input includes a fraction.&lt;br /&gt;
	-- The word &#039;Julian&#039; is accepted for the Julian calendar.&lt;br /&gt;
	local Date = getExports(frame)&lt;br /&gt;
	local args = frame:getParent().args&lt;br /&gt;
	local date = Date(&#039;juliandate&#039;, args[1], args[2])&lt;br /&gt;
	if date then&lt;br /&gt;
		return from_en(date:text())&lt;br /&gt;
	end&lt;br /&gt;
	return message(&#039;mt-need-jdn&#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function dateToJd(frame)&lt;br /&gt;
	-- Return Julian date (a number) from a date which may include a time,&lt;br /&gt;
	-- or the current date (&#039;currentdate&#039;) or current date and time (&#039;currentdatetime&#039;).&lt;br /&gt;
	-- The word &#039;Julian&#039; is accepted for the Julian calendar.&lt;br /&gt;
	local Date = getExports(frame)&lt;br /&gt;
	local args = frame:getParent().args&lt;br /&gt;
	local date = Date(args[1], args[2], args[3], args[4], args[5], args[6], args[7])&lt;br /&gt;
	if date then&lt;br /&gt;
		return tostring(date.jd)&lt;br /&gt;
	end&lt;br /&gt;
	return message(&#039;mt-need-valid-ymd-current&#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function timeInterval(frame)&lt;br /&gt;
	-- Implement [[Template:Time interval]].&lt;br /&gt;
	-- There are two positional arguments: date1, date2.&lt;br /&gt;
	-- The default for each is the current date and time.&lt;br /&gt;
	-- Result is date2 - date1 formatted.&lt;br /&gt;
	local Date = getExports(frame)&lt;br /&gt;
	local args = frame:getParent().args&lt;br /&gt;
	local parms = {&lt;br /&gt;
		extra = makeExtra(args),&lt;br /&gt;
		wantDuration = yes(args.duration),&lt;br /&gt;
		range = yes(args.range) or (args.range == &#039;dash&#039; and &#039;dash&#039; or nil),&lt;br /&gt;
		wantSc = yes(args.sc),&lt;br /&gt;
	}&lt;br /&gt;
	local fix = yes(args.fix) and &#039;fix&#039; or &#039;&#039;&lt;br /&gt;
	local date1 = Date(fix, &#039;partial&#039;, stripToNil(args[1]) or &#039;currentdatetime&#039;)&lt;br /&gt;
	if not date1 then&lt;br /&gt;
		return message(&#039;mt-invalid-start&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	local date2 = Date(fix, &#039;partial&#039;, stripToNil(args[2]) or &#039;currentdatetime&#039;)&lt;br /&gt;
	if not date2 then&lt;br /&gt;
		return message(&#039;mt-invalid-end&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	parms.diff = date2 - date1&lt;br /&gt;
	for argname, translate in pairs(translateParameters) do&lt;br /&gt;
		local parm = stripToNil(args[argname])&lt;br /&gt;
		if parm then&lt;br /&gt;
			parm = translate[parm]&lt;br /&gt;
			if parm == nil then  -- test for nil because false is a valid setting&lt;br /&gt;
				return message(&#039;mt-bad-param2&#039;, argname, args[argname])&lt;br /&gt;
			end&lt;br /&gt;
			parms[argname] = parm&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if parms.round then&lt;br /&gt;
		local round = parms.round&lt;br /&gt;
		local show = parms.show&lt;br /&gt;
		if round ~= &#039;on&#039; then&lt;br /&gt;
			if show then&lt;br /&gt;
				if show.id ~= round then&lt;br /&gt;
					return message(&#039;mt-conflicting-show&#039;, args.show, args.round)&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				parms.show = translateParameters.show[round]&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		parms.round = true&lt;br /&gt;
	end&lt;br /&gt;
	return from_en(dateDifference(parms))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return {&lt;br /&gt;
	age_generic = ageGeneric,           -- can emulate several age templates&lt;br /&gt;
	birth_date_and_age = bda,           -- Template:Birth_date_and_age&lt;br /&gt;
	death_date_and_age = dda,           -- Template:Death_date_and_age&lt;br /&gt;
	gsd = dateToGsd,                    -- Template:Gregorian_serial_date&lt;br /&gt;
	extract = dateExtract,              -- Template:Extract&lt;br /&gt;
	jd_to_date = jdToDate,              -- Template:?&lt;br /&gt;
	JULIANDAY = dateToJd,               -- Template:JULIANDAY&lt;br /&gt;
	time_interval = timeInterval,       -- Template:Time_interval&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Vorlage:Use_mdy_dates&amp;diff=1511</id>
		<title>Vorlage:Use mdy dates</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Vorlage:Use_mdy_dates&amp;diff=1511"/>
		<updated>2022-08-12T16:59:07Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ safesubst:&amp;lt;noinclude/&amp;gt;#invoke:Unsubst||date=__DATE__ |$B=&lt;br /&gt;
{{DMCA|Use mdy dates|from|{{{date|}}}}}{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Pages using Use mdy dates template with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Use mdy dates]] with unknown parameter &amp;quot;_VALUE_&amp;quot;|ignoreblank=y| cs1-dates | date }}}}&amp;lt;noinclude&amp;gt;{{Documentation}}&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Vorlage:United_States_presidents_by_age&amp;diff=1509</id>
		<title>Vorlage:United States presidents by age</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Vorlage:United_States_presidents_by_age&amp;diff=1509"/>
		<updated>2022-08-12T16:59:07Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;timeline&amp;gt;&lt;br /&gt;
ImageSize = width:1000 height:700&lt;br /&gt;
PlotArea  = width:900 height:670 left:80 bottom:30&lt;br /&gt;
AlignBars = justify&lt;br /&gt;
&lt;br /&gt;
Colors =&lt;br /&gt;
  id:pre   value:rgb(0.7,0.7,0.7) # grey&lt;br /&gt;
  id:pres  value:rgb(0,0,1) # blue&lt;br /&gt;
  id:post  value:rgb(0.7,0.7,0.7) # grey&lt;br /&gt;
  id:alive value:rgb(0.5,0.8,0.5) # green&lt;br /&gt;
&lt;br /&gt;
Period     = from:0 till:100&lt;br /&gt;
TimeAxis   = orientation:horizontal&lt;br /&gt;
ScaleMajor = unit:year increment:10 start:0&lt;br /&gt;
ScaleMinor = unit:year increment:1  start:0&lt;br /&gt;
&lt;br /&gt;
LineData = &lt;br /&gt;
 at:10 layer:front width:0.25&lt;br /&gt;
 at:20 layer:front width:0.25&lt;br /&gt;
 at:30 layer:front width:0.25&lt;br /&gt;
 at:40 layer:front width:0.25&lt;br /&gt;
 at:50 layer:front width:0.25&lt;br /&gt;
 at:60 layer:front width:0.25&lt;br /&gt;
 at:70 layer:front width:0.25&lt;br /&gt;
 at:80 layer:front width:0.25&lt;br /&gt;
 at:90 layer:front width:0.25&lt;br /&gt;
 at:100 layer:front width:0.25&lt;br /&gt;
&lt;br /&gt;
PlotData=&lt;br /&gt;
  align:center   width:8 shift:(0,-0)&lt;br /&gt;
&lt;br /&gt;
  bar:Washington color:pre from:0  till:  57.18&lt;br /&gt;
  bar:Washington color:pres from:57.18  till:  65.02&lt;br /&gt;
  bar:Washington color:post from:65.02  till:  67.8&lt;br /&gt;
&lt;br /&gt;
  bar:Adams color:pre from:0  till:  61.34&lt;br /&gt;
  bar:Adams color:pres from:61.34  till:  65.34&lt;br /&gt;
  bar:Adams color:post from:65.34  till:  90.67&lt;br /&gt;
&lt;br /&gt;
  bar:Jefferson color:pre from:0  till:  57.89&lt;br /&gt;
  bar:Jefferson color:pres from:57.89  till:  65.89&lt;br /&gt;
  bar:Jefferson color:post from:65.89  till:  83.22&lt;br /&gt;
&lt;br /&gt;
  bar:Madison color:pre from:0  till:  57.97&lt;br /&gt;
  bar:Madison color:pres from:57.97  till:  65.97&lt;br /&gt;
  bar:Madison color:post from:65.97  till:  85.29&lt;br /&gt;
&lt;br /&gt;
  bar:Monroe color:pre from:0  till:  58.85&lt;br /&gt;
  bar:Monroe color:pres from:58.85  till:  66.85&lt;br /&gt;
  bar:Monroe color:post from:66.85  till:  73.18&lt;br /&gt;
&lt;br /&gt;
  bar:J.&amp;amp;#32;Q.&amp;amp;#32;Adams color:pre from:0  till:  57.65&lt;br /&gt;
  bar:J.&amp;amp;#32;Q.&amp;amp;#32;Adams color:pres from:57.65  till:  61.65&lt;br /&gt;
  bar:J.&amp;amp;#32;Q.&amp;amp;#32;Adams color:post from:61.65  till:  80.63&lt;br /&gt;
&lt;br /&gt;
  bar:Jackson color:pre from:0  till:  61.97&lt;br /&gt;
  bar:Jackson color:pres from:61.97  till:  69.97&lt;br /&gt;
  bar:Jackson color:post from:69.97  till:  78.23&lt;br /&gt;
&lt;br /&gt;
  bar:Van&amp;amp;#32;Buren color:pre from:0  till:  79.63&lt;br /&gt;
  bar:Van&amp;amp;#32;Buren color:pres from:54.24  till:  58.24&lt;br /&gt;
&lt;br /&gt;
  bar:W.&amp;amp;#32;Harrison color:pre from:0  till:  68.04&lt;br /&gt;
  bar:W.&amp;amp;#32;Harrison color:pres from:68.04  till:  68.14&lt;br /&gt;
&lt;br /&gt;
  bar:Tyler color:pre from:0  till:  51.02&lt;br /&gt;
  bar:Tyler color:pres from:51.02  till:  54.94&lt;br /&gt;
  bar:Tyler color:post from:54.94  till:  71.82&lt;br /&gt;
&lt;br /&gt;
  bar:Polk color:pre from:0  till:  49.33&lt;br /&gt;
  bar:Polk color:pres from:49.33  till:  53.33&lt;br /&gt;
  bar:Polk color:post from:53.33  till:  53.61&lt;br /&gt;
&lt;br /&gt;
  bar:Taylor color:pre from:0  till:  64.27&lt;br /&gt;
  bar:Taylor color:pres from:64.27  till:  65.62&lt;br /&gt;
&lt;br /&gt;
  bar:Fillmore color:pre from:0  till:  50.5&lt;br /&gt;
  bar:Fillmore color:pres from:50.5  till:  53.15&lt;br /&gt;
  bar:Fillmore color:post from:53.15  till:  74.16&lt;br /&gt;
&lt;br /&gt;
  bar:Pierce color:pre from:0  till:  48.28&lt;br /&gt;
  bar:Pierce color:pres from:48.28  till:  52.28&lt;br /&gt;
  bar:Pierce color:post from:52.28  till:  64.88&lt;br /&gt;
&lt;br /&gt;
  bar:Buchanan color:pre from:0  till:  65.86&lt;br /&gt;
  bar:Buchanan color:pres from:65.86  till:  69.86&lt;br /&gt;
  bar:Buchanan color:post from:69.86  till:  77.1&lt;br /&gt;
&lt;br /&gt;
  bar:Lincoln color:pre from:0  till:  52.05&lt;br /&gt;
  bar:Lincoln color:pres from:52.05  till:  56.17&lt;br /&gt;
&lt;br /&gt;
  bar:A.&amp;amp;#32;Johnson color:pre from:0  till:  56.29&lt;br /&gt;
  bar:A.&amp;amp;#32;Johnson color:pres from:56.29  till:  60.17&lt;br /&gt;
  bar:A.&amp;amp;#32;Johnson color:post from:60.17  till:  66.58&lt;br /&gt;
&lt;br /&gt;
  bar:Grant color:pre from:0  till:  46.85&lt;br /&gt;
  bar:Grant color:pres from:46.85  till:  54.85&lt;br /&gt;
  bar:Grant color:post from:54.85  till:  63.24&lt;br /&gt;
&lt;br /&gt;
  bar:Hayes color:pre from:0  till:  54.41&lt;br /&gt;
  bar:Hayes color:pres from:54.41  till:  58.41&lt;br /&gt;
  bar:Hayes color:post from:58.41  till:  70.28&lt;br /&gt;
&lt;br /&gt;
  bar:Garfield color:pre from:0  till:  49.29&lt;br /&gt;
  bar:Garfield color:pres from:49.29  till:  49.84&lt;br /&gt;
&lt;br /&gt;
  bar:Arthur color:pre from:0  till:  51.96&lt;br /&gt;
  bar:Arthur color:pres from:51.96  till:  55.41&lt;br /&gt;
  bar:Arthur color:post from:55.41  till:  57.12&lt;br /&gt;
&lt;br /&gt;
  bar:Cleveland color:pre from:0  till:  47.96&lt;br /&gt;
  bar:Cleveland color:pres from:47.96  till:  51.96&lt;br /&gt;
  bar:Cleveland color:post from:51.96  till:  55.96&lt;br /&gt;
  bar:Cleveland color:pres from:55.96  till:  59.96&lt;br /&gt;
  bar:Cleveland color:post from:59.96  till:  71.27&lt;br /&gt;
&lt;br /&gt;
  bar:B.&amp;amp;#32;Harrison color:pre from:0  till:  55.54&lt;br /&gt;
  bar:B.&amp;amp;#32;Harrison color:pres from:55.54  till:  59.54&lt;br /&gt;
  bar:B.&amp;amp;#32;Harrison color:post from:59.54  till:  67.56&lt;br /&gt;
&lt;br /&gt;
  bar:McKinley color:pre from:0  till:  54.09&lt;br /&gt;
  bar:McKinley color:pres from:54.09  till:  58.62&lt;br /&gt;
&lt;br /&gt;
  bar:T.&amp;amp;#32;Roosevelt color:pre from:0  till:  42.88&lt;br /&gt;
  bar:T.&amp;amp;#32;Roosevelt color:pres from:42.88  till:  50.35&lt;br /&gt;
  bar:T.&amp;amp;#32;Roosevelt color:post from:50.35  till:  60.19&lt;br /&gt;
&lt;br /&gt;
  bar:Taft color:pre from:0  till:  51.47&lt;br /&gt;
  bar:Taft color:pres from:51.47  till:  55.47&lt;br /&gt;
  bar:Taft color:post from:55.47  till:  72.48&lt;br /&gt;
&lt;br /&gt;
  bar:Wilson color:pre from:0  till:  56.18&lt;br /&gt;
  bar:Wilson color:pres from:56.18  till:  64.18&lt;br /&gt;
  bar:Wilson color:post from:64.18  till:  67.1&lt;br /&gt;
&lt;br /&gt;
  bar:Harding color:pre from:0  till:  55.33&lt;br /&gt;
  bar:Harding color:pres from:55.33  till:  57.74&lt;br /&gt;
&lt;br /&gt;
  bar:Coolidge color:pre from:0  till:  51.08&lt;br /&gt;
  bar:Coolidge color:pres from:51.08  till:  56.67&lt;br /&gt;
  bar:Coolidge color:post from:56.67  till:  60.51&lt;br /&gt;
&lt;br /&gt;
  bar:Hoover color:pre from:0  till:  54.56&lt;br /&gt;
  bar:Hoover color:pres from:54.56  till:  58.56&lt;br /&gt;
  bar:Hoover color:post from:58.56  till:  90.19&lt;br /&gt;
&lt;br /&gt;
  bar:F.&amp;amp;#32;Roosevelt color:pre from:0  till:  51.09&lt;br /&gt;
  bar:F.&amp;amp;#32;Roosevelt color:pres from:51.09  till:  63.2&lt;br /&gt;
&lt;br /&gt;
  bar:Truman color:pre from:0  till:  60.93&lt;br /&gt;
  bar:Truman color:pres from:60.93  till:  68.71&lt;br /&gt;
  bar:Truman color:post from:68.71  till:  88.64&lt;br /&gt;
&lt;br /&gt;
  bar:Eisenhower color:pre from:0  till:  62.27&lt;br /&gt;
  bar:Eisenhower color:pres from:62.27  till:  70.27&lt;br /&gt;
  bar:Eisenhower color:post from:70.27  till:  78.45&lt;br /&gt;
&lt;br /&gt;
  bar:Kennedy color:pre from:0  till:  43.65&lt;br /&gt;
  bar:Kennedy color:pres from:43.65  till:  46.49&lt;br /&gt;
&lt;br /&gt;
  bar:Johnson color:pre from:0  till:  55.24&lt;br /&gt;
  bar:Johnson color:pres from:55.24  till:  60.4&lt;br /&gt;
  bar:Johnson color:post from:60.4  till:  64.41&lt;br /&gt;
&lt;br /&gt;
  bar:Nixon color:pre from:0  till:  56.03&lt;br /&gt;
  bar:Nixon color:pres from:56.03  till:  61.58&lt;br /&gt;
  bar:Nixon color:post from:61.58  till:  81.28&lt;br /&gt;
&lt;br /&gt;
  bar:Ford color:pre from:0  till:  61.07&lt;br /&gt;
  bar:Ford color:pres from:61.07  till:  63.52&lt;br /&gt;
  bar:Ford color:post from:63.52  till:  93.45&lt;br /&gt;
&lt;br /&gt;
  bar:Carter color:alive from:0  till:  52.3&lt;br /&gt;
  bar:Carter color:pres from:52.3  till:  56.3&lt;br /&gt;
  bar:Carter color:alive from:56.3  till:  96.94&lt;br /&gt;
&lt;br /&gt;
  bar:Reagan color:pre from:0  till:  69.96&lt;br /&gt;
  bar:Reagan color:pres from:69.96  till:  77.96&lt;br /&gt;
  bar:Reagan color:post from:77.96  till:  93.33&lt;br /&gt;
&lt;br /&gt;
  bar:G.&amp;amp;#32;H.&amp;amp;#32;W.&amp;amp;#32;Bush color:pre from:0  till:  64.61&lt;br /&gt;
  bar:G.&amp;amp;#32;H.&amp;amp;#32;W.&amp;amp;#32;Bush color:pres from:64.61  till:  68.61&lt;br /&gt;
  bar:G.&amp;amp;#32;H.&amp;amp;#32;W.&amp;amp;#32;Bush color:post from:68.61  till:  94.47&lt;br /&gt;
&lt;br /&gt;
  bar:Clinton color:alive from:0  till:  46.42&lt;br /&gt;
  bar:Clinton color:pres from:46.42  till:  54.42&lt;br /&gt;
  bar:Clinton color:alive from:54.42  till:  75.06&lt;br /&gt;
&lt;br /&gt;
  bar:G.&amp;amp;#32;W.&amp;amp;#32;Bush color:alive from:0  till:  54.54&lt;br /&gt;
  bar:G.&amp;amp;#32;W.&amp;amp;#32;Bush color:pres from:54.54  till:  62.54&lt;br /&gt;
  bar:G.&amp;amp;#32;W.&amp;amp;#32;Bush color:alive from:62.54  till:  75.18&lt;br /&gt;
&lt;br /&gt;
  bar:Obama color:alive from:0  till:  47.46&lt;br /&gt;
  bar:Obama color:pres from:47.46  till:  55.46&lt;br /&gt;
  bar:Obama color:alive from:55.46  till:  60.10&lt;br /&gt;
&lt;br /&gt;
  bar:Trump color:alive from:0  till:  70.6&lt;br /&gt;
  bar:Trump color:pres from:70.6  till:  74.6&lt;br /&gt;
  bar:Trump color:alive from:74.6  till:  75.24&lt;br /&gt;
&lt;br /&gt;
  bar:Biden color:alive from:0  till:  78.17&lt;br /&gt;
  bar:Biden color:pres from:78.17  till:  79.17&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/timeline&amp;gt; &amp;lt;noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Graphical timeline templates|US Presidents]]&lt;br /&gt;
[[Category:President of the United States templates|{{PAGENAME}}]]&lt;br /&gt;
[[Category:United States presidency timelines|τ]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Vorlage:Short_description/lowercasecheck&amp;diff=1507</id>
		<title>Vorlage:Short description/lowercasecheck</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Vorlage:Short_description/lowercasecheck&amp;diff=1507"/>
		<updated>2022-08-12T16:59:07Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#ifeq:&amp;lt;!--test first character for lower-case letter--&amp;gt;{{#invoke:string|find|1={{{1|}}}|2=^%l|plain=false}}|1&lt;br /&gt;
|&amp;lt;!-- first character is a lower case letter; test against whitelist&lt;br /&gt;
--&amp;gt;{{#switch: {{First word|{{{1|}}}}}&amp;lt;!--begin whitelist--&amp;gt;&lt;br /&gt;
|c. &amp;lt;!--for circa--&amp;gt;&lt;br /&gt;
|gTLD&lt;br /&gt;
|iMac&lt;br /&gt;
|iOS&lt;br /&gt;
|iOS,&lt;br /&gt;
|iPad&lt;br /&gt;
|iPhone&lt;br /&gt;
|iTunes&lt;br /&gt;
|macOS&lt;br /&gt;
|none&lt;br /&gt;
|pH&lt;br /&gt;
|pH-dependent=&amp;lt;!-- end whitelist; short description starts with an allowed lower-case string; whitelist matched; do nothing --&amp;gt; &lt;br /&gt;
|#default=&amp;lt;!-- apply category to track lower-case short descriptions --&amp;gt;{{main other|[[Category:Pages with lower-case short description|{{trim|{{{1|}}}}}]]}}{{Testcases other|{{red|CATEGORY APPLIED}}}}&amp;lt;!-- end whitelist test --&amp;gt;}}&lt;br /&gt;
|&amp;lt;!-- short description does not start with lower-case letter; do nothing; end lower-case test --&amp;gt;&lt;br /&gt;
}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Vorlage:Short_description&amp;diff=1505</id>
		<title>Vorlage:Short description</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Vorlage:Short_description&amp;diff=1505"/>
		<updated>2022-08-12T16:59:07Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#ifeq:{{lc:{{{1|}}}}}|none|&amp;lt;nowiki /&amp;gt;&amp;lt;!--Prevents whitespace issues when used with adjacent newlines--&amp;gt;|&amp;lt;div class=&amp;quot;shortdescription nomobile noexcerpt noprint searchaux&amp;quot; style=&amp;quot;display:none&amp;quot;&amp;gt;{{{1|}}}{{SHORTDESC:{{{1|}}}|{{{2|}}}}}&amp;lt;/div&amp;gt;}}&amp;lt;includeonly&amp;gt;[[Category:{{{pagetype|{{pagetype |defaultns = extended |plural=y}}}}} with short description{{#ifeq:{{{pagetype}}}|Disambiguation pages|s}}]]&amp;lt;/includeonly&amp;gt;&amp;lt;!-- Start tracking&lt;br /&gt;
--&amp;gt;{{#invoke:Check for unknown parameters|check|unknown={{Main other|[[Category:Pages using short description with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Short description]] with unknown parameter &amp;quot;_VALUE_&amp;quot;|ignoreblank=y| 1 | 2 | pagetype | bot |plural }}&amp;lt;!--&lt;br /&gt;
--&amp;gt;{{#ifexpr: {{#invoke:String|len|{{{1|}}}}}&amp;gt;100 | [[Category:{{{pagetype|{{pagetype |defaultns = extended |plural=y}}}}} with long short description]]}}&amp;lt;!--&lt;br /&gt;
--&amp;gt;{{Short description/lowercasecheck|{{{1|}}}}}&amp;lt;!--&lt;br /&gt;
--&amp;gt;{{Main other |{{SDcat |sd={{{1|}}} }} }}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{Documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Vorlage:Reflist&amp;diff=1503</id>
		<title>Vorlage:Reflist</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Vorlage:Reflist&amp;diff=1503"/>
		<updated>2022-08-12T16:59:06Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;templatestyles src=&amp;quot;Reflist/styles.css&amp;quot; /&amp;gt;&amp;lt;div class=&amp;quot;reflist &amp;lt;!--&lt;br /&gt;
--&amp;gt;{{#if:{{{1|}}}{{{colwidth|}}}|reflist-columns references-column-width}} &amp;lt;!--&lt;br /&gt;
--&amp;gt;{{#switch:{{{liststyle|{{{group|}}}}}}|upper-alpha|upper-roman|lower-alpha|lower-greek|lower-roman=reflist-{{{liststyle|{{{group}}}}}}}} &amp;lt;!--&lt;br /&gt;
--&amp;gt;{{#if:{{{1|}}}|{{#iferror:{{#ifexpr: {{{1|1}}} &amp;gt; 1 }}||{{#switch:{{{1|}}}|1=|2=reflist-columns-2|#default=reflist-columns-3}} }}}}&amp;quot; &amp;lt;!-- end class&lt;br /&gt;
--&amp;gt;{{#if: {{{1|}}}&amp;lt;!-- start style --&amp;gt;&lt;br /&gt;
    | {{#iferror: {{#ifexpr: {{{1|1}}} &amp;gt; 1 }} |style=&amp;quot;column-width: {{{1}}};&amp;quot;}}&lt;br /&gt;
    | {{#if: {{{colwidth|}}}|style=&amp;quot;column-width: {{{colwidth}}};&amp;quot;}}&lt;br /&gt;
    }}&amp;gt;&lt;br /&gt;
{{#tag:references|{{{refs|}}}|group={{{group|}}}|responsive={{#if:{{{1|}}}{{{colwidth|}}}|0|1}}}}&amp;lt;/div&amp;gt;{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using reflist with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Reflist]] with unknown parameter &amp;quot;_VALUE_&amp;quot;|ignoreblank=y| 1 | colwidth | group | liststyle | refs }}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{Documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Vorlage:Ns_has_subpages&amp;diff=1501</id>
		<title>Vorlage:Ns has subpages</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Vorlage:Ns_has_subpages&amp;diff=1501"/>
		<updated>2022-08-12T16:58:59Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{&amp;lt;includeonly&amp;gt;safesubst:&amp;lt;/includeonly&amp;gt;#invoke:Ns has subpages|main}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;!-- Categories go on the /doc subpage and interwikis go on Wikidata. --&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Vorlage:Notelist&amp;diff=1499</id>
		<title>Vorlage:Notelist</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Vorlage:Notelist&amp;diff=1499"/>
		<updated>2022-08-12T16:58:58Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{reflist|{{{1|{{{colwidth|}}}}}}|refs={{{refs|{{{notes|}}}}}}|group={{#switch: {{{group|}}}&lt;br /&gt;
    | note&lt;br /&gt;
    | upper-alpha&lt;br /&gt;
    | upper-roman&lt;br /&gt;
    | lower-alpha&lt;br /&gt;
    | lower-greek&lt;br /&gt;
    | lower-roman = {{{group|}}}&lt;br /&gt;
    | #default = lower-alpha&lt;br /&gt;
   }}}}{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using notelist with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Notelist]] with unknown parameter &amp;quot;_VALUE_&amp;quot;|ignoreblank=y| 1 | colwidth | group | notes | refs }}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Vorlage:Main_other&amp;diff=1497</id>
		<title>Vorlage:Main other</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Vorlage:Main_other&amp;diff=1497"/>
		<updated>2022-08-12T16:58:57Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#switch:&lt;br /&gt;
  &amp;lt;!--If no or empty &amp;quot;demospace&amp;quot; parameter then detect namespace--&amp;gt;&lt;br /&gt;
  {{#if:{{{demospace|}}} &lt;br /&gt;
  | {{lc: {{{demospace}}} }}    &amp;lt;!--Use lower case &amp;quot;demospace&amp;quot;--&amp;gt;&lt;br /&gt;
  | {{#ifeq:{{NAMESPACE}}|{{ns:0}}&lt;br /&gt;
    | main&lt;br /&gt;
    | other&lt;br /&gt;
    }} &lt;br /&gt;
  }}&lt;br /&gt;
| main     = {{{1|}}}&lt;br /&gt;
| other&lt;br /&gt;
| #default = {{{2|}}}&lt;br /&gt;
}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;!-- Add categories to the /doc subpage; interwikis go to Wikidata, thank you! --&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Vorlage:Lists_of_US_presidents_and_vice_presidents&amp;diff=1495</id>
		<title>Vorlage:Lists of US presidents and vice presidents</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Vorlage:Lists_of_US_presidents_and_vice_presidents&amp;diff=1495"/>
		<updated>2022-08-12T16:58:57Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Navbox&lt;br /&gt;
|name  = Lists of US presidents and vice presidents&lt;br /&gt;
|title = Lists related to the [[President of the United States|presidents]] and [[Vice President of the United States|vice presidents of the United States]]&lt;br /&gt;
|state = {{{state|autocollapse}}}&lt;br /&gt;
|bodyclass = hlist&lt;br /&gt;
|above = &lt;br /&gt;
* [[List of presidents of the United States|List of presidents]]&lt;br /&gt;
* [[List of vice presidents of the United States|List of vice presidents]]&lt;br /&gt;
&lt;br /&gt;
|group1 = Presidents&lt;br /&gt;
|list1 = &lt;br /&gt;
* [[List of presidents of the United States by age|Age]]&lt;br /&gt;
* [[List of autobiographies by presidents of the United States|Autobiographies]]&lt;br /&gt;
* [[List of burial places of presidents and vice presidents of the United States#Presidential burial places|Burial places]]&lt;br /&gt;
* [[List of presidents of the United States by date of death|Death]]&lt;br /&gt;
* [[Historical rankings of presidents of the United States|Historical rankings]]&lt;br /&gt;
* [[List of official vehicles of the president of the United States|Official vehicles]]&lt;br /&gt;
* [[Portraits of presidents of the United States|Portraits]]&lt;br /&gt;
* [[List of presidents of the United States by time in office|Time in office]]&lt;br /&gt;
&lt;br /&gt;
|group2 = Professional&amp;lt;br /&amp;gt;careers&lt;br /&gt;
|list2 = &lt;br /&gt;
* [[United States presidential approval rating|Approval rating]]&lt;br /&gt;
* [[List of United States presidential assassination attempts and plots|Assassination attempts and plots]]&lt;br /&gt;
* [[List of U.S. presidential campaign slogans|Campaign slogans]]&lt;br /&gt;
* [[Divided government in the United States|Control of Congress]]&lt;br /&gt;
* [[United States presidential doctrines|Doctrines]]&lt;br /&gt;
* [[United States presidential inauguration#List of inauguration ceremonies|Inaugurations]]&lt;br /&gt;
* [[List of international trips made by presidents of the United States|International trips]]&lt;br /&gt;
* [[List of presidents of the United States by judicial appointments|Judicial appointments]]&lt;br /&gt;
* [[Presidential library#List of presidential libraries|Libraries]]&lt;br /&gt;
* [[List of presidents of the United States by military rank|Military rank]]&lt;br /&gt;
* [[List of presidents of the United States by military service|Military service]]&lt;br /&gt;
* [[List of presidents of the United States by other offices held|Other offices held]]&lt;br /&gt;
* [[List of people pardoned or granted clemency by the president of the United States|Pardons]]&lt;br /&gt;
*[[List of former United States presidents who ran for office|Post-presidency campaigns]]&lt;br /&gt;
* [[List of presidents of the United States by previous experience|Previous experience]]&lt;br /&gt;
* [[List of United States presidential vetoes|Vetoes]]&lt;br /&gt;
&lt;br /&gt;
|group3 = Personal life&lt;br /&gt;
|list3 = &lt;br /&gt;
* [[Ancestral background of presidents of the United States|Ancestry]]&lt;br /&gt;
* [[List of personal coats of arms of presidents of the United States|Coats of arms]]&lt;br /&gt;
* [[List of presidents of the United States who died in office|Deaths in office]]&lt;br /&gt;
* [[List of presidents of the United States by education|Education]]&lt;br /&gt;
* [[List of presidents of the United States with facial hair|Facial hair]]&lt;br /&gt;
* [[List of United States presidential firsts|Firsts]]&lt;br /&gt;
* [[List of presidents of the United States who were Freemasons|Freemasons]]&lt;br /&gt;
* [[List of presidents of the United States by home state|Home state]]&lt;br /&gt;
* [[List of left-handed United States presidents|Left-handed]]&lt;br /&gt;
* [[List of multilingual presidents of the United States|Multilingualism]]&lt;br /&gt;
* [[List of presidents of the United States by net worth|Net worth]]&lt;br /&gt;
* [[List of nicknames of presidents of the United States|Nicknames]]&lt;br /&gt;
* [[United States presidential pets|Pets]]&lt;br /&gt;
* [[Religious affiliations of presidents of the United States|Religious affiliation]]&lt;br /&gt;
* [[List of residences of presidents of the United States|Residences]]&lt;br /&gt;
* [[List of presidents of the United States who owned slaves|Slave owners]]&lt;br /&gt;
&lt;br /&gt;
|group4 = Vice presidents&lt;br /&gt;
|list4 = &lt;br /&gt;
* [[List of vice presidents of the United States by age|Age]]&lt;br /&gt;
* [[List of burial places of presidents and vice presidents of the United States#Vice presidential burial places|Burial places]]&lt;br /&gt;
* [[List of personal coats of arms of vice presidents of the United States|Coats of arms]]&lt;br /&gt;
* [[List of vice presidents of the United States by education|Education]]&lt;br /&gt;
* [[List of vice presidents of the United States by home state|Home state]]&lt;br /&gt;
* [[List of vice presidents of the United States by other offices held|Other offices held]]&lt;br /&gt;
* [[List of United States vice presidents who ran for president|Ran for president]]&lt;br /&gt;
* [[Religious affiliations of vice presidents of the United States|Religious affiliation]]&lt;br /&gt;
* [[List of vice presidents of the United States who owned slaves|Slave owners]]&lt;br /&gt;
* [[List of tie-breaking votes cast by the vice president of the United States|Tie-breaking votes]]&lt;br /&gt;
* [[List of vice presidents of the United States by time in office|Time in office]]&lt;br /&gt;
&lt;br /&gt;
|group5 = Succession&lt;br /&gt;
|list5 = &lt;br /&gt;
* [[Acting president of the United States|Acting president]]&lt;br /&gt;
* [[Designated survivor]]&lt;br /&gt;
* [[United States presidential line of succession|Line of succession]]&lt;br /&gt;
&lt;br /&gt;
|group6 = [[United States presidential election|Elections]]&lt;br /&gt;
|list6 = &lt;br /&gt;
* [[List of United States presidential elections by Electoral College margin|Electoral College margin]]&lt;br /&gt;
* [[List of United States presidential elections by popular vote margin|Popular vote margin]]&lt;br /&gt;
* [[List of United States presidential elections in which the winner lost the popular vote|Winner lost popular vote]]&lt;br /&gt;
&lt;br /&gt;
|group7 = [[List of United States presidential candidates|Candidates]]&lt;br /&gt;
|list7 = {{Navbox|subgroup&lt;br /&gt;
|group1 = [[List of political parties in the United States|Political affiliation]]&lt;br /&gt;
|list1 =&lt;br /&gt;
* [[List of United States Democratic Party presidential tickets|Democratic]]&lt;br /&gt;
* [[List of Democratic-Republican Party presidential tickets|Democratic-Republican]]&lt;br /&gt;
* [[List of Federalist Party presidential tickets|Federalist]]&lt;br /&gt;
* [[List of Green Party of the United States presidential tickets|Green]]&lt;br /&gt;
* [[List of United States Libertarian Party presidential tickets|Libertarian]]&lt;br /&gt;
* [[List of United States National Republican and Whig Party presidential tickets|National Republican{{\}}Whig]]&lt;br /&gt;
* [[List of United States Republican Party presidential tickets|Republican]]&lt;br /&gt;
* [[List of United States major third party and independent presidential tickets|Third party{{\}}Independent]]&lt;br /&gt;
&lt;br /&gt;
|group2 = Distinctions&lt;br /&gt;
|list2 =&lt;br /&gt;
* [[List of African-American United States presidential and vice presidential candidates|African American]]&lt;br /&gt;
* [[List of female United States presidential and vice-presidential candidates|Female]]&lt;br /&gt;
* [[List of United States presidential candidate firsts|Firsts]]&lt;br /&gt;
* [[Heights of presidents and presidential candidates of the United States|Height]]&lt;br /&gt;
* [[List of major-party United States presidential candidates who lost their home state|Lost their home state]]&lt;br /&gt;
* [[List of United States presidential candidates by number of votes received|Number of votes received]]&lt;br /&gt;
* [[List of people who received an electoral vote in the United States Electoral College|Received at least one electoral vote]]&lt;br /&gt;
* [[List of unsuccessful major party candidates for President of the United States|Unsuccessful major party presidential candidates]]&lt;br /&gt;
* [[List of unsuccessful major party candidates for Vice President of the United States|Unsuccessful major party vice presidential candidates]]&lt;br /&gt;
}}&lt;br /&gt;
|group8 = Families&lt;br /&gt;
|list8 = &lt;br /&gt;
* [[First family of the United States|First families]]&lt;br /&gt;
* [[List of first ladies of the United States|First ladies]]&lt;br /&gt;
* [[List of children of presidents of the United States|Presidential children]]&lt;br /&gt;
* [[Second Ladies and Gentlemen of the United States|Second ladies and gentlemen]]&lt;br /&gt;
* [[List of children of vice presidents of the United States|Vice presidential children]]&lt;br /&gt;
&lt;br /&gt;
|group9 = Namesakes&amp;lt;br /&amp;gt;and honors&lt;br /&gt;
|list9 =&lt;br /&gt;
* [[List of presidents of the United States on currency|Currency appearances]]&lt;br /&gt;
* [[List of educational institutions named after presidents of the United States|Educational institution names]]&lt;br /&gt;
* [[Presidential memorials in the United States|Memorials]]&lt;br /&gt;
* [[List of sculptures of presidents of the United States|Sculptures]]&lt;br /&gt;
* [[List of U.S. counties named after presidents of the United States|U.S. county names]]&lt;br /&gt;
* [[Presidents of the United States on U.S. postage stamps|U.S. postage stamp appearances]]&lt;br /&gt;
* [[United States Senate Vice Presidential Bust Collection|U.S. Senate vice presidential bust collection]]&lt;br /&gt;
&lt;br /&gt;
|group10 = In media&lt;br /&gt;
|list10 = &lt;br /&gt;
* [[List of actors who played the president of the United States|Portrayals]]&lt;br /&gt;
* [[Lists of fictional presidents of the United States|Fictional depictions]]&lt;br /&gt;
** [[United States presidential line of succession in fiction|Line of succession]]&lt;br /&gt;
&lt;br /&gt;
|below = &lt;br /&gt;
* {{icon|Portal}} [[Portal:Biography|Biography portal]]&lt;br /&gt;
* {{icon|Portal}} [[Portal:Politics|Politics portal]]&lt;br /&gt;
* {{icon|Portal}} [[Portal:United States|United States portal]]&lt;br /&gt;
}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{Documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Vorlage:Lifespan_of_each_United_States_president&amp;diff=1493</id>
		<title>Vorlage:Lifespan of each United States president</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Vorlage:Lifespan_of_each_United_States_president&amp;diff=1493"/>
		<updated>2022-08-12T16:58:55Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div style=&amp;quot;overflow:auto&amp;quot;&amp;gt;&lt;br /&gt;
{{#tag:timeline|&lt;br /&gt;
Define $width = 1200 # 4 pixels per year ($end - $start) × 4&lt;br /&gt;
Define $warning = 1080 # $width - 120&lt;br /&gt;
Define $height = 1225 # 43 × 25 + 150&lt;br /&gt;
Define $footnote = 800 # $width  - 400&lt;br /&gt;
&lt;br /&gt;
Define $start = 1730&lt;br /&gt;
Define $end = 2025&lt;br /&gt;
Define $now = {{CURRENTYEAR}}&lt;br /&gt;
&lt;br /&gt;
ImageSize  = width:$width height:$height&lt;br /&gt;
PlotArea   = right:10 left:1 bottom:80 top:60&lt;br /&gt;
Period     = from:$start till:$end&lt;br /&gt;
TimeAxis   = orientation:horizontal&lt;br /&gt;
Legend = orientation:vertical position:bottom columns:1&lt;br /&gt;
&lt;br /&gt;
Colors =&lt;br /&gt;
     id:bg              value:white&lt;br /&gt;
     id:lightline       value:rgb(0.8, 0.8, 0.8)&lt;br /&gt;
     id:lighttext       value:rgb(0.5, 0.5, 0.5)&lt;br /&gt;
     id:LIFESPAN        value:rgb(0.88, 0.90, 0.70) Legend: Lifespan&lt;br /&gt;
     id:POTUS_NONP      value:rgb(0.7, 0.7, 0.7) Legend: Nonpartisan&lt;br /&gt;
     id:POTUS_FED       value:rgb(0.85, 0.52, 0.38) Legend: Federalist&lt;br /&gt;
     id:POTUS_DEMREP    value:rgb(0, 0.5, 0) Legend: Democratic-Republican&lt;br /&gt;
     id:POTUS_NATREP    value:rgb(0.99, 0.9, 0.69) Legend: National_Republican&lt;br /&gt;
     id:POTUS_DEM       value:rgb(0.2, 0.2, 1) Legend: Democrat&lt;br /&gt;
     id:POTUS_WHIG      value:rgb(0.84, 0.74, 0.34) Legend: Whig&lt;br /&gt;
     id:POTUS_REP       value:rgb(1, 0.2, 0.2) Legend: Republican&lt;br /&gt;
     id:POTUS_UNION     value:rgb(0.7, 0.13, 0.13) Legend: National_Unionist&lt;br /&gt;
     id:NAME            value:rgb(0.15, 0.13, 0.05)&lt;br /&gt;
     id:TODAY           value:green&lt;br /&gt;
&lt;br /&gt;
BackgroundColors = canvas:bg&lt;br /&gt;
ScaleMinor = gridcolor:lightline unit:year increment:1 start:$start&lt;br /&gt;
ScaleMajor = gridcolor:lighttext unit:year increment:10 start:1730&lt;br /&gt;
&lt;br /&gt;
Define $dy = -5 # shift text to button side of bar&lt;br /&gt;
&lt;br /&gt;
LineData=&lt;br /&gt;
   at:$now color:TODAY width:0.1&lt;br /&gt;
&lt;br /&gt;
PlotData=&lt;br /&gt;
  bar:1 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1732 till:1789 shift:(-0,$dy) textcolor:NAME text:[[George Washington]]&lt;br /&gt;
    color:POTUS_NONP&lt;br /&gt;
    from:1789 till:1797&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1797 till:1799&lt;br /&gt;
&lt;br /&gt;
  bar:2 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1735 till:1797 shift:(-0,$dy) textcolor:NAME text:[[John Adams]]&lt;br /&gt;
    color:POTUS_FED&lt;br /&gt;
    from:1797 till:1801&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1801 till:1826&lt;br /&gt;
&lt;br /&gt;
  bar:3 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1743 till:1801 shift:(-0,$dy) textcolor:NAME text:[[Thomas Jefferson]]&lt;br /&gt;
    color:POTUS_DEMREP&lt;br /&gt;
    from:1801 till:1809&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1809 till:1826&lt;br /&gt;
&lt;br /&gt;
  bar:4 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1751 till:1809 shift:(-0,$dy) textcolor:NAME text:[[James Madison]]&lt;br /&gt;
    color:POTUS_DEMREP&lt;br /&gt;
    from:1809 till:1817&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1817 till:1836&lt;br /&gt;
&lt;br /&gt;
  bar:5 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1758 till:1817 shift:(-0,$dy) textcolor:NAME text:[[James Monroe]]&lt;br /&gt;
    color:POTUS_DEMREP&lt;br /&gt;
    from:1817 till:1825&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1825 till:1831&lt;br /&gt;
&lt;br /&gt;
  bar:6 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1767 till:1825 shift:(-0,$dy) textcolor:NAME text:[[John Quincy Adams]]&lt;br /&gt;
    color:POTUS_DEMREP&lt;br /&gt;
    from:1825 till:1825.4&lt;br /&gt;
    color:POTUS_NATREP&lt;br /&gt;
    from:1825.4 till:1829&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1829 till:1848&lt;br /&gt;
&lt;br /&gt;
  bar:7 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1767 till:1829 shift:(-0,$dy) textcolor:NAME text:[[Andrew Jackson]]&lt;br /&gt;
    color:POTUS_DEM&lt;br /&gt;
    from:1829 till:1837&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1837 till:1845&lt;br /&gt;
&lt;br /&gt;
  bar:8 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1782 till:1837 shift:(-0,$dy) textcolor:NAME text:[[Martin Van Buren]]&lt;br /&gt;
    color:POTUS_DEM&lt;br /&gt;
    from:1837 till:1841&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1841 till:1862&lt;br /&gt;
&lt;br /&gt;
  bar:9 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1773 till:1841 shift:(-0,$dy) textcolor:NAME text:[[William Henry Harrison]]&lt;br /&gt;
    color:POTUS_WHIG&lt;br /&gt;
    from:1841 till:1841.4&lt;br /&gt;
&lt;br /&gt;
  bar:10 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1790 till:1841.4 shift:(-0,$dy) textcolor:NAME text:[[John Tyler]]&lt;br /&gt;
    color:POTUS_WHIG&lt;br /&gt;
    from:1841.4 till:1841.8&lt;br /&gt;
    color:POTUS_NONP&lt;br /&gt;
    from:1841.8 till:1845&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1845 till:1862&lt;br /&gt;
&lt;br /&gt;
  bar:11 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1795 till:1845 shift:(-0,$dy) textcolor:NAME text:[[James K. Polk]]&lt;br /&gt;
    color:POTUS_DEM&lt;br /&gt;
    from:1845 till:1849&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1849 till:1849&lt;br /&gt;
&lt;br /&gt;
  bar:12 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1784 till:1849 shift:(-0,$dy) textcolor:NAME text:[[Zachary Taylor]]&lt;br /&gt;
    color:POTUS_WHIG&lt;br /&gt;
    from:1849 till:1850&lt;br /&gt;
&lt;br /&gt;
  bar:13 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1800 till:1850 shift:(-0,$dy) textcolor:NAME text:[[Millard Fillmore]]&lt;br /&gt;
    color:POTUS_WHIG&lt;br /&gt;
    from:1850 till:1853&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1853 till:1874&lt;br /&gt;
&lt;br /&gt;
  bar:14 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1804 till:1853 shift:(-0,$dy) textcolor:NAME text:[[Franklin Pierce]]&lt;br /&gt;
    color:POTUS_DEM&lt;br /&gt;
    from:1853 till:1857&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1857 till:1869&lt;br /&gt;
&lt;br /&gt;
  bar:15 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1791 till:1857 shift:(-0,$dy) textcolor:NAME text:[[James Buchanan]]&lt;br /&gt;
    color:POTUS_DEM&lt;br /&gt;
    from:1857 till:1861&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1861 till:1868&lt;br /&gt;
&lt;br /&gt;
  bar:16 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1809 till:1861 shift:(-0,$dy) textcolor:NAME text:[[Abraham Lincoln]]&lt;br /&gt;
    color:POTUS_REP&lt;br /&gt;
    from:1861 till:1864&lt;br /&gt;
    color:POTUS_UNION&lt;br /&gt;
    from:1864 till:1865&lt;br /&gt;
&lt;br /&gt;
  bar:17 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1808 till:1865 shift:(-0,$dy) textcolor:NAME text:[[Andrew Johnson]]&lt;br /&gt;
    color:POTUS_UNION&lt;br /&gt;
    from:1865 till:1868&lt;br /&gt;
    color:POTUS_DEM&lt;br /&gt;
    from:1868 till:1869&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1869 till:1875&lt;br /&gt;
&lt;br /&gt;
  bar:18 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1822 till:1869 shift:(-0,$dy) textcolor:NAME text:[[Ulysses S. Grant]]&lt;br /&gt;
    color:POTUS_REP&lt;br /&gt;
    from:1869 till:1877&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1877 till:1885&lt;br /&gt;
&lt;br /&gt;
  bar:19 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1822 till:1877 shift:(-0,$dy) textcolor:NAME text:[[Rutherford B. Hayes]]&lt;br /&gt;
    color:POTUS_REP&lt;br /&gt;
    from:1877 till:1881&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1881 till:1893&lt;br /&gt;
&lt;br /&gt;
  bar:20 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1831 till:1881 shift:(-0,$dy) textcolor:NAME text:[[James A. Garfield]]&lt;br /&gt;
    color:POTUS_REP&lt;br /&gt;
    from:1881 till:1881.4&lt;br /&gt;
&lt;br /&gt;
  bar:21 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1830 till:1881.4 shift:(-0,$dy) textcolor:NAME text:[[Chester A. Arthur]]&lt;br /&gt;
    color:POTUS_REP&lt;br /&gt;
    from:1881.4 till:1885&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1885 till:1886&lt;br /&gt;
&lt;br /&gt;
 bar:22 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1837 till:1885 shift:(-0,$dy) textcolor:NAME text:[[Grover Cleveland]]&lt;br /&gt;
    color:POTUS_DEM&lt;br /&gt;
    from:1885 till:1889&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1889 till:1893&lt;br /&gt;
    color:POTUS_DEM&lt;br /&gt;
    from:1893 till:1897&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1897 till:1908&lt;br /&gt;
&lt;br /&gt;
  bar:23 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1833 till:1889 shift:(-0,$dy) textcolor:NAME text:[[Benjamin Harrison]]&lt;br /&gt;
    color:POTUS_REP&lt;br /&gt;
    from:1889 till:1893&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1893 till:1901&lt;br /&gt;
&lt;br /&gt;
  bar:24 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1843 till:1897 shift:(-0,$dy) textcolor:NAME text:[[William McKinley]]&lt;br /&gt;
    color:POTUS_REP&lt;br /&gt;
    from:1897 till:1901&lt;br /&gt;
&lt;br /&gt;
  bar:25 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1858 till:1901 shift:(-0,$dy) textcolor:NAME text:[[Theodore Roosevelt]]&lt;br /&gt;
    color:POTUS_REP&lt;br /&gt;
    from:1901 till:1909&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1909 till:1919&lt;br /&gt;
&lt;br /&gt;
  bar:26 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1857 till:1909 shift:(-0,$dy) textcolor:NAME text:[[William Howard Taft]]&lt;br /&gt;
    color:POTUS_REP&lt;br /&gt;
    from:1909 till:1913&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1913 till:1930&lt;br /&gt;
&lt;br /&gt;
  bar:27 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1856 till:1913 shift:(-0,$dy) textcolor:NAME text:[[Woodrow Wilson]]&lt;br /&gt;
    color:POTUS_DEM&lt;br /&gt;
    from:1913 till:1921&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1921 till:1924&lt;br /&gt;
&lt;br /&gt;
  bar:28 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1865 till:1921 shift:(-0,$dy) textcolor:NAME text:[[Warren G. Harding]]&lt;br /&gt;
    color:POTUS_REP&lt;br /&gt;
    from:1921 till:1923&lt;br /&gt;
&lt;br /&gt;
  bar:29 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1872 till:1923 shift:(-0,$dy) textcolor:NAME text:[[Calvin Coolidge]]&lt;br /&gt;
    color:POTUS_REP&lt;br /&gt;
    from:1923 till:1929&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1929 till:1933&lt;br /&gt;
&lt;br /&gt;
  bar:30 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1874 till:1929 shift:(-0,$dy) textcolor:NAME text:[[Herbert Hoover]]&lt;br /&gt;
    color:POTUS_REP&lt;br /&gt;
    from:1929 till:1933&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1933 till:1964&lt;br /&gt;
&lt;br /&gt;
  bar:31 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1882 till:1933 shift:(-0,$dy) textcolor:NAME text:[[Franklin D. Roosevelt]]&lt;br /&gt;
    color:POTUS_DEM&lt;br /&gt;
    from:1933 till:1945&lt;br /&gt;
&lt;br /&gt;
  bar:32 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1884 till:1945 shift:(-0,$dy) textcolor:NAME text:[[Harry S. Truman]]&lt;br /&gt;
    color:POTUS_DEM&lt;br /&gt;
    from:1945 till:1953&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1953 till:1972&lt;br /&gt;
&lt;br /&gt;
  bar:33 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1890 till:1953 shift:(-0,$dy) textcolor:NAME text:[[Dwight D. Eisenhower]]&lt;br /&gt;
    color:POTUS_REP&lt;br /&gt;
    from:1953 till:1961&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1961 till:1969&lt;br /&gt;
&lt;br /&gt;
  bar:34 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1917 till:1961 shift:(-0,$dy) textcolor:NAME text:[[John F. Kennedy]]&lt;br /&gt;
    color:POTUS_DEM&lt;br /&gt;
    from:1961 till:1963&lt;br /&gt;
&lt;br /&gt;
  bar:35 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1908 till:1963 shift:(-0,$dy) textcolor:NAME text:[[Lyndon B. Johnson]]&lt;br /&gt;
    color:POTUS_DEM&lt;br /&gt;
    from:1963 till:1969&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1969 till:1973&lt;br /&gt;
&lt;br /&gt;
  bar:36 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1913 till:1969 shift:(-0,$dy) textcolor:NAME text:[[Richard Nixon]]&lt;br /&gt;
    color:POTUS_REP&lt;br /&gt;
    from:1969 till:1974&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1974 till:1994&lt;br /&gt;
&lt;br /&gt;
  bar:37 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1913 till:1974 shift:(-0,$dy) textcolor:NAME text:[[Gerald Ford]]&lt;br /&gt;
    color:POTUS_REP&lt;br /&gt;
    from:1974 till:1977&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1977 till:2006&lt;br /&gt;
&lt;br /&gt;
  bar:38 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1924 till:1977 shift:(-0,$dy) textcolor:NAME text:[[Jimmy Carter]]&lt;br /&gt;
    color:POTUS_DEM&lt;br /&gt;
    from:1977 till:1981&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1981 till:$now&lt;br /&gt;
&lt;br /&gt;
  bar:39 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1911 till:1981 shift:(-0,$dy) textcolor:NAME text:[[Ronald Reagan]]&lt;br /&gt;
    color:POTUS_REP&lt;br /&gt;
    from:1981 till:1989&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1989 till:2004&lt;br /&gt;
&lt;br /&gt;
  bar:40 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1924 till:1989 shift:(-0,$dy) textcolor:NAME text:[[George H. W. Bush]]&lt;br /&gt;
    color:POTUS_REP&lt;br /&gt;
    from:1989 till:1993&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:1993 till:2018&lt;br /&gt;
&lt;br /&gt;
  bar:41 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1946 till:1993 shift:(-0,$dy) textcolor:NAME text:[[Bill Clinton]]&lt;br /&gt;
    color:POTUS_DEM&lt;br /&gt;
    from:1993 till:2001&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:2001 till:$now&lt;br /&gt;
&lt;br /&gt;
  bar:42 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1946 till:2001 shift:(-0,$dy) textcolor:NAME text:[[George W. Bush]]&lt;br /&gt;
    color:POTUS_REP&lt;br /&gt;
    from:2001 till:2009&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:2009 till:$now&lt;br /&gt;
&lt;br /&gt;
  bar:43 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1961 till:2009 shift:(-0,$dy) textcolor:NAME text:[[Barack Obama]]&lt;br /&gt;
    color:POTUS_DEM&lt;br /&gt;
    from:2009 till:2017&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:2017 till:$now&lt;br /&gt;
&lt;br /&gt;
  bar:44 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1946 till:2017 shift:(-0,$dy) textcolor:NAME text:[[Donald Trump]]&lt;br /&gt;
    color:POTUS_REP&lt;br /&gt;
    from:2017 till:2021&lt;br /&gt;
    color:LIFESPAN&lt;br /&gt;
    from:2021 till:$now&lt;br /&gt;
&lt;br /&gt;
  bar:45 width:18&lt;br /&gt;
    color:LIFESPAN align:center fontsize:M&lt;br /&gt;
    from:1942 till:2021 shift:(-0,$dy) textcolor:NAME text:[[Joe Biden]]&lt;br /&gt;
    color:POTUS_DEM&lt;br /&gt;
    from:2021 till:$now&lt;br /&gt;
&lt;br /&gt;
TextData =&lt;br /&gt;
  fontsize:M&lt;br /&gt;
  textcolor:green&lt;br /&gt;
  pos:($warning,30)&lt;br /&gt;
  text:Updated 1/2022&lt;br /&gt;
&lt;br /&gt;
TextData =&lt;br /&gt;
   pos:(480,$height)&lt;br /&gt;
   fontsize:L&lt;br /&gt;
   textcolor:black&lt;br /&gt;
   text:&amp;quot;Lifespan of each United States president&amp;quot;&lt;br /&gt;
}}&amp;lt;/div&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Graphical timeline templates|US Presidents]]&lt;br /&gt;
[[Category:President of the United States templates|{{PAGENAME}}]]&lt;br /&gt;
[[Category:United States presidency timelines|τ]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Vorlage:First_word&amp;diff=1491</id>
		<title>Vorlage:First word</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Vorlage:First_word&amp;diff=1491"/>
		<updated>2022-08-12T16:58:55Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{&amp;lt;includeonly&amp;gt;safesubst:&amp;lt;/includeonly&amp;gt;#invoke:String|match|s={{{1}}}|^[^{{{sep|%s}}}]*}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Vorlage:FULLROOTPAGENAME&amp;diff=1489</id>
		<title>Vorlage:FULLROOTPAGENAME</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Vorlage:FULLROOTPAGENAME&amp;diff=1489"/>
		<updated>2022-08-12T16:58:55Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ safesubst:&amp;lt;noinclude/&amp;gt;#if: {{ safesubst:&amp;lt;noinclude/&amp;gt;Ns has subpages | {{ safesubst:&amp;lt;noinclude/&amp;gt;#if:{{{1|}}}|{{ safesubst:&amp;lt;noinclude/&amp;gt;NAMESPACE:{{{1}}}}}|{{ safesubst:&amp;lt;noinclude/&amp;gt;NAMESPACE}}}} }} &lt;br /&gt;
  | {{ safesubst:&amp;lt;noinclude/&amp;gt;#titleparts:{{ safesubst:&amp;lt;noinclude/&amp;gt;#if:{{{1|}}}|{{{1}}}|{{ safesubst:&amp;lt;noinclude/&amp;gt;FULLPAGENAME}}}}|1}}&lt;br /&gt;
  | {{ safesubst:&amp;lt;noinclude/&amp;gt;#if:{{{1|}}}|{{{1}}}|{{ safesubst:&amp;lt;noinclude/&amp;gt;FULLPAGENAME}}}}&lt;br /&gt;
}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Vorlage:Ayd&amp;diff=1487</id>
		<title>Vorlage:Ayd</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Vorlage:Ayd&amp;diff=1487"/>
		<updated>2022-08-12T16:58:54Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Template:Age in years and days nts]]&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Vorlage:Age_in_years_and_days_nts&amp;diff=1485</id>
		<title>Vorlage:Age in years and days nts</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Vorlage:Age_in_years_and_days_nts&amp;diff=1485"/>
		<updated>2022-08-12T16:58:54Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{{#ifeq: {{{disp|}}} | table | nowrap style=text-align:right {{!}} {{#time: j M Y | {{{1|}}} }} {{!!}} nowrap style=text-align:right {{!}} {{#if: {{{2|}}} | {{#time: j M Y | {{{2}}} }} | {{center|Living}} }} {{!!}} }}{{{{{♥|safesubst:}}}#invoke:age|age_generic|template=age_yd_nts}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;{{documentation}}&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=List_of_presidents_of_the_United_States_by_age&amp;diff=1483</id>
		<title>List of presidents of the United States by age</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=List_of_presidents_of_the_United_States_by_age&amp;diff=1483"/>
		<updated>2022-08-12T16:58:53Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Short description|none}}&lt;br /&gt;
{{Use American English|date=November 2020}}&lt;br /&gt;
{{Use mdy dates|date=November 2020}}&lt;br /&gt;
&lt;br /&gt;
This is a &#039;&#039;&#039;list of presidents of the United States by age&#039;&#039;&#039;. The first table charts the age of each [[president of the United States]] at the time of [[United States presidential inauguration|presidential inauguration]] (first inauguration if elected to multiple and consecutive terms), upon leaving office, and at the time of death. Where the president is still living, their lifespan is calculated up to {{FULLDATE}}.&lt;br /&gt;
&lt;br /&gt;
==Age of presidents==&lt;br /&gt;
[[File:Age distribution graph United States Presidents.png|thumb|300x300px|Age of presidents when assuming office]]&lt;br /&gt;
The [[median]] age at inauguration of incoming U.S. presidents is 55 years.&amp;lt;ref name=Forbes11092020&amp;gt;{{cite magazine| title=Biden Set To Become The Oldest President In U.S. History| last=McCarthy| first=Niall| date=November 9, 2020| url=https://www.forbes.com/sites/niallmccarthy/2020/11/09/biden-set-to-become-the-oldest-president-in-us-history-infographic/?sh=105580cb7be6| magazine=[[Forbes]]|access-date=January 27, 2021}}&amp;lt;/ref&amp;gt;&amp;lt;ref name=NYT01202021&amp;gt;{{cite news| last=Diaz| first=Johnny| date=January 18, 2021| orig-year=Updated January 20, 2021| title=Biden Is the Oldest President to Take the Oath| url=https://www.nytimes.com/2021/01/18/us/politics/joe-biden-age-oldest-presidents.html |archive-url=https://ghostarchive.org/archive/20211228/https://www.nytimes.com/2021/01/18/us/politics/joe-biden-age-oldest-presidents.html |archive-date=2021-12-28 |url-access=limited| newspaper=The New York Times| access-date=January 24, 2021}}{{cbignore}}&amp;lt;/ref&amp;gt; The specific years and days median is 55 years and 104.5 days, which falls midway between how old [[Warren G. Harding]] was in 1921 and [[Lyndon B. Johnson]] was in 1963.&lt;br /&gt;
&lt;br /&gt;
The youngest person to assume the presidency was [[Theodore Roosevelt]], who, at the age of 42, [[United States presidential line of succession|succeeded to the office]] after the [[assassination of William McKinley]].&amp;lt;ref name=Forbes11092020/&amp;gt; The youngest to become president by [[United States presidential election|election]] was [[John F. Kennedy]], who was [[United States presidential inauguration|inaugurated]] at age 43.&amp;lt;ref name=WHHA-JFK&amp;gt;{{cite web| title=John F. Kennedy| url=https://www.whitehousehistory.org/bios/john-kennedy| website=whitehousehistory.org| publisher=White House Historical Association| location=Washington, D.C.| access-date=January 24, 2021}}&amp;lt;/ref&amp;gt; The oldest person to assume the presidency was [[Joe Biden]], who took the [[Oath of office of the President of the United States|presidential oath of office]] 61 days after turning 78.&amp;lt;ref name=Forbes11092020/&amp;gt;&amp;lt;ref name=&amp;quot;Bloomberg01192021&amp;quot;&amp;gt;{{cite news|last1=Merrill|first1=Dave|last2=Caronello|first2=Sophie|date=January 19, 2021|title=Biden to Become Oldest President Ever at Inauguration|agency=[[Bloomberg News]]|url=https://www.bloomberg.com/news/articles/2021-01-19/biden-to-become-oldest-president-ever-at-inauguration-graphic|url-status=live|access-date=January 21, 2021|archive-url=https://web.archive.org/web/20210128211849/https://www.bloomberg.com/news/articles/2021-01-19/biden-to-become-oldest-president-ever-at-inauguration-graphic|archive-date=January 28, 2021}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Assassination of John F. Kennedy|Assassinated]] at age 46, John F. Kennedy was the youngest president at the end of his tenure, and his lifespan was the shortest of any president.&amp;lt;ref name=WHHA-JFK/&amp;gt;&amp;lt;ref&amp;gt;{{cite news|last=Merelli|first=Annalisa|date=January 20, 2021|title=What happens if Joe Biden dies in office?|website=[[Quartz (publication)|Quartz]]|url=https://qz.com/1959985/what-happens-if-joe-biden-dies-after-the-inauguration/|url-status=live|access-date=January 31, 2021|archive-url=https://web.archive.org/web/20210416170939/https://qz.com/1959985/what-happens-if-joe-biden-dies-after-the-inauguration/|archive-date=April 16, 2021}}&amp;lt;/ref&amp;gt; At age 50, Theodore Roosevelt was the youngest person to become a former president.&amp;lt;ref&amp;gt;{{cite news| last=Shank| first=Richard| title=Theodore Roosevelt remains a giant among presidents| date=January 10, 2019| newspaper=[[The Hutchinson News]]| location=Hutchinson, Kansas| url=https://www.hutchnews.com/news/20190110/theodore-roosevelt-remains-giant-among-presidents| access-date=February 8, 2021}}&amp;lt;/ref&amp;gt; The oldest president at the end of his tenure was [[Ronald Reagan]] at 77; this distinction will eventually devolve upon Joe Biden, who was older when he took office than Reagan was when he left office.&amp;lt;ref name=NYT01202021/&amp;gt;&amp;lt;ref name=Bloomberg01192021/&amp;gt; Biden was born before four of his predecessors: [[Donald Trump]], [[George W. Bush]], [[Bill Clinton]] and [[Barack Obama]].&amp;lt;ref&amp;gt;{{cite news|author=&amp;lt;!--Tampa Bay Times editorial board/no by-line.--&amp;gt;|date=November 12, 2020|title=Joe Biden is old. But how old compared to other leaders?|work=[[Tampa Bay Times]]|url=https://www.tampabay.com/opinion/2020/11/12/joe-biden-is-old-but-how-old-compared-to-other-leaders-opinion/|url-status=live|access-date=February 14, 2021|archive-url=https://web.archive.org/web/20201113080017/https://www.tampabay.com/opinion/2020/11/12/joe-biden-is-old-but-how-old-compared-to-other-leaders-opinion/|archive-date=November 13, 2020}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[James K. Polk]] had the shortest retirement of any president, dying barely three months after leaving office at age 53 (the youngest president to die of natural causes).&amp;lt;ref&amp;gt;{{cite web| title=James Polk| date=October 24, 2019| orig-year=April 2, 2014| website=biography.com| url=https://www.biography.com/us-president/james-polk| access-date=January 24, 2021| publisher=A&amp;amp;E Television Networks}}&amp;lt;/ref&amp;gt; [[Jimmy Carter]]&#039;s retirement, now {{age|1981|1|20}} years, is the longest in American presidential history. At age {{age|1924|10|1}}, Jimmy Carter is also the oldest living president&amp;lt;ref name=NYT01202021/&amp;gt; as well as the nation&#039;s longest-lived president.&amp;lt;ref&amp;gt;{{cite news|last=Raymond|first=Jonathan|date=January 20, 2021|title=Jimmy Carter, unable to make inauguration, saluted by President Biden in remarks|publisher=[[WXIA-TV]]|url=https://www.11alive.com/article/news/politics/jimmy-carter-biden-salute-inauguration/85-d40e3e07-e37c-478f-90f7-841c991d4cc8|url-status=live|access-date=January 31, 2021|archive-url=https://archive.today/20210611045907/https://www.11alive.com/article/news/politics/jimmy-carter-biden-salute-inauguration/85-d40e3e07-e37c-478f-90f7-841c991d4cc8|archive-date=June 11, 2021}}&amp;lt;/ref&amp;gt; He is one of six U.S. presidents (along with [[John Adams]], [[Herbert Hoover]], [[Ronald Reagan]], [[Gerald Ford]] and [[George H. W. Bush]]) to have lived into their 90s.&amp;lt;ref&amp;gt;{{cite web| last=Feinman| first=Ronald L.| title=Presidents and Vice Presidents Who Lived Into Their 90s in American History| date=November 6, 2015| url=http://www.theprogressiveprofessor.com/?p=25854| work=The Progressive Professor| access-date=January 31, 2021}}&amp;lt;/ref&amp;gt; The youngest living president is Barack Obama, age {{age|1961|8|4}}.&lt;br /&gt;
&lt;br /&gt;
==Presidential age-related data==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;sortable wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; rowspan=2 | {{Abbr|No.|Order of presidency}}&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; rowspan=2 | President&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; rowspan=2 | Born&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; rowspan=2 | Age at&amp;lt;br&amp;gt;{{nowrap|start of presidency}}&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; rowspan=2 | Age at&amp;lt;br&amp;gt;{{nowrap|end of presidency}}&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; rowspan=2 | {{nowrap|Post-presidency}}&amp;lt;br&amp;gt;timespan&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; colspan=2 | Lifespan&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; | Died&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; | Age&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | {{0}}1&lt;br /&gt;
| {{sortname|George|Washington}}&lt;br /&gt;
| {{dts|1732|2|22|abbr=on}}{{efn|name=calendar|Birthdate as changed to [[Calendar (New Style) Act 1750|New Style]].}}&lt;br /&gt;
| {{ayd|1732|2|22|1789|4|30}}&amp;lt;br&amp;gt;{{dts|1789|4|30|abbr=on}}&lt;br /&gt;
| {{ayd|1732|2|22|1797|3|4}}&amp;lt;br&amp;gt;{{dts|1797|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1797|3|4|1799|12|14}}&lt;br /&gt;
| {{dts|1799|12|14|abbr=on}}&lt;br /&gt;
| {{ayd|1732|2|22|1799|12|14}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | {{0}}2&lt;br /&gt;
| {{sortname|John|Adams}}&lt;br /&gt;
| {{dts|1735|10|30|abbr=on}}{{efn|name=calendar|Birthdate as changed to [[Calendar (New Style) Act 1750|New Style]].}}&lt;br /&gt;
| {{nowrap|{{ayd|1735|10|30|1797|3|4}}}}&amp;lt;br&amp;gt;{{dts|1797|3|4|abbr=on}}&lt;br /&gt;
| {{nowrap|{{ayd|1735|10|30|1801|3|4}}}}&amp;lt;br&amp;gt;{{dts|1801|3|4|abbr=on}}&lt;br /&gt;
| {{nowrap|{{ayd|1801|3|4|1826|7|4}}}}&lt;br /&gt;
| &amp;lt;span style=&amp;quot;display:none&amp;quot;&amp;gt;{{dts|1826|7|5}}&amp;lt;/span&amp;gt;{{dts|1826|7|4|abbr=on}}&lt;br /&gt;
| {{nowrap|{{ayd|1735|10|30|1826|7|4}}}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | {{0}}3&lt;br /&gt;
| {{sortname|Thomas|Jefferson}}&lt;br /&gt;
| {{dts|1743|4|13|abbr=on}}{{efn|name=calendar|Birthdate as changed to [[Calendar (New Style) Act 1750|New Style]].}}&lt;br /&gt;
| {{ayd|1743|4|13|1801|3|4}}&amp;lt;br&amp;gt;{{dts|1801|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1743|4|13|1809|3|4}}&amp;lt;br&amp;gt;{{dts|1809|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1809|3|4|1826|7|4}}&lt;br /&gt;
| {{dts|1826|7|4|abbr=on}}&lt;br /&gt;
| {{ayd|1743|4|13|1826|7|4}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | {{0}}4&lt;br /&gt;
| {{sortname|James|Madison}}&lt;br /&gt;
| {{dts|1751|3|16|abbr=on}}{{efn|name=calendar|Birthdate as changed to [[Calendar (New Style) Act 1750|New Style]].}}&lt;br /&gt;
| {{ayd|1751|3|16|1809|3|4}}&amp;lt;br&amp;gt;{{dts|1809|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1751|3|16|1817|3|4}}&amp;lt;br&amp;gt;{{dts|1817|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1817|3|4|1836|6|28}}&lt;br /&gt;
| {{dts|1836|6|28|abbr=on}}&lt;br /&gt;
| {{ayd|1751|3|16|1836|6|28}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | {{0}}5&lt;br /&gt;
| {{sortname|James|Monroe}}&lt;br /&gt;
| {{dts|1758|4|28|abbr=on}}&lt;br /&gt;
| {{ayd|1758|4|28|1817|3|4}}&amp;lt;br&amp;gt;{{dts|1817|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1758|4|28|1825|3|4}}&amp;lt;br&amp;gt;{{dts|1825|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1825|3|4|1831|7|4}}&lt;br /&gt;
| {{dts|1831|7|4|abbr=on}}&lt;br /&gt;
| {{ayd|1758|4|28|1831|7|4}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | {{0}}6&lt;br /&gt;
| {{sortname|John Quincy|Adams}}&lt;br /&gt;
| {{dts|1767|7|11|abbr=on}}&lt;br /&gt;
| {{ayd|1767|7|11|1825|3|4}}&amp;lt;br&amp;gt;{{dts|1825|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1767|7|11|1829|3|4}}&amp;lt;br&amp;gt;{{dts|1829|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1829|3|4|1848|2|23}}&lt;br /&gt;
| {{dts|1848|2|23|abbr=on}}&lt;br /&gt;
| {{ayd|1767|7|11|1848|2|23}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | {{0}}7&lt;br /&gt;
| {{sortname|Andrew|Jackson}}&lt;br /&gt;
| {{dts|1767|3|15|abbr=on}}&lt;br /&gt;
| {{ayd|1767|3|15|1829|3|4}}&amp;lt;br&amp;gt;{{dts|1829|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1767|3|15|1837|3|4}}&amp;lt;br&amp;gt;{{dts|1837|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1837|3|4|1845|6|8}}&lt;br /&gt;
| {{dts|1845|6|8|abbr=on}}&lt;br /&gt;
| {{ayd|1767|3|15|1845|6|8}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | {{0}}8&lt;br /&gt;
| {{sortname|Martin Van|Buren}}&lt;br /&gt;
| {{dts|1782|12|5|abbr=on}}&lt;br /&gt;
| {{ayd|1782|12|5|1837|3|4}}&amp;lt;br&amp;gt;{{dts|1837|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1782|12|5|1841|3|4}}&amp;lt;br&amp;gt;{{dts|1841|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1841|3|4|1862|7|24}}&lt;br /&gt;
| {{dts|1862|7|24|abbr=on}}&lt;br /&gt;
| {{ayd|1782|12|5|1862|7|24}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | {{0}}9&lt;br /&gt;
| {{sortname|William Henry|Harrison}}&lt;br /&gt;
| {{dts|1773|2|9|abbr=on}}&lt;br /&gt;
| {{ayd|1773|2|9|1841|3|4}}&amp;lt;br&amp;gt;{{dts|1841|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1773|2|9|1841|4|4}}&amp;lt;br&amp;gt; {{dts|1841|4|4|abbr=on}}&lt;br /&gt;
| &amp;lt;span style=&amp;quot;display:none&amp;quot;&amp;gt;00,001&amp;lt;/span&amp;gt;0 days{{efn|name=died|Died in office}}&lt;br /&gt;
| {{dts|1841|4|4|abbr=on}}&lt;br /&gt;
| {{ayd|1773|2|9|1841|4|4}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 10&lt;br /&gt;
| {{sortname|John|Tyler}}&lt;br /&gt;
| {{dts|1790|3|29|abbr=on}}&lt;br /&gt;
| {{ayd|1790|3|29|1841|4|4}}&amp;lt;br&amp;gt;{{dts|1841|4|4|abbr=on}}&lt;br /&gt;
| {{ayd|1790|3|29|1845|3|4}}&amp;lt;br&amp;gt;{{dts|1845|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1845|3|4|1862|1|18}}&lt;br /&gt;
| {{dts|1862|1|18|abbr=on}}&lt;br /&gt;
| {{ayd|1790|3|29|1862|1|18}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 11&lt;br /&gt;
| {{sortname|James K.|Polk}}&lt;br /&gt;
| {{dts|1795|11|2|abbr=on}}&lt;br /&gt;
| {{ayd|1795|11|2|1845|3|4}}&amp;lt;br&amp;gt;{{dts|1845|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1795|11|2|1849|3|4}}&amp;lt;br&amp;gt;{{dts|1849|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1849|3|4|1849|6|15}}&lt;br /&gt;
| {{dts|1849|6|15|abbr=on}}&lt;br /&gt;
| {{ayd|1795|11|2|1849|6|15}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 12&lt;br /&gt;
| {{sortname|Zachary|Taylor}}&lt;br /&gt;
| {{dts|1784|11|24|abbr=on}}&lt;br /&gt;
| {{ayd|1784|11|24|1849|3|4}}&amp;lt;br&amp;gt;{{dts|1849|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1784|11|24|1850|7|9}}&amp;lt;br&amp;gt;{{dts|1850|7|9|abbr=on}}&lt;br /&gt;
| &amp;lt;span style=&amp;quot;display:none&amp;quot;&amp;gt;00,003&amp;lt;/span&amp;gt;0 days{{efn|name=died}}&lt;br /&gt;
| {{dts|1850|7|9|abbr=on}}&lt;br /&gt;
| {{ayd|1784|11|24|1850|7|9}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 13&lt;br /&gt;
| {{sortname|Millard|Fillmore}}&lt;br /&gt;
| {{dts|1800|1|7|abbr=on}}&lt;br /&gt;
| {{ayd|1800|1|7|1850|7|9}}&amp;lt;br&amp;gt;{{dts|1850|7|9|abbr=on}}&lt;br /&gt;
| {{ayd|1800|1|7|1853|3|4}}&amp;lt;br&amp;gt;{{dts|1853|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1853|3|4|1874|3|8}}&lt;br /&gt;
| {{dts|1874|3|8|abbr=on}}&lt;br /&gt;
| {{ayd|1800|1|7|1874|3|8}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 14&lt;br /&gt;
| {{sortname|Franklin|Pierce}}&lt;br /&gt;
| {{dts|1804|11|23|abbr=on}}&lt;br /&gt;
| {{ayd|1804|11|23|1853|3|4}}&amp;lt;br&amp;gt;{{dts|1853|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1804|11|23|1857|3|4}}&amp;lt;br&amp;gt;{{dts|1857|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1857|3|4|1869|10|8}}&lt;br /&gt;
| {{dts|1869|10|8|abbr=on}}&lt;br /&gt;
| {{ayd|1804|11|23|1869|10|8}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 15&lt;br /&gt;
| {{sortname|James|Buchanan}}&lt;br /&gt;
| {{dts|1791|4|23|abbr=on}}&lt;br /&gt;
| {{ayd|1791|4|23|1857|3|4}}&amp;lt;br&amp;gt;{{dts|1857|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1791|4|23|1861|3|4}}&amp;lt;br&amp;gt;{{dts|1861|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1861|3|4|1868|6|1}}&lt;br /&gt;
| {{dts|1868|6|1|abbr=on}}&lt;br /&gt;
| {{ayd|1791|4|23|1868|6|1}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 16&lt;br /&gt;
| {{sortname|Abraham|Lincoln}}&lt;br /&gt;
| {{dts|1809|2|12|abbr=on}}&lt;br /&gt;
| {{ayd|1809|2|12|1861|3|4}}&amp;lt;br&amp;gt;{{dts|1861|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1809|2|12|1865|4|15}}&amp;lt;br&amp;gt;{{dts|1865|4|15|abbr=on}}&lt;br /&gt;
| &amp;lt;span style=&amp;quot;display:none&amp;quot;&amp;gt;00,006&amp;lt;/span&amp;gt;0 days{{efn|name=died}}&lt;br /&gt;
| {{dts|1865|4|15|abbr=on}}&lt;br /&gt;
| {{ayd|1809|2|12|1865|4|15}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 17&lt;br /&gt;
| {{sortname|Andrew|Johnson}}&lt;br /&gt;
| {{dts|1808|12|29|abbr=on}}&lt;br /&gt;
| {{ayd|1808|12|29|1865|4|15}}&amp;lt;br&amp;gt;{{dts|1865|4|15|abbr=on}}&lt;br /&gt;
| {{ayd|1808|12|29|1869|3|4}}&amp;lt;br&amp;gt;{{dts|1869|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1869|3|4|1875|7|31}}&lt;br /&gt;
| {{dts|1875|7|31|abbr=on}}&lt;br /&gt;
| {{ayd|1808|12|29|1875|7|31}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 18&lt;br /&gt;
| {{sortname|Ulysses S.|Grant}}&lt;br /&gt;
| {{dts|1822|4|27|abbr=on}}&lt;br /&gt;
| {{ayd|1822|4|27|1869|3|4}}&amp;lt;br&amp;gt;{{dts|1869|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1822|4|27|1877|3|4}}&amp;lt;br&amp;gt;{{dts|1877|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1877|3|4|1885|7|23}}&lt;br /&gt;
| {{dts|1885|7|23|abbr=on}}&lt;br /&gt;
| {{ayd|1822|4|27|1885|7|23}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 19&lt;br /&gt;
| {{sortname|Rutherford B.|Hayes}}&lt;br /&gt;
| {{dts|1822|10|4|abbr=on}}&lt;br /&gt;
| {{ayd|1822|10|4|1877|3|4}}&amp;lt;br&amp;gt;{{dts|1877|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1822|10|4|1881|3|4}}&amp;lt;br&amp;gt;{{dts|1881|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1881|3|4|1893|1|17}}&lt;br /&gt;
| {{dts|1893|1|17|abbr=on}}&lt;br /&gt;
| {{ayd|1822|10|4|1893|1|17}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 20&lt;br /&gt;
| {{sortname|James A.|Garfield}}&lt;br /&gt;
| {{dts|1831|11|19|abbr=on}}&lt;br /&gt;
| {{ayd|1831|11|19|1881|3|4}}&amp;lt;br&amp;gt;{{dts|1881|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1831|11|19|1881|9|19}}&amp;lt;br&amp;gt;{{dts|1881|9|19|abbr=on}}&lt;br /&gt;
| &amp;lt;span style=&amp;quot;display:none&amp;quot;&amp;gt;00,002&amp;lt;/span&amp;gt;0 days{{efn|name=died}}&lt;br /&gt;
| {{dts|1881|9|19|abbr=on}}&lt;br /&gt;
| {{ayd|1831|11|19|1881|9|19}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 21&lt;br /&gt;
| {{sortname|Chester A.|Arthur}}&lt;br /&gt;
| {{dts|1829|10|5|abbr=on}}&lt;br /&gt;
| {{ayd|1829|10|5|1881|9|19}}&amp;lt;br&amp;gt;{{dts|1881|9|19|abbr=on}}&lt;br /&gt;
| {{ayd|1829|10|5|1885|3|4}}&amp;lt;br&amp;gt;{{dts|1885|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1885|3|4|1886|11|18}}&lt;br /&gt;
| {{dts|1886|11|18|abbr=on}}&lt;br /&gt;
| {{ayd|1829|10|5|1886|11|18}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 22&lt;br /&gt;
| {{sortname|Grover|Cleveland}}&lt;br /&gt;
| {{dts|1837|3|18|abbr=on}}&lt;br /&gt;
| {{ayd|1837|3|18|1885|3|4}}&amp;lt;br&amp;gt;{{dts|1885|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1837|3|18|1889|3|4}}&amp;lt;br&amp;gt;{{dts|1889|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1889|3|4|1893|3|4}}{{efn|name=cleveland 1|Cleveland was president for two non-consecutive terms; this is his first post-presidential retirement, between his terms (1889–1893).}}&lt;br /&gt;
| {{dts|1908|6|24|abbr=on}}&lt;br /&gt;
| {{ayd|1837|3|18|1908|6|24}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 23&lt;br /&gt;
| {{sortname|Benjamin|Harrison}}&lt;br /&gt;
| {{dts|1833|8|20|abbr=on}}&lt;br /&gt;
| {{ayd|1833|8|20|1889|3|4}}&amp;lt;br&amp;gt;{{dts|1889|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1833|8|20|1893|3|4}}&amp;lt;br&amp;gt;{{dts|1893|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1893|3|4|1901|3|13}}&lt;br /&gt;
| {{dts|1901|3|13|abbr=on}}&lt;br /&gt;
| {{ayd|1833|8|20|1901|3|13}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 24&lt;br /&gt;
| {{sortname|Grover|Cleveland}}&lt;br /&gt;
| {{dts|1837|3|18|abbr=on}}&lt;br /&gt;
| {{ayd|1837|3|18|1893|3|4}}&amp;lt;br&amp;gt;{{dts|1893|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1837|3|18|1897|3|4}}&amp;lt;br&amp;gt;{{dts|1897|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1897|3|4|1908|6|24}}{{efn|name=cleveland 2|Cleveland was president for two non-consecutive terms; this is his post-presidential retirement, after his second term (1897–1908).}}&lt;br /&gt;
| {{dts|1908|6|24|abbr=on}}&lt;br /&gt;
| {{ayd|1837|3|18|1908|6|24}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 25&lt;br /&gt;
| {{sortname|William|McKinley}}&lt;br /&gt;
| {{dts|1843|1|29|abbr=on}}&lt;br /&gt;
| {{ayd|1843|1|29|1897|3|4}}&amp;lt;br&amp;gt;{{dts|1897|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1843|1|29|1901|9|14}}&amp;lt;br&amp;gt;{{dts|1901|9|14|abbr=on}}&lt;br /&gt;
| &amp;lt;span style=&amp;quot;display:none&amp;quot;&amp;gt;00,007&amp;lt;/span&amp;gt;0 days{{efn|name=died}}&lt;br /&gt;
| {{dts|1901|9|14|abbr=on}}&lt;br /&gt;
| {{ayd|1843|1|29|1901|9|14}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 26&lt;br /&gt;
| {{sortname|Theodore|Roosevelt}}&lt;br /&gt;
| {{dts|1858|10|27|abbr=on}}&lt;br /&gt;
| {{ayd|1858|10|27|1901|9|14}}&amp;lt;br&amp;gt;{{dts|1901|9|14|abbr=on}}&lt;br /&gt;
| {{ayd|1858|10|27|1909|3|4}}&amp;lt;br&amp;gt;{{dts|1909|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1909|3|4|1919|1|6}}&lt;br /&gt;
| {{dts|1919|1|6|abbr=on}}&lt;br /&gt;
| {{ayd|1858|10|27|1919|1|6}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 27&lt;br /&gt;
| {{sortname|William Howard|Taft}}&lt;br /&gt;
| {{dts|1857|9|15|abbr=on}}&lt;br /&gt;
| {{ayd|1857|9|15|1909|3|4}}&amp;lt;br&amp;gt;{{dts|1909|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1857|9|15|1913|3|4}}&amp;lt;br&amp;gt;{{dts|1913|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1913|3|4|1930|3|8}}&lt;br /&gt;
| {{dts|1930|3|8|abbr=on}}&lt;br /&gt;
| {{ayd|1857|9|15|1930|3|8}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 28&lt;br /&gt;
| {{sortname|Woodrow|Wilson}}&lt;br /&gt;
| {{dts|1856|12|28|abbr=on}}&lt;br /&gt;
| {{ayd|1856|12|28|1913|3|4}}&amp;lt;br&amp;gt;{{dts|1913|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1856|12|28|1921|3|4}}&amp;lt;br&amp;gt;{{dts|1921|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1921|3|4|1924|2|3}}&lt;br /&gt;
| {{dts|1924|2|3|abbr=on}}&lt;br /&gt;
| {{ayd|1856|12|28|1924|2|3}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 29&lt;br /&gt;
| {{sortname|Warren G.|Harding}}&lt;br /&gt;
| {{dts|1865|11|2|abbr=on}}&lt;br /&gt;
| {{ayd|1865|11|2|1921|3|4}}&amp;lt;br&amp;gt;{{dts|1921|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1865|11|2|1923|8|2}}&amp;lt;br&amp;gt;{{dts|1923|8|2|abbr=on}}&lt;br /&gt;
| &amp;lt;span style=&amp;quot;display:none&amp;quot;&amp;gt;00,004&amp;lt;/span&amp;gt;0 days{{efn|name=died}}&lt;br /&gt;
| {{dts|1923|8|2|abbr=on}}&lt;br /&gt;
| {{ayd|1865|11|2|1923|8|2}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 30&lt;br /&gt;
| {{sortname|Calvin|Coolidge}}&lt;br /&gt;
| {{dts|1872|7|4|abbr=on}}&lt;br /&gt;
| {{ayd|1872|7|4|1923|8|2}}&amp;lt;br&amp;gt;{{dts|1923|8|2|abbr=on}}&lt;br /&gt;
| {{ayd|1872|7|4|1929|3|4}}&amp;lt;br&amp;gt;{{dts|1929|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1929|3|4|1933|1|5}}&lt;br /&gt;
| {{dts|1933|1|5|abbr=on}}&lt;br /&gt;
| {{ayd|1872|7|4|1933|1|5}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 31&lt;br /&gt;
| {{sortname|Herbert|Hoover}}&lt;br /&gt;
| {{dts|1874|8|10|abbr=on}}&lt;br /&gt;
| {{ayd|1874|8|10|1929|3|4}}&amp;lt;br&amp;gt;{{dts|1929|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1874|8|10|1933|3|4}}&amp;lt;br&amp;gt;{{dts|1933|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1933|3|4|1964|10|20}}&lt;br /&gt;
| {{dts|1964|10|20|abbr=on}}&lt;br /&gt;
| {{ayd|1874|8|10|1964|10|20}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 32&lt;br /&gt;
| nowrap | {{sortname|Franklin D.|Roosevelt}}&lt;br /&gt;
| {{dts|1882|1|30|abbr=on}}&lt;br /&gt;
| {{ayd|1882|1|30|1933|3|4}}&amp;lt;br&amp;gt;{{dts|1933|3|4|abbr=on}}&lt;br /&gt;
| {{ayd|1882|1|30|1945|4|12}}&amp;lt;br&amp;gt;{{dts|1945|4|12|abbr=on}}&lt;br /&gt;
| &amp;lt;span style=&amp;quot;display:none&amp;quot;&amp;gt;00,008&amp;lt;/span&amp;gt;0 days{{efn|name=died}}&lt;br /&gt;
| {{dts|1945|4|12|abbr=on}}&lt;br /&gt;
| {{ayd|1882|1|30|1945|4|12}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 33&lt;br /&gt;
| {{sortname|Harry S.|Truman}}&lt;br /&gt;
| {{dts|1884|5|8|abbr=on}}&lt;br /&gt;
| {{ayd|1884|5|8|1945|4|12}}&amp;lt;br&amp;gt;{{dts|1945|4|12|abbr=on}}&lt;br /&gt;
| {{ayd|1884|5|8|1953|1|20}}&amp;lt;br&amp;gt;{{dts|1953|1|20|abbr=on}}&lt;br /&gt;
| {{ayd|1953|1|20|1972|12|26}}&lt;br /&gt;
| {{dts|1972|12|26|abbr=on}}&lt;br /&gt;
| {{ayd|1884|5|8|1972|12|26}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 34&lt;br /&gt;
| nowrap | {{sortname|Dwight D.|Eisenhower}}&lt;br /&gt;
| {{dts|1890|10|14|abbr=on}}&lt;br /&gt;
| {{ayd|1890|10|14|1953|1|20}}&amp;lt;br&amp;gt;{{dts|1953|1|20|abbr=on}}&lt;br /&gt;
| {{ayd|1890|10|14|1961|1|20}}&amp;lt;br&amp;gt;{{dts|1961|1|20|abbr=on}}&lt;br /&gt;
| {{ayd|1961|1|20|1969|3|28}}&lt;br /&gt;
| {{dts|1969|3|28|abbr=on}}&lt;br /&gt;
| {{ayd|1890|10|14|1969|3|28}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 35&lt;br /&gt;
| {{sortname|John F.|Kennedy}}&lt;br /&gt;
| {{dts|1917|5|29|abbr=on}}&lt;br /&gt;
| {{ayd|1917|5|29|1961|1|20}}&amp;lt;br&amp;gt;{{dts|1961|1|20|abbr=on}}&lt;br /&gt;
| {{ayd|1917|5|29|1963|11|22}}&amp;lt;br&amp;gt;{{dts|1963|11|22|abbr=on}}&lt;br /&gt;
| &amp;lt;span style=&amp;quot;display:none&amp;quot;&amp;gt;00,005&amp;lt;/span&amp;gt;0 days{{efn|name=died}}&lt;br /&gt;
| {{dts|1963|11|22|abbr=on}}&lt;br /&gt;
| {{ayd|1917|5|29|1963|11|22}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 36&lt;br /&gt;
| {{sortname|Lyndon B.|Johnson}}&lt;br /&gt;
| {{dts|1908|8|27|abbr=on}}&lt;br /&gt;
| {{ayd|1908|8|27|1963|11|22}}&amp;lt;br&amp;gt;{{dts|1963|11|22|abbr=on}}&lt;br /&gt;
| {{ayd|1908|8|27|1969|1|20}}&amp;lt;br&amp;gt;{{dts|1969|1|20|abbr=on}}&lt;br /&gt;
| {{ayd|1969|1|20|1973|1|22}}&lt;br /&gt;
| {{dts|1973|1|22|abbr=on}}&lt;br /&gt;
| {{ayd|1908|8|27|1973|1|22}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 37&lt;br /&gt;
| {{sortname|Richard|Nixon}}&lt;br /&gt;
| {{dts|1913|1|9|abbr=on}}&lt;br /&gt;
| {{ayd|1913|1|9|1969|1|20}}&amp;lt;br&amp;gt;{{dts|1969|1|20|abbr=on}}&lt;br /&gt;
| {{ayd|1913|1|9|1974|8|9}}&amp;lt;br&amp;gt;{{dts|1974|8|9|abbr=on}}{{efn|Resigned from office.}}&lt;br /&gt;
| {{ayd|1974|8|9|1994|4|22}}&lt;br /&gt;
| {{dts|1994|4|22|abbr=on}}&lt;br /&gt;
| {{ayd|1913|1|9|1994|4|22}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 38&lt;br /&gt;
| {{sortname|Gerald|Ford}}&lt;br /&gt;
| {{dts|1913|7|14|abbr=on}}&lt;br /&gt;
| {{ayd|1913|7|14|1974|8|9}}&amp;lt;br&amp;gt;{{dts|1974|8|9|abbr=on}}&lt;br /&gt;
| {{ayd|1913|7|14|1977|1|20}}&amp;lt;br&amp;gt;{{dts|1977|1|20|abbr=on}}&lt;br /&gt;
| {{ayd|1977|1|20|2006|12|26}}&lt;br /&gt;
| {{dts|2006|12|26|abbr=on}}&lt;br /&gt;
| {{ayd|1913|7|14|2006|12|26}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 39&lt;br /&gt;
| {{sortname|Jimmy|Carter}}&lt;br /&gt;
| {{dts|1924|10|1|abbr=on}}&lt;br /&gt;
| {{ayd|1924|10|1|1977|1|20}}&amp;lt;br&amp;gt;{{dts|1977|1|20|abbr=on}}&lt;br /&gt;
| {{ayd|1924|10|1|1981|1|20}}&amp;lt;br&amp;gt;{{dts|1981|1|20|abbr=on}}&lt;br /&gt;
|&#039;&#039;{{ayd|1981|1|20}}&#039;&#039;&lt;br /&gt;
| &amp;lt;span style=&amp;quot;display:none&amp;quot;&amp;gt;{{CURRENTYEAR}}-{{CURRENTMONTH}}-{{CURRENTDAY}}&amp;lt;/span&amp;gt;&#039;&#039;(living)&#039;&#039;&lt;br /&gt;
| &#039;&#039;{{ayd|1924|10|1}}&#039;&#039;&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 40&lt;br /&gt;
| {{sortname|Ronald|Reagan}}&lt;br /&gt;
| {{dts|1911|2|6|abbr=on}}&lt;br /&gt;
| {{ayd|1911|2|6|1981|1|20}}&amp;lt;br&amp;gt;{{dts|1981|1|20|abbr=on}}&lt;br /&gt;
| {{ayd|1911|2|6|1989|1|20}}&amp;lt;br&amp;gt;{{dts|1989|1|20|abbr=on}}&lt;br /&gt;
| {{ayd|1989|1|20|2004|6|5}}&lt;br /&gt;
| {{dts|2004|6|5|abbr=on}}&lt;br /&gt;
| {{ayd|1911|2|6|2004|6|5}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 41&lt;br /&gt;
| {{sortname|George H. W.|Bush}}&lt;br /&gt;
| {{dts|1924|6|12|abbr=on}}&lt;br /&gt;
| {{ayd|1924|6|12|1989|1|20}}&amp;lt;br&amp;gt;{{dts|1989|1|20|abbr=on}}&lt;br /&gt;
| {{ayd|1924|6|12|1993|1|20}}&amp;lt;br&amp;gt;{{dts|1993|1|20|abbr=on}}&lt;br /&gt;
| {{ayd|1993|1|20|2018|11|30}}&lt;br /&gt;
| {{dts|2018|11|30|abbr=on}}&lt;br /&gt;
| {{ayd|1924|6|12|2018|11|30}}&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 42&lt;br /&gt;
| {{sortname|Bill|Clinton}}&lt;br /&gt;
| {{dts|1946|8|19|abbr=on}}&lt;br /&gt;
| {{ayd|1946|8|19|1993|1|20}}&amp;lt;br&amp;gt;{{dts|1993|1|20|abbr=on}}&lt;br /&gt;
| {{ayd|1946|8|19|2001|1|20}}&amp;lt;br&amp;gt;{{dts|2001|1|20|abbr=on}}&lt;br /&gt;
|&#039;&#039;{{ayd|2001|1|20}}&#039;&#039;&lt;br /&gt;
| &amp;lt;span style=&amp;quot;display:none&amp;quot;&amp;gt;{{CURRENTYEAR}}-{{CURRENTMONTH}}-{{CURRENTDAY}}&amp;lt;/span&amp;gt;&#039;&#039;(living)&#039;&#039;&lt;br /&gt;
| &#039;&#039;{{ayd|1946|8|19}}&#039;&#039;&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 43&lt;br /&gt;
| {{sortname|George W.|Bush}}&lt;br /&gt;
| {{dts|1946|7|6|abbr=on}}&lt;br /&gt;
| {{ayd|1946|7|6|2001|1|20}}&amp;lt;br&amp;gt;{{dts|2001|1|20|abbr=on}}&lt;br /&gt;
| {{ayd|1946|7|6|2009|1|20}}&amp;lt;br&amp;gt;{{dts|2009|1|20|abbr=on}}&lt;br /&gt;
|&#039;&#039;{{ayd|2009|1|20}}&#039;&#039;&lt;br /&gt;
| &amp;lt;span style=&amp;quot;display:none&amp;quot;&amp;gt;{{CURRENTYEAR}}-{{CURRENTMONTH}}-{{CURRENTDAY}}&amp;lt;/span&amp;gt;&#039;&#039;(living)&#039;&#039;&lt;br /&gt;
| &#039;&#039;{{ayd|1946|7|6}}&#039;&#039;&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 44&lt;br /&gt;
| {{sortname|Barack|Obama}}&lt;br /&gt;
| {{dts|1961|8|4|abbr=on}}&lt;br /&gt;
| {{ayd|1961|8|4|2009|1|20}}&amp;lt;br&amp;gt;{{dts|2009|1|20|abbr=on}}&lt;br /&gt;
| {{ayd|1961|8|4|2017|1|20}}&amp;lt;br&amp;gt;{{dts|2017|1|20|abbr=on}}&lt;br /&gt;
|&#039;&#039;{{ayd|2017|1|20}}&#039;&#039;&lt;br /&gt;
| &amp;lt;span style=&amp;quot;display:none&amp;quot;&amp;gt;{{CURRENTYEAR}}-{{CURRENTMONTH}}-{{CURRENTDAY}}&amp;lt;/span&amp;gt;&#039;&#039;(living)&#039;&#039;&lt;br /&gt;
| &#039;&#039;{{ayd|1961|8|4}}&#039;&#039;&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 45&lt;br /&gt;
| {{sortname|Donald|Trump}}&lt;br /&gt;
| {{dts|1946|6|14|abbr=on}}&lt;br /&gt;
| {{ayd|1946|6|14|2017|1|20}}&amp;lt;br&amp;gt;{{dts|2017|1|20|abbr=on}}&lt;br /&gt;
| {{ayd|1946|6|14|2021|1|20}}&amp;lt;br&amp;gt;{{dts|2021|1|20|abbr=on}}&lt;br /&gt;
|&#039;&#039;{{ayd|2021|1|20}}&#039;&#039;&lt;br /&gt;
| &amp;lt;span style=&amp;quot;display:none&amp;quot;&amp;gt;{{CURRENTYEAR}}-{{CURRENTMONTH}}-{{CURRENTDAY}}&amp;lt;/span&amp;gt;&#039;&#039;(living)&#039;&#039;&lt;br /&gt;
| &#039;&#039;{{ayd|1946|6|14}}&#039;&#039;&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | 46&lt;br /&gt;
| {{sortname|Joe|Biden}}&lt;br /&gt;
| {{dts|1942|11|20|abbr=on}}&lt;br /&gt;
| {{ayd|1942|11|20|2021|1|20}}&amp;lt;br&amp;gt;{{dts|2021|1|20|abbr=on}}&lt;br /&gt;
| &amp;lt;span style=&amp;quot;display:none&amp;quot;&amp;gt;{{ayd|1942|11|20}}&amp;lt;/span&amp;gt;&#039;&#039;(incumbent)&#039;&#039;&lt;br /&gt;
| &#039;&#039;(incumbent)&#039;&#039;&lt;br /&gt;
| &amp;lt;span style=&amp;quot;display:none&amp;quot;&amp;gt;{{CURRENTYEAR}}-{{CURRENTMONTH}}-{{CURRENTDAY}}&amp;lt;/span&amp;gt;&#039;&#039;(living)&#039;&#039;&lt;br /&gt;
| &#039;&#039;{{ayd|1942|11|20}}&#039;&#039;&lt;br /&gt;
|- style=&amp;quot;text-align: left; background:#FFFFFF&amp;quot;&lt;br /&gt;
! rowspan=2 | &amp;lt;abbr title=&amp;quot;Order of presidency&amp;quot;&amp;gt;#&amp;lt;/abbr&amp;gt;&lt;br /&gt;
! rowspan=2 | President&lt;br /&gt;
! rowspan=2 | Born&lt;br /&gt;
! rowspan=2 | Age at&amp;lt;br&amp;gt;{{nowrap|start of presidency}}&lt;br /&gt;
! rowspan=2 | Age at&amp;lt;br&amp;gt;{{nowrap|end of presidency}}&lt;br /&gt;
! rowspan=2 | {{nowrap|Post-presidency}}&amp;lt;br&amp;gt;timespan&lt;br /&gt;
! Died !! Age&lt;br /&gt;
|- &lt;br /&gt;
! colspan=2 | Lifespan&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Notes===&lt;br /&gt;
{{notelist}}&lt;br /&gt;
&lt;br /&gt;
{{anchor|oldest}}&lt;br /&gt;
&lt;br /&gt;
==Graphical representation==&lt;br /&gt;
This is a [[Bar chart|graphical]] lifespan timeline of the presidents of the United States. They are listed in order of office, with Grover Cleveland listed in the order of his first presidency.&lt;br /&gt;
&lt;br /&gt;
{{Lifespan of each United States president}}&lt;br /&gt;
&lt;br /&gt;
The following chart shows presidents by their age (living presidents in green), with the years of their presidency in blue.&lt;br /&gt;
&lt;br /&gt;
{{United States presidents by age}}&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
{{reflist}}&lt;br /&gt;
&lt;br /&gt;
==Sources==&lt;br /&gt;
* Frank Freidel and Hugh S. Sidey, [https://www.whitehouse.gov/about-the-white-house/presidents/ &amp;quot;The Presidents of the United States&amp;quot;]. The [[White House]].&lt;br /&gt;
* Robert S. Summers, [https://web.archive.org/web/20050810015819/http://www.ipl.org/div/potus/ &amp;quot;POTUS: Presidents of the United States&amp;quot;]. [[Internet Public Library]].&lt;br /&gt;
&lt;br /&gt;
{{Lists of US Presidents and Vice Presidents}}&lt;br /&gt;
&lt;br /&gt;
{{DEFAULTSORT:presidents of the United States by age}}&lt;br /&gt;
[[Category:Lists of political office-holders by age|United States, Presidents]]&lt;br /&gt;
[[Category:Lists relating to the United States presidency|Age]]&lt;br /&gt;
[[Category:United States presidents and death]]&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Portal_bar/styles.css&amp;diff=1481</id>
		<title>Portal bar/styles.css</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Portal_bar/styles.css&amp;diff=1481"/>
		<updated>2022-08-12T14:32:27Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Navbox/styles.css&amp;diff=1479</id>
		<title>Navbox/styles.css</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Navbox/styles.css&amp;diff=1479"/>
		<updated>2022-08-12T14:32:26Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Navbar/styles.css&amp;diff=1477</id>
		<title>Navbar/styles.css</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Navbar/styles.css&amp;diff=1477"/>
		<updated>2022-08-12T14:32:26Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Hatnote/styles.css&amp;diff=1475</id>
		<title>Hatnote/styles.css</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Hatnote/styles.css&amp;diff=1475"/>
		<updated>2022-08-12T14:32:26Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Citation/CS1/styles.css&amp;diff=1473</id>
		<title>Citation/CS1/styles.css</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Citation/CS1/styles.css&amp;diff=1473"/>
		<updated>2022-08-12T14:32:25Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Yesno&amp;diff=1471</id>
		<title>Yesno</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Yesno&amp;diff=1471"/>
		<updated>2022-08-12T14:32:25Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{&amp;lt;includeonly&amp;gt;safesubst:&amp;lt;/includeonly&amp;gt;#switch: {{&amp;lt;includeonly&amp;gt;safesubst:&amp;lt;/includeonly&amp;gt;lc: {{{1|¬}}} }}&lt;br /&gt;
 |no&lt;br /&gt;
 |n&lt;br /&gt;
 |f&lt;br /&gt;
 |false&lt;br /&gt;
 |off&lt;br /&gt;
 |0        = {{{no|&amp;lt;!-- null --&amp;gt;}}}&lt;br /&gt;
 |         = {{{blank|{{{no|&amp;lt;!-- null --&amp;gt;}}}}}}&lt;br /&gt;
 |¬        = {{{¬|}}}&lt;br /&gt;
 |yes&lt;br /&gt;
 |y&lt;br /&gt;
 |t&lt;br /&gt;
 |true&lt;br /&gt;
 |on&lt;br /&gt;
 |1        = {{{yes|yes}}}&lt;br /&gt;
 |#default = {{{def|{{{yes|yes}}}}}}&lt;br /&gt;
}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{Documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Use_dmy_dates&amp;diff=1469</id>
		<title>Use dmy dates</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Use_dmy_dates&amp;diff=1469"/>
		<updated>2022-08-12T14:32:24Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ &amp;lt;includeonly&amp;gt;safesubst:&amp;lt;/includeonly&amp;gt;#invoke:Unsubst||date=__DATE__ |$B=&lt;br /&gt;
{{DMCA|Use dmy dates|from|{{{date|}}}}}{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using Use dmy dates template with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Use dmy dates]] with unknown parameter &amp;quot;_VALUE_&amp;quot;|ignoreblank=y| cs1-dates  | date }}}}&amp;lt;noinclude&amp;gt;{{documentation}}&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Short_description/lowercasecheck&amp;diff=1467</id>
		<title>Short description/lowercasecheck</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Short_description/lowercasecheck&amp;diff=1467"/>
		<updated>2022-08-12T14:32:24Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#ifeq:&amp;lt;!--test first character for lower-case letter--&amp;gt;{{#invoke:string|find|1={{{1|}}}|2=^%l|plain=false}}|1&lt;br /&gt;
|&amp;lt;!-- first character is a lower case letter; test against whitelist&lt;br /&gt;
--&amp;gt;{{#switch: {{First word|{{{1|}}}}}&amp;lt;!--begin whitelist--&amp;gt;&lt;br /&gt;
|c. &amp;lt;!--for circa--&amp;gt;&lt;br /&gt;
|gTLD&lt;br /&gt;
|iMac&lt;br /&gt;
|iOS&lt;br /&gt;
|iOS,&lt;br /&gt;
|iPad&lt;br /&gt;
|iPhone&lt;br /&gt;
|iTunes&lt;br /&gt;
|macOS&lt;br /&gt;
|none&lt;br /&gt;
|pH&lt;br /&gt;
|pH-dependent=&amp;lt;!-- end whitelist; short description starts with an allowed lower-case string; whitelist matched; do nothing --&amp;gt; &lt;br /&gt;
|#default=&amp;lt;!-- apply category to track lower-case short descriptions --&amp;gt;{{main other|[[Category:Pages with lower-case short description|{{trim|{{{1|}}}}}]]}}{{Testcases other|{{red|CATEGORY APPLIED}}}}&amp;lt;!-- end whitelist test --&amp;gt;}}&lt;br /&gt;
|&amp;lt;!-- short description does not start with lower-case letter; do nothing; end lower-case test --&amp;gt;&lt;br /&gt;
}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Short_description&amp;diff=1465</id>
		<title>Short description</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Short_description&amp;diff=1465"/>
		<updated>2022-08-12T14:32:24Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#ifeq:{{lc:{{{1|}}}}}|none|&amp;lt;nowiki /&amp;gt;&amp;lt;!--Prevents whitespace issues when used with adjacent newlines--&amp;gt;|&amp;lt;div class=&amp;quot;shortdescription nomobile noexcerpt noprint searchaux&amp;quot; style=&amp;quot;display:none&amp;quot;&amp;gt;{{{1|}}}{{SHORTDESC:{{{1|}}}|{{{2|}}}}}&amp;lt;/div&amp;gt;}}&amp;lt;includeonly&amp;gt;[[Category:{{{pagetype|{{pagetype |defaultns = extended |plural=y}}}}} with short description{{#ifeq:{{{pagetype}}}|Disambiguation pages|s}}]]&amp;lt;/includeonly&amp;gt;&amp;lt;!-- Start tracking&lt;br /&gt;
--&amp;gt;{{#invoke:Check for unknown parameters|check|unknown={{Main other|[[Category:Pages using short description with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Short description]] with unknown parameter &amp;quot;_VALUE_&amp;quot;|ignoreblank=y| 1 | 2 | pagetype | bot |plural }}&amp;lt;!--&lt;br /&gt;
--&amp;gt;{{#ifexpr: {{#invoke:String|len|{{{1|}}}}}&amp;gt;100 | [[Category:{{{pagetype|{{pagetype |defaultns = extended |plural=y}}}}} with long short description]]}}&amp;lt;!--&lt;br /&gt;
--&amp;gt;{{Short description/lowercasecheck|{{{1|}}}}}&amp;lt;!--&lt;br /&gt;
--&amp;gt;{{Main other |{{SDcat |sd={{{1|}}} }} }}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{Documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=SDcat&amp;diff=1463</id>
		<title>SDcat</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=SDcat&amp;diff=1463"/>
		<updated>2022-08-12T14:32:23Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{{#invoke:SDcat |setCat}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Row_numbers&amp;diff=1461</id>
		<title>Row numbers</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Row_numbers&amp;diff=1461"/>
		<updated>2022-08-12T14:32:23Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{{#invoke:row numbers|row_numbers}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Row_indexer&amp;diff=1459</id>
		<title>Row indexer</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Row_indexer&amp;diff=1459"/>
		<updated>2022-08-12T14:32:23Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Template:Row numbers]]&lt;br /&gt;
&lt;br /&gt;
{{R from move}}&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Right&amp;diff=1457</id>
		<title>Right</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Right&amp;diff=1457"/>
		<updated>2022-08-12T14:32:23Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{{{{{|safesubst:}}}#ifeq:{{{1|a}}}|{{{1|b}}}&lt;br /&gt;
|&amp;lt;div style=&amp;quot;float:right;&amp;quot;&amp;gt;{{{1|}}}&amp;lt;/div&amp;gt;&lt;br /&gt;
|style=&amp;quot;text-align:right&amp;quot;{{{{{|safesubst:}}}!}}[[Category:Pages using right with no input arguments]]&lt;br /&gt;
}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Reflist/styles.css&amp;diff=1455</id>
		<title>Reflist/styles.css</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Reflist/styles.css&amp;diff=1455"/>
		<updated>2022-08-12T14:32:22Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Reflist&amp;diff=1453</id>
		<title>Reflist</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Reflist&amp;diff=1453"/>
		<updated>2022-08-12T14:32:22Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;templatestyles src=&amp;quot;Reflist/styles.css&amp;quot; /&amp;gt;&amp;lt;div class=&amp;quot;reflist &amp;lt;!--&lt;br /&gt;
--&amp;gt;{{#if:{{{1|}}}{{{colwidth|}}}|reflist-columns references-column-width}} &amp;lt;!--&lt;br /&gt;
--&amp;gt;{{#switch:{{{liststyle|{{{group|}}}}}}|upper-alpha|upper-roman|lower-alpha|lower-greek|lower-roman=reflist-{{{liststyle|{{{group}}}}}}}} &amp;lt;!--&lt;br /&gt;
--&amp;gt;{{#if:{{{1|}}}|{{#iferror:{{#ifexpr: {{{1|1}}} &amp;gt; 1 }}||{{#switch:{{{1|}}}|1=|2=reflist-columns-2|#default=reflist-columns-3}} }}}}&amp;quot; &amp;lt;!-- end class&lt;br /&gt;
--&amp;gt;{{#if: {{{1|}}}&amp;lt;!-- start style --&amp;gt;&lt;br /&gt;
    | {{#iferror: {{#ifexpr: {{{1|1}}} &amp;gt; 1 }} |style=&amp;quot;column-width: {{{1}}};&amp;quot;}}&lt;br /&gt;
    | {{#if: {{{colwidth|}}}|style=&amp;quot;column-width: {{{colwidth}}};&amp;quot;}}&lt;br /&gt;
    }}&amp;gt;&lt;br /&gt;
{{#tag:references|{{{refs|}}}|group={{{group|}}}|responsive={{#if:{{{1|}}}{{{colwidth|}}}|0|1}}}}&amp;lt;/div&amp;gt;{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using reflist with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Reflist]] with unknown parameter &amp;quot;_VALUE_&amp;quot;|ignoreblank=y| 1 | colwidth | group | liststyle | refs }}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{Documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Pp-semi-indef&amp;diff=1451</id>
		<title>Pp-semi-indef</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Pp-semi-indef&amp;diff=1451"/>
		<updated>2022-08-12T14:32:22Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{{#invoke:Protection banner|main}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;!-- Categories go on the /doc subpage, and interwikis go on Wikidata. --&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Portalbar&amp;diff=1449</id>
		<title>Portalbar</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Portalbar&amp;diff=1449"/>
		<updated>2022-08-12T14:32:22Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[template:portal bar]]&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Portal_bar&amp;diff=1447</id>
		<title>Portal bar</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Portal_bar&amp;diff=1447"/>
		<updated>2022-08-12T14:32:21Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#invoke:Portal bar|main}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;!-- Categories go on the /doc subpage, and interwikis go on Wikidata. --&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Pagetype&amp;diff=1445</id>
		<title>Pagetype</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Pagetype&amp;diff=1445"/>
		<updated>2022-08-12T14:32:21Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{&amp;lt;includeonly&amp;gt;safesubst:&amp;lt;/includeonly&amp;gt;#invoke:pagetype|main}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;!-- Categories go on the /doc subpage, and interwikis go on Wikidata. --&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Ns_has_subpages&amp;diff=1443</id>
		<title>Ns has subpages</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Ns_has_subpages&amp;diff=1443"/>
		<updated>2022-08-12T14:32:21Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{&amp;lt;includeonly&amp;gt;safesubst:&amp;lt;/includeonly&amp;gt;#invoke:Ns has subpages|main}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;!-- Categories go on the /doc subpage and interwikis go on Wikidata. --&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
	<entry>
		<id>https://www.1ok.de/mediawiki/index.php?title=Notelist&amp;diff=1441</id>
		<title>Notelist</title>
		<link rel="alternate" type="text/html" href="https://www.1ok.de/mediawiki/index.php?title=Notelist&amp;diff=1441"/>
		<updated>2022-08-12T14:32:21Z</updated>

		<summary type="html">&lt;p&gt;Timetrave: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{reflist|{{{1|{{{colwidth|}}}}}}|refs={{{refs|{{{notes|}}}}}}|group={{#switch: {{{group|}}}&lt;br /&gt;
    | note&lt;br /&gt;
    | upper-alpha&lt;br /&gt;
    | upper-roman&lt;br /&gt;
    | lower-alpha&lt;br /&gt;
    | lower-greek&lt;br /&gt;
    | lower-roman = {{{group|}}}&lt;br /&gt;
    | #default = lower-alpha&lt;br /&gt;
   }}}}{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using notelist with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Notelist]] with unknown parameter &amp;quot;_VALUE_&amp;quot;|ignoreblank=y| 1 | colwidth | group | notes | refs }}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Timetrave</name></author>
	</entry>
</feed>