
<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://zoophilia.wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Adam52</id>
	<title>Zoophilia Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://zoophilia.wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Adam52"/>
	<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Special:Contributions/Adam52"/>
	<updated>2026-05-07T09:23:42Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.44.0</generator>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Module:Citation/CS1/Whitelist&amp;diff=225</id>
		<title>Module:Citation/CS1/Whitelist</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Module:Citation/CS1/Whitelist&amp;diff=225"/>
		<updated>2020-08-22T20:23:48Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&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;
	nil - these parameters are no longer supported. remove entirely&lt;br /&gt;
	&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local whitelist = {}&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-last&#039;] = true,&lt;br /&gt;
	[&#039;authorlink&#039;] = true,&lt;br /&gt;
	[&#039;author-link&#039;] = true,&lt;br /&gt;
	[&#039;authormask&#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,&lt;br /&gt;
	[&#039;booktitle&#039;] = true,&lt;br /&gt;
	[&#039;book-title&#039;] = true,&lt;br /&gt;
	[&#039;cartography&#039;] = true,&lt;br /&gt;
	[&#039;chapter&#039;] = true,&lt;br /&gt;
	[&#039;chapter-format&#039;] = true,&lt;br /&gt;
	[&#039;chapterurl&#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,&lt;br /&gt;
	[&#039;collaboration&#039;] = true,&lt;br /&gt;
	[&#039;conference&#039;] = true,&lt;br /&gt;
	[&#039;conference-format&#039;] = true,&lt;br /&gt;
	[&#039;conferenceurl&#039;] = true,&lt;br /&gt;
	[&#039;conference-url&#039;] = true,&lt;br /&gt;
	[&#039;contribution&#039;] = true,&lt;br /&gt;
	[&#039;contribution-format&#039;] = true,&lt;br /&gt;
	[&#039;contributionurl&#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-last&#039;] = true,&lt;br /&gt;
	[&#039;contributor-given&#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;degree&#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;displayauthors&#039;] = true,&lt;br /&gt;
	[&#039;display-authors&#039;] = true,&lt;br /&gt;
	[&#039;display-contributors&#039;] = true,&lt;br /&gt;
	[&#039;displayeditors&#039;] = true,&lt;br /&gt;
	[&#039;display-editors&#039;] = true,&lt;br /&gt;
	[&#039;display-interviewers&#039;] = true,&lt;br /&gt;
	[&#039;display-translators&#039;] = true,&lt;br /&gt;
	[&#039;docket&#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&#039;] = true,&lt;br /&gt;
	[&#039;doi-broken-date&#039;] = true,&lt;br /&gt;
	[&#039;doi-inactive-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;editorlink&#039;] = true,&lt;br /&gt;
	[&#039;editor-link&#039;] = true,&lt;br /&gt;
	[&#039;editormask&#039;] = true,&lt;br /&gt;
	[&#039;editor-mask&#039;] = true,&lt;br /&gt;
	[&#039;editors&#039;] = true,&lt;br /&gt;
	[&#039;editor-surname&#039;] = true,&lt;br /&gt;
	[&#039;eissn&#039;] = true,&lt;br /&gt;
	[&#039;EISSN&#039;] = true,&lt;br /&gt;
	[&#039;embargo&#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;event&#039;] = true,&lt;br /&gt;
	[&#039;event-format&#039;] = true,&lt;br /&gt;
	[&#039;eventurl&#039;] = true,&lt;br /&gt;
	[&#039;event-url&#039;] = true,&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,&lt;br /&gt;
	[&#039;id&#039;] = true,&lt;br /&gt;
	[&#039;ID&#039;] = true,&lt;br /&gt;
	[&#039;ignoreisbnerror&#039;] = true,&lt;br /&gt;
	[&#039;ignore-isbn-error&#039;] = true,&lt;br /&gt;
	[&#039;inset&#039;] = true,&lt;br /&gt;
	[&#039;institution&#039;] = true,&lt;br /&gt;
	[&#039;interviewer&#039;] = true,&lt;br /&gt;
	[&#039;interviewer-first&#039;] = true,&lt;br /&gt;
	[&#039;interviewer-last&#039;] = true,&lt;br /&gt;
	[&#039;interviewerlink&#039;] = true,&lt;br /&gt;
	[&#039;interviewer-link&#039;] = true,&lt;br /&gt;
	[&#039;interviewermask&#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;isbn13&#039;] = true,&lt;br /&gt;
	[&#039;ISBN13&#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;lastauthoramp&#039;] = true,&lt;br /&gt;
	[&#039;last-author-amp&#039;] = true,&lt;br /&gt;
	[&#039;laydate&#039;] = true,&lt;br /&gt;
	[&#039;lay-date&#039;] = true,&lt;br /&gt;
	[&#039;laysource&#039;] = true,&lt;br /&gt;
	[&#039;lay-source&#039;] = true,&lt;br /&gt;
	[&#039;lay-format&#039;] = true,&lt;br /&gt;
	[&#039;layurl&#039;] = true,&lt;br /&gt;
	[&#039;lay-url&#039;] = true,&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;mailinglist&#039;] = true,														-- cite mailing list only&lt;br /&gt;
	[&#039;mailing-list&#039;] = true,													-- cite mailing list only&lt;br /&gt;
	[&#039;medium&#039;] = true,&lt;br /&gt;
	[&#039;minutes&#039;] = true,&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-format&#039;] = true,&lt;br /&gt;
	[&#039;newspaper&#039;] = true,&lt;br /&gt;
	[&#039;nocat&#039;] = true,&lt;br /&gt;
	[&#039;no-cat&#039;] = true,&lt;br /&gt;
	[&#039;nopp&#039;] = true,&lt;br /&gt;
	[&#039;no-pp&#039;] = true,&lt;br /&gt;
	[&#039;notracking&#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;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;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;publicationdate&#039;] = true,&lt;br /&gt;
	[&#039;publication-date&#039;] = true,&lt;br /&gt;
	[&#039;publicationplace&#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;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-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;season&#039;] = true,&lt;br /&gt;
	[&#039;section&#039;] = true,&lt;br /&gt;
	[&#039;section-format&#039;] = true,&lt;br /&gt;
	[&#039;sectionurl&#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;serieslink&#039;] = true,&lt;br /&gt;
	[&#039;series-link&#039;] = true,&lt;br /&gt;
	[&#039;seriesno&#039;] = true,&lt;br /&gt;
	[&#039;series-no&#039;] = true,&lt;br /&gt;
	[&#039;seriesnumber&#039;] = true,&lt;br /&gt;
	[&#039;series-number&#039;] = true,&lt;br /&gt;
	[&#039;series-separator&#039;] = true,&lt;br /&gt;
	[&#039;ssrn&#039;] = true,&lt;br /&gt;
	[&#039;SSRN&#039;] = true,&lt;br /&gt;
	[&#039;subject&#039;] = true,&lt;br /&gt;
	[&#039;subjectlink&#039;] = true,&lt;br /&gt;
	[&#039;subject-link&#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,&lt;br /&gt;
	[&#039;timecaption&#039;] = true,&lt;br /&gt;
	[&#039;time-caption&#039;] = true,&lt;br /&gt;
	[&#039;title&#039;] = true,&lt;br /&gt;
	[&#039;titlelink&#039;] = true,&lt;br /&gt;
	[&#039;title-link&#039;] = true,&lt;br /&gt;
	[&#039;transcript&#039;] = true,&lt;br /&gt;
	[&#039;transcript-format&#039;] = true,&lt;br /&gt;
	[&#039;transcripturl&#039;] = true,&lt;br /&gt;
	[&#039;transcript-url&#039;] = true,&lt;br /&gt;
	[&#039;translator&#039;] = true,&lt;br /&gt;
	[&#039;translator-first&#039;] = true,&lt;br /&gt;
	[&#039;translator-last&#039;] = true,&lt;br /&gt;
	[&#039;translator-given&#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-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-last#&#039;] = true,&lt;br /&gt;
	[&#039;author#-last&#039;] = true,&lt;br /&gt;
	[&#039;author-link#&#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-mask#&#039;] = true,&lt;br /&gt;
	[&#039;author#mask&#039;] = true,&lt;br /&gt;
	[&#039;author#-mask&#039;] = true,&lt;br /&gt;
	[&#039;authormask#&#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-last#&#039;] = true,&lt;br /&gt;
	[&#039;contributor#-last&#039;] = true,&lt;br /&gt;
	[&#039;contributor-given#&#039;] = true,&lt;br /&gt;
	[&#039;contributor#-given&#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-link#&#039;] = true,&lt;br /&gt;
	[&#039;editor#link&#039;] = true,&lt;br /&gt;
	[&#039;editor#-link&#039;] = true,&lt;br /&gt;
	[&#039;editorlink#&#039;] = true,&lt;br /&gt;
	[&#039;editor-mask#&#039;] = true,&lt;br /&gt;
	[&#039;editor#mask&#039;] = true,&lt;br /&gt;
	[&#039;editor#-mask&#039;] = true,&lt;br /&gt;
	[&#039;editormask#&#039;] = true,&lt;br /&gt;
	[&#039;editor#-surname&#039;] = true,&lt;br /&gt;
	[&#039;editor-surname#&#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-last#&#039;] = true,&lt;br /&gt;
	[&#039;interviewer#-last&#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#-link&#039;] = true,&lt;br /&gt;
	[&#039;subjectlink#&#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-last#&#039;] = true,&lt;br /&gt;
	[&#039;translator#-last&#039;] = true,&lt;br /&gt;
	[&#039;translator-given#&#039;] = true,&lt;br /&gt;
	[&#039;translator#-given&#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/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,														-- cite arxiv only&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;
		},&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;
This is an experiment that attempts to use validate() and a limited list of valid parameters to validate the&lt;br /&gt;
parameters provided in a cite arxiv, cite biorxiv, or cite citeseerx templates.  These parameters are common to&lt;br /&gt;
all three templates&lt;br /&gt;
&lt;br /&gt;
Same conventions for true/false/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-last&#039;] = true,&lt;br /&gt;
	[&#039;authorlink&#039;] = true,&lt;br /&gt;
	[&#039;author-link&#039;] = true,&lt;br /&gt;
	[&#039;authormask&#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;displayauthors&#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;lastauthoramp&#039;] = true,&lt;br /&gt;
	[&#039;last-author-amp&#039;] = true,&lt;br /&gt;
	[&#039;mode&#039;] = true,&lt;br /&gt;
	[&#039;name-list-format&#039;] = true,&lt;br /&gt;
	[&#039;nocat&#039;] = true,&lt;br /&gt;
	[&#039;no-cat&#039;] = true,&lt;br /&gt;
	[&#039;notracking&#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;url&#039;] = true,&lt;br /&gt;
	[&#039;URL&#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-last#&#039;] = true,&lt;br /&gt;
	[&#039;author#-last&#039;] = true,&lt;br /&gt;
	[&#039;author-link#&#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-mask#&#039;] = true,&lt;br /&gt;
	[&#039;author#mask&#039;] = true,&lt;br /&gt;
	[&#039;author#-mask&#039;] = true,&lt;br /&gt;
	[&#039;authormask#&#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/nil as above.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local unique_arguments = {&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;episodelink&#039;] = true,													-- aliases of |title-link=&lt;br /&gt;
		[&#039;episode-link&#039;] = true,&lt;br /&gt;
		[&#039;network&#039;] = true,&lt;br /&gt;
		[&#039;station&#039;] = true,&lt;br /&gt;
		},&lt;br /&gt;
	map = {&lt;br /&gt;
		[&#039;map&#039;] = true,&lt;br /&gt;
		[&#039;map-format&#039;] = true,&lt;br /&gt;
		[&#039;mapurl&#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;
	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;episodelink&#039;] = true,													-- aliases of |title-link=&lt;br /&gt;
		[&#039;episode-link&#039;] = true,&lt;br /&gt;
		[&#039;network&#039;] = true,&lt;br /&gt;
		[&#039;station&#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>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Module:Citation/CS1/Utilities&amp;diff=223</id>
		<title>Module:Citation/CS1/Utilities</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Module:Citation/CS1/Utilities&amp;diff=223"/>
		<updated>2020-08-22T20:23:48Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
local z = {&lt;br /&gt;
	error_categories = {};														-- for categorizing citations that contain errors&lt;br /&gt;
	error_ids = {};&lt;br /&gt;
	message_tail = {};&lt;br /&gt;
	maintenance_cats = {};														-- for categorizing citations that aren&#039;t erroneous per se, but could use a little work&lt;br /&gt;
	properties_cats = {};														-- for categorizing citations based on certain properties, language of source for instance&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; 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.&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.&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; M A K E _ W I K I L I N K &amp;gt;----------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Makes a wikilink; when bot link and display text is provided, returns a wikilink in the form [[L|D]]; if only&lt;br /&gt;
link is provided, returns a wikilink in the form [[L]]; if neither are provided or link is omitted, returns an&lt;br /&gt;
empty string.&lt;br /&gt;
&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local function make_wikilink (link, display)&lt;br /&gt;
	if is_set (link) then&lt;br /&gt;
		if is_set (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;
	else&lt;br /&gt;
		return &#039;&#039;;&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S E T _ E R R O R &amp;gt;--------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Sets an error condition and returns the appropriate error message.  The actual placement of the error message in the output is&lt;br /&gt;
the responsibility of the calling function.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function set_error( 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 &amp;quot;&amp;quot;;&lt;br /&gt;
	suffix = suffix or &amp;quot;&amp;quot;;&lt;br /&gt;
	&lt;br /&gt;
	if error_state == nil then&lt;br /&gt;
		error( cfg.messages[&#039;undefined_error&#039;] );								-- because missing error handler in Module:Citation/CS1/Configuration&lt;br /&gt;
	elseif is_set( error_state.category ) then&lt;br /&gt;
		table.insert( z.error_categories, error_state.category );&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[ error_id ] = true;&lt;br /&gt;
	if in_array( error_id, { &#039;bare_url_missing_title&#039;, &#039;trans_missing_title&#039; } )&lt;br /&gt;
			and z.error_ids[&#039;citation_missing_title&#039;] then&lt;br /&gt;
		return &#039;&#039;, false;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	message = table.concat({ prefix, message, suffix });&lt;br /&gt;
	&lt;br /&gt;
	if raw == true then&lt;br /&gt;
		return message, error_state.hidden;&lt;br /&gt;
	end		&lt;br /&gt;
		&lt;br /&gt;
	return error_comment( message, error_state.hidden );&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 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.maintenance_cats 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.maintenance_cats.&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.maintenance_cats&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.maintenance_cats, 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; 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&lt;br /&gt;
		return str;&lt;br /&gt;
	else&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;
		-- Remove newlines as they break italics.&lt;br /&gt;
		return str:gsub( &#039;\n&#039;, &#039; &#039; );&lt;br /&gt;
	end&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; 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;
		local error_str = &amp;quot;&amp;quot;;&lt;br /&gt;
		for _, k in ipairs( error_list ) do&lt;br /&gt;
			if error_str ~= &amp;quot;&amp;quot; then error_str = error_str .. cfg.messages[&#039;parameter-separator&#039;] end&lt;br /&gt;
			error_str = error_str .. wrap_style (&#039;parameter&#039;, k);&lt;br /&gt;
		end&lt;br /&gt;
		if #error_list &amp;gt; 1 then&lt;br /&gt;
			error_str = error_str .. cfg.messages[&#039;parameter-final-separator&#039;];&lt;br /&gt;
		else&lt;br /&gt;
			error_str = error_str .. cfg.messages[&#039;parameter-pair-separator&#039;];&lt;br /&gt;
		end&lt;br /&gt;
		error_str = error_str .. wrap_style (&#039;parameter&#039;, selected);&lt;br /&gt;
		table.insert( z.message_tail, { set_error( error_condition, {error_str}, true ) } );&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 white space 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 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 white space 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 wililink; 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;
--	L = L and mw.text.trim (L, &#039;%s|&#039;);&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;
	is_set = is_set,															-- exported functions&lt;br /&gt;
	in_array = in_array,&lt;br /&gt;
	substitute = substitute,&lt;br /&gt;
	error_comment = error_comment,&lt;br /&gt;
	set_error = set_error,&lt;br /&gt;
	select_one = select_one,&lt;br /&gt;
	add_maint_cat = add_maint_cat,&lt;br /&gt;
	wrap_style = wrap_style,&lt;br /&gt;
	safe_for_italics = safe_for_italics,&lt;br /&gt;
	remove_wiki_link = remove_wiki_link,&lt;br /&gt;
	is_wikilink = is_wikilink,&lt;br /&gt;
	make_wikilink = make_wikilink,&lt;br /&gt;
	set_selected_modules = set_selected_modules,&lt;br /&gt;
	strip_apostrophe_markup = strip_apostrophe_markup,&lt;br /&gt;
	z = z,																		-- exported table&lt;br /&gt;
	}&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Module:Citation/CS1/Identifiers&amp;diff=221</id>
		<title>Module:Citation/CS1/Identifiers</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Module:Citation/CS1/Identifiers&amp;diff=221"/>
		<updated>2020-08-22T20:23:48Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&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 is_set, in_array, set_error, select_one, add_maint_cat, substitute, make_wikilink;	-- functions in Module:Citation/CS1/Utilities&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;&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; 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 );&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;
	if not (cfg.use_identifier_redirects and is_set (options.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 (options.q);						-- if wikidata has an article title for this wiki, get it;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local label_link = (cfg.use_identifier_redirects and is_set (options.redirect) and options.redirect) or wd_article or options.link;&lt;br /&gt;
&lt;br /&gt;
	return table.concat	({&lt;br /&gt;
		make_wikilink (label_link, 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;
]]&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;
	if not (cfg.use_identifier_redirects and is_set (options.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 (options.q);						-- if wikidata has an article title for this wiki, get it;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local label_link = (cfg.use_identifier_redirects and is_set (options.redirect) and options.redirect) or wd_article or options.link;&lt;br /&gt;
&lt;br /&gt;
	return table.concat (&lt;br /&gt;
		{&lt;br /&gt;
		make_wikilink (label_link, 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 Latn 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 |embargo= against today&#039;s date.  If embargo date is&lt;br /&gt;
in the future, returns the content of |embargo=; otherwise, returns and empty string because the embargo has expired or because&lt;br /&gt;
|embargo= 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, good2, todays_date;&lt;br /&gt;
		good1, embargo_date = pcall( lang.formatDate, lang, &#039;U&#039;, embargo );&lt;br /&gt;
		good2, todays_date = pcall( lang.formatDate, lang, &#039;U&#039; );&lt;br /&gt;
	&lt;br /&gt;
		if good1 and good2 then													-- if embargo date and today&#039;s date are good dates&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;
				add_maint_cat (&#039;embargo&#039;)&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;;																	-- |embargo= 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-Engish 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_biorxiv_date (biorxiv_date)&lt;br /&gt;
	local good1, good2;&lt;br /&gt;
	local biorxiv_ts, tomorrow_ts;												-- to hold unix time stamps 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 timesatmp &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;
		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 time stamp&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, issbn/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;
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;
--============================&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 9108 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;
local function arxiv (id, class)&lt;br /&gt;
	local handler = cfg.id_handlers[&#039;ARXIV&#039;];&lt;br /&gt;
	local year, month, version;&lt;br /&gt;
	local err_cat = 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 9108-0703 format w/ &amp;amp; w/o 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_cat = 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 w/ &amp;amp; w/o 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 --or									-- when year is 07, is month invalid (before April)?&lt;br /&gt;
				err_cat = 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 w/ &amp;amp; w/o 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_cat = true;													-- flag for error message&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
	else&lt;br /&gt;
		err_cat = true;															-- not a recognized format; flag for error message&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	err_cat = err_cat and table.concat ({&#039; &#039;, set_error (&#039;bad_arxiv&#039;)}) or &#039;&#039;;	-- set error message if flag is true&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}) .. err_cat;&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;
			text = table.concat ({text, &#039; &#039;, set_error (&#039;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 (id, access)&lt;br /&gt;
	local handler = cfg.id_handlers[&#039;BIBCODE&#039;];&lt;br /&gt;
	local err_type;&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 its 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;
		text = text .. &#039; &#039; .. set_error( &#039;bad_bibcode&#039;, {err_type});&lt;br /&gt;
	end&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(id)&lt;br /&gt;
	local handler = cfg.id_handlers[&#039;BIORXIV&#039;];&lt;br /&gt;
	local err_cat = 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 .. &#039;-&#039; .. m .. &#039;-&#039; .. d) then	-- validate the encoded date; TODO: don&#039;t ignore leapyear 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_cat = 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;
	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}) .. (err_cat and (&#039; &#039; .. set_error( &#039;bad_biorxiv&#039;)) or &#039;&#039;);&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;
local function citeseerx (id)&lt;br /&gt;
	local handler = cfg.id_handlers[&#039;CITESEERX&#039;];&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;
		text = text .. &#039; &#039; .. set_error( &#039;bad_citeseerx&#039; );&lt;br /&gt;
	end&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(id, inactive, access)&lt;br /&gt;
	local cat = &amp;quot;&amp;quot;&lt;br /&gt;
	local handler = cfg.id_handlers[&#039;DOI&#039;];&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= 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;
			table.insert( z.error_categories, &#039;Pages with DOIs inactive as of &#039; .. inactive_year .. &#039; &#039; .. inactive_month);	-- use inactive month in category name&lt;br /&gt;
		elseif is_set(inactive_year) then&lt;br /&gt;
			table.insert( z.error_categories, &#039;Pages with DOIs inactive as of &#039; .. inactive_year);&lt;br /&gt;
		else&lt;br /&gt;
			table.insert( z.error_categories, &#039;Pages with inactive DOIs&#039;);		-- when inactive doesn&#039;t contain a recognizable date&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;
	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}) .. (inactive or &#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
	local registrant = id:match (&#039;^10%.([^/]+)/[^%s–]-[^%.,]$&#039;);				-- registrant set when doi has the proper basic form&lt;br /&gt;
	&lt;br /&gt;
	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+); accecpts: 10000–39999&lt;br /&gt;
		&#039;^[^1-4]%d%d%d%d$&#039;,														-- 5 digits without subcode (0xxxx, 40000+); accecpts: 10000–49999&lt;br /&gt;
		&#039;^[^1-9]%d%d%d%.%d%d*$&#039;,												-- 4 digits with subcode (0xxx); accecpts: 1000–9999&lt;br /&gt;
		&#039;^[^1-9]%d%d%d$&#039;,														-- 4 digits without subcode (0xxx); accecpts: 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;%s&#039;,																	-- any space character in registrant&lt;br /&gt;
		}&lt;br /&gt;
	&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;
				cat = &#039; &#039; .. set_error (&#039;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;
		cat = &#039; &#039; .. set_error (&#039;bad_doi&#039;);										-- invalid directory or malformed&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return text .. cat &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 anallowed 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(id, access)&lt;br /&gt;
	local handler = cfg.id_handlers[&#039;HDL&#039;];&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 fwd slash, must not contain spaces, endashes, and must not end with period or comma&lt;br /&gt;
		text = text .. &#039; &#039; .. set_error( &#039;bad_hdl&#039; );&lt;br /&gt;
	end&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( isbn_str )&lt;br /&gt;
	if nil ~= isbn_str:match(&amp;quot;[^%s-0-9X]&amp;quot;) then&lt;br /&gt;
		return 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;
	isbn_str = isbn_str:gsub( &amp;quot;-&amp;quot;, &amp;quot;&amp;quot; ):gsub( &amp;quot; &amp;quot;, &amp;quot;&amp;quot; );						-- remove hyphens and spaces&lt;br /&gt;
	local len = isbn_str:len();&lt;br /&gt;
 &lt;br /&gt;
	if len ~= 10 and len ~= 13 then&lt;br /&gt;
		return 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 isbn_str:match( &amp;quot;^%d*X?$&amp;quot; ) == nil then								-- fail if isbn_str has &#039;X&#039; anywhere but last position&lt;br /&gt;
			return false, cfg.err_msg_supl.form;									&lt;br /&gt;
		end&lt;br /&gt;
		return is_valid_isxn(isbn_str, 10), cfg.err_msg_supl.check;&lt;br /&gt;
	else&lt;br /&gt;
		if isbn_str:match( &amp;quot;^%d+$&amp;quot; ) == nil then&lt;br /&gt;
			return false, cfg.err_msg_supl.char;								-- fail if isbn13 is not all digits&lt;br /&gt;
		end&lt;br /&gt;
		if isbn_str:match( &amp;quot;^97[89]%d*$&amp;quot; ) == nil then&lt;br /&gt;
			return false, cfg.err_msg_supl.prefix;								-- fail when isbn13 does not begin with 978 or 979&lt;br /&gt;
		end&lt;br /&gt;
		if isbn_str:match (&#039;^9790&#039;) then&lt;br /&gt;
			return false, cfg.err_msg_supl.group;								-- group identifier &#039;0&#039; is reserved to ismn&lt;br /&gt;
		end&lt;br /&gt;
		return is_valid_isxn_13 (isbn_str), 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 M A Z O 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 isbn10, if mixed and first character is a digit.&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(id, domain)&lt;br /&gt;
	local err_cat = &amp;quot;&amp;quot;&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_cat = &#039; &#039; .. set_error (&#039;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 isbn( id ) then													-- see if asin value is isbn10&lt;br /&gt;
				add_maint_cat (&#039;ASIN&#039;);&lt;br /&gt;
			elseif not is_set (err_cat) then&lt;br /&gt;
				err_cat = &#039; &#039; .. set_error (&#039;bad_asin&#039;);						-- asin is not isbn10&lt;br /&gt;
			end&lt;br /&gt;
		elseif not id:match(&amp;quot;^%u[%d%u]+$&amp;quot;) then&lt;br /&gt;
			err_cat = &#039; &#039; .. set_error (&#039;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) then &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;au&#039;, &#039;br&#039;, &#039;mx&#039;}) then	-- Australia, Brazil, Mexico&lt;br /&gt;
		domain = &amp;quot;com.&amp;quot; .. domain;&lt;br /&gt;
	end&lt;br /&gt;
	local handler = cfg.id_handlers[&#039;ASIN&#039;];&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}) .. err_cat;&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 begining 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;
]]&lt;br /&gt;
&lt;br /&gt;
local function ismn (id)&lt;br /&gt;
	local handler = cfg.id_handlers[&#039;ISMN&#039;];&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( &amp;quot;[%s-–]&amp;quot;, &amp;quot;&amp;quot; );													-- strip spaces, hyphens, and endashes from the ismn&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 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;
 	local label_link = (cfg.use_identifier_redirects and is_set (handler.redirect) and handler.redirect) or wd_article or handler.link;	-- because no place to link to yet&lt;br /&gt;
&lt;br /&gt;
	text = table.concat (														-- because no place to link to yet&lt;br /&gt;
		{&lt;br /&gt;
		make_wikilink (label_link, 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;
		text = text .. &#039; &#039; .. set_error( &#039;bad_ismn&#039; )							-- add 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(id, e)&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 handler;&lt;br /&gt;
	local text;&lt;br /&gt;
	local valid_issn = true;&lt;br /&gt;
	&lt;br /&gt;
	if e then&lt;br /&gt;
		 handler = cfg.id_handlers[&#039;EISSN&#039;];&lt;br /&gt;
	else&lt;br /&gt;
		 handler = cfg.id_handlers[&#039;ISSN&#039;];&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	id=id:gsub( &amp;quot;[%s-–]&amp;quot;, &amp;quot;&amp;quot; );													-- strip spaces, hyphens, and endashes from the issn&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, use the 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 false == valid_issn then&lt;br /&gt;
		text = text .. &#039; &#039; .. set_error( &#039;bad_issn&#039;, e and &#039;e&#039; or &#039;&#039; )			-- add an error message if the issn 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; 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 (id)&lt;br /&gt;
	local handler = cfg.id_handlers[&#039;JFM&#039;];&lt;br /&gt;
	local id_num;&lt;br /&gt;
	local err_cat = &#039;&#039;;&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;
		add_maint_cat (&#039;jfm_format&#039;);&lt;br /&gt;
	else																		-- plain number without mr 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;
		err_cat = &#039; &#039; .. set_error( &#039;bad_jfm&#039; );								-- set an 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, encode=handler.encode}) .. err_cat;&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 lower case alpha&lt;br /&gt;
length = 10 then lccn[1] and lccn[2] are both lower case alpha or both digits&lt;br /&gt;
length = 11 then lccn[1] is lower case alpha, lccn[2] and lccn[3] are both lower case alpha or both digits&lt;br /&gt;
length = 12 then lccn[1] and lccn[2] are both lower case alpha&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function lccn(lccn)&lt;br /&gt;
	local handler = cfg.id_handlers[&#039;LCCN&#039;];&lt;br /&gt;
	local err_cat = &#039;&#039;;															-- 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_cat = &#039; &#039; .. set_error( &#039;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_cat = &#039; &#039; .. set_error( &#039;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_cat = &#039; &#039; .. set_error( &#039;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_cat = &#039; &#039; .. set_error( &#039;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_cat = &#039; &#039; .. set_error( &#039;bad_lccn&#039; );							-- no match, set an error message&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		err_cat = &#039; &#039; .. set_error( &#039;bad_lccn&#039; );								-- wrong length, set an error message&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if not is_set (err_cat) and nil ~= lccn:find (&#039;%s&#039;) then&lt;br /&gt;
		err_cat = &#039; &#039; .. set_error( &#039;bad_lccn&#039; );								-- lccn contains a space, set an 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=lccn,separator=handler.separator, encode=handler.encode}) .. err_cat;&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 (id)&lt;br /&gt;
	local handler = cfg.id_handlers[&#039;MR&#039;];&lt;br /&gt;
	local id_num;&lt;br /&gt;
	local id_len;&lt;br /&gt;
	local err_cat = &#039;&#039;;&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;
		add_maint_cat (&#039;mr_format&#039;);&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;
		err_cat = &#039; &#039; .. set_error( &#039;bad_mr&#039; );									-- set an 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, encode=handler.encode}) .. err_cat;&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 (id)&lt;br /&gt;
	local handler = cfg.id_handlers[&#039;OCLC&#039;];&lt;br /&gt;
	local number;&lt;br /&gt;
	local err_msg = &#039;&#039;;															-- empty string for concatenation&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;														-- contrain 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;														-- contrain 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;
		err_msg = &#039; &#039; .. set_error( &#039;bad_oclc&#039; )								-- add an error message if the id is malformed&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, separator=handler.separator, encode=handler.encode}) .. err_msg;&lt;br /&gt;
&lt;br /&gt;
	return text;&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(id, access)&lt;br /&gt;
	local code;&lt;br /&gt;
	local handler = cfg.id_handlers[&#039;OL&#039;];&lt;br /&gt;
	local ident;&lt;br /&gt;
	&lt;br /&gt;
	ident, code = id:gsub(&#039;^OL&#039;, &#039;&#039;):match(&amp;quot;^(%d+([AMW]))$&amp;quot;);					-- optional OL prefix followed immediately by digits followed by &#039;A&#039;, &#039;M&#039;, or &#039;W&#039;; remove OL prefix&lt;br /&gt;
&lt;br /&gt;
	if not is_set (ident) then													-- if malformed return an error&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 .. &#039;OL&#039;,&lt;br /&gt;
			id=id, separator=handler.separator,	encode = handler.encode,&lt;br /&gt;
			access = access}) .. &#039; &#039; .. set_error( &#039;bad_ol&#039; );&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	id = ident;																	-- use ident without the optional OL prefix (it has been removed)&lt;br /&gt;
	&lt;br /&gt;
	if ( code == &amp;quot;A&amp;quot; ) then&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 .. &#039;authors/OL&#039;,&lt;br /&gt;
			id=id, separator=handler.separator,	encode = handler.encode,&lt;br /&gt;
			access = access})&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if ( code == &amp;quot;M&amp;quot; ) then&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 .. &#039;books/OL&#039;,&lt;br /&gt;
			id=id, separator=handler.separator,	encode = handler.encode,&lt;br /&gt;
			access = access})&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if ( code == &amp;quot;W&amp;quot; ) then&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 .. &#039;works/OL&#039;,&lt;br /&gt;
			id=id, separator=handler.separator,	encode = handler.encode,&lt;br /&gt;
			access = access})&lt;br /&gt;
	end&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(id, embargo)&lt;br /&gt;
	local handler = cfg.id_handlers[&#039;PMC&#039;];&lt;br /&gt;
	local err_cat = &#039;&#039;;															-- presume that PMC is valid&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;
		add_maint_cat (&#039;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_cat = &#039; &#039; .. set_error( &#039;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_cat = &#039; &#039; .. set_error( &#039;bad_pmc&#039; );								-- set an error message&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if is_set (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 (handler.link, handler.label),&lt;br /&gt;
			handler.separator,&lt;br /&gt;
			id,&lt;br /&gt;
			err_cat&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}) .. err_cat;&lt;br /&gt;
	end&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(id)&lt;br /&gt;
	local handler = cfg.id_handlers[&#039;PMID&#039;];&lt;br /&gt;
	local err_cat = &#039;&#039;;															-- presume that PMID is valid&lt;br /&gt;
	&lt;br /&gt;
	if id:match(&amp;quot;[^%d]&amp;quot;) then													-- if PMID has anything but digits&lt;br /&gt;
		err_cat = &#039; &#039; .. set_error( &#039;bad_pmid&#039; );								-- set an error message&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;
			err_cat = &#039; &#039; .. set_error( &#039;bad_pmid&#039; );							-- set an error message&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}) .. err_cat;&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 (id, access)&lt;br /&gt;
	local handler = cfg.id_handlers[&#039;S2CID&#039;];&lt;br /&gt;
	local err_cat = &#039;&#039;;															-- presume that S2CID is valid&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;
			err_cat = &#039; &#039; .. set_error( &#039;bad_s2cid&#039; );							-- set an error message&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
	else																		-- when id format incorrect&lt;br /&gt;
		err_cat = &#039; &#039; .. set_error( &#039;bad_s2cid&#039; );								-- set an 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:gsub (&#039;%.%a%a&#039;, &#039;&#039;), separator=handler.separator, encode=handler.encode, access=access}) .. err_cat;&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 isbn10; 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;
]]&lt;br /&gt;
&lt;br /&gt;
local function sbn (id)&lt;br /&gt;
	local check;&lt;br /&gt;
	local err_type = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
	if nil ~= id:match(&amp;quot;[^%s-0-9X]&amp;quot;) then&lt;br /&gt;
		return 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;
	id=id:gsub( &amp;quot;[%s-]&amp;quot;, &amp;quot;&amp;quot; );													-- strip spaces and hyphens from the sbn&lt;br /&gt;
&lt;br /&gt;
	if  9 ~= id:len() then&lt;br /&gt;
		return false, cfg.err_msg_supl.length;									-- fail if incorrect length&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if id:match( &amp;quot;^%d*X?$&amp;quot; ) == nil then										-- fail if sbn has &#039;X&#039; anywhere but last position&lt;br /&gt;
		return false, cfg.err_msg_supl.form;									&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return is_valid_isxn(&#039;0&#039; .. id, 10), cfg.err_msg_supl.check;				-- prefix sbn with &#039;0&#039; and validate as isbn10&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 (id)&lt;br /&gt;
	local handler = cfg.id_handlers[&#039;SSRN&#039;];&lt;br /&gt;
	local err_cat = &#039;&#039;;															-- presume that SSRN is valid&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;
			err_cat = &#039; &#039; .. set_error( &#039;bad_ssrn&#039; );							-- set an error message&lt;br /&gt;
		end&lt;br /&gt;
	else																		-- when id format incorrect&lt;br /&gt;
		err_cat = &#039; &#039; .. set_error( &#039;bad_ssrn&#039; );								-- set an 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, access=handler.access}) .. err_cat;&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 (id)&lt;br /&gt;
	local handler = cfg.id_handlers[&#039;USENETID&#039;];&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;
		text = text .. &#039; &#039; .. set_error( &#039;bad_usenet_id&#039; )						-- add an error message if the message id 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; 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 (id)&lt;br /&gt;
	local handler = cfg.id_handlers[&#039;ZBL&#039;];&lt;br /&gt;
	local err_cat = &#039;&#039;;&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;
		add_maint_cat (&#039;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;
		err_cat = &#039; &#039; .. set_error( &#039;bad_zbl&#039; );								-- no, set an 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, encode=handler.encode}) .. err_cat;&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; B U I L D _ I D _ L I S T &amp;gt;--------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Takes a table of IDs created by extract_ids() and turns it into a table of formatted ID outputs.&lt;br /&gt;
&lt;br /&gt;
inputs:&lt;br /&gt;
	id_list – table of identifiers built by extract_ids()&lt;br /&gt;
	options – table of various template parameter values used to modify some manually handled identifiers&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function build_id_list( id_list, options )&lt;br /&gt;
	local new_list, handler = {};&lt;br /&gt;
&lt;br /&gt;
	local function fallback(k) return { __index = function(t,i) return cfg.id_handlers[k][i] end } end;&lt;br /&gt;
	&lt;br /&gt;
	for k, v in pairs( id_list ) do												-- k is uc identifier name as index to cfg.id_handlers; e.g. cfg.id_handlers[&#039;ISBN&#039;], v is a table&lt;br /&gt;
		-- fallback to read-only cfg&lt;br /&gt;
		handler = setmetatable( { [&#039;id&#039;] = v, [&#039;access&#039;] = options.IdAccessLevels[k] }, fallback(k) );&lt;br /&gt;
&lt;br /&gt;
		if handler.mode == &#039;external&#039; then&lt;br /&gt;
			table.insert( new_list, {handler.label, external_link_id( handler ) } );&lt;br /&gt;
		elseif handler.mode == &#039;internal&#039; then&lt;br /&gt;
			table.insert( new_list, {handler.label, internal_link_id( handler ) } );&lt;br /&gt;
		elseif handler.mode ~= &#039;manual&#039; then&lt;br /&gt;
			error( cfg.messages[&#039;unknown_ID_mode&#039;] );&lt;br /&gt;
		elseif k == &#039;ARXIV&#039; then&lt;br /&gt;
			table.insert( new_list, {handler.label, arxiv( v, options.Class ) } ); &lt;br /&gt;
		elseif k == &#039;ASIN&#039; then&lt;br /&gt;
			table.insert( new_list, {handler.label, asin( v, options.ASINTLD ) } ); &lt;br /&gt;
		elseif k == &#039;BIBCODE&#039; then&lt;br /&gt;
			table.insert( new_list, {handler.label, bibcode( v, handler.access ) } );&lt;br /&gt;
		elseif k == &#039;BIORXIV&#039; then&lt;br /&gt;
			table.insert( new_list, {handler.label, biorxiv( v ) } );&lt;br /&gt;
		elseif k == &#039;CITESEERX&#039; then&lt;br /&gt;
			table.insert( new_list, {handler.label, citeseerx( v ) } );&lt;br /&gt;
		elseif k == &#039;DOI&#039; then&lt;br /&gt;
			table.insert( new_list, {handler.label, doi( v, options.DoiBroken, handler.access ) } );&lt;br /&gt;
		elseif k == &#039;EISSN&#039; then&lt;br /&gt;
			table.insert( new_list, {handler.label, issn( v, true ) } );		-- true distinguishes eissn from issn&lt;br /&gt;
		elseif k == &#039;HDL&#039; then&lt;br /&gt;
			table.insert( new_list, {handler.label, hdl( v, handler.access ) } );&lt;br /&gt;
		elseif k == &#039;ISBN&#039; then&lt;br /&gt;
			local ISBN = internal_link_id( handler );&lt;br /&gt;
			local check;&lt;br /&gt;
			local err_type = &#039;&#039;;&lt;br /&gt;
			check, err_type = isbn( v );&lt;br /&gt;
			if not check then&lt;br /&gt;
				if is_set(options.IgnoreISBN) then								-- ISBN is invalid; if |ignore-isbn-error= set&lt;br /&gt;
					add_maint_cat (&#039;ignore_isbn_err&#039;);							-- ad a maint category&lt;br /&gt;
				else&lt;br /&gt;
					ISBN = ISBN .. set_error( &#039;bad_isbn&#039;, {err_type}, false, &amp;quot; &amp;quot;, &amp;quot;&amp;quot; );	-- else display an error message&lt;br /&gt;
				end&lt;br /&gt;
			elseif is_set(options.IgnoreISBN) then								-- ISBN is OK; if |ignore-isbn-error= set&lt;br /&gt;
				add_maint_cat (&#039;ignore_isbn_err&#039;);								-- because |ignore-isbn-error= unnecessary&lt;br /&gt;
			end&lt;br /&gt;
			table.insert( new_list, {handler.label, ISBN } );				&lt;br /&gt;
		elseif k == &#039;ISMN&#039; then&lt;br /&gt;
			table.insert( new_list, {handler.label, ismn( v ) } );&lt;br /&gt;
		elseif k == &#039;ISSN&#039; then&lt;br /&gt;
			table.insert( new_list, {handler.label, issn( v ) } );&lt;br /&gt;
		elseif k == &#039;JFM&#039; then&lt;br /&gt;
			table.insert( new_list, {handler.label, jfm( v ) } );&lt;br /&gt;
		elseif k == &#039;LCCN&#039; then&lt;br /&gt;
			table.insert( new_list, {handler.label, lccn( v ) } );&lt;br /&gt;
		elseif k == &#039;MR&#039; then&lt;br /&gt;
			table.insert( new_list, {handler.label, mr( v ) } );&lt;br /&gt;
		elseif k == &#039;OCLC&#039; then&lt;br /&gt;
			table.insert( new_list, {handler.label, oclc( v ) } );&lt;br /&gt;
		elseif k == &#039;OL&#039; or k == &#039;OLA&#039; then&lt;br /&gt;
			table.insert( new_list, {handler.label, openlibrary( v, handler.access ) } );&lt;br /&gt;
		elseif k == &#039;PMC&#039; then&lt;br /&gt;
			table.insert( new_list, {handler.label, pmc( v, options.Embargo ) } );&lt;br /&gt;
		elseif k == &#039;PMID&#039; then&lt;br /&gt;
			table.insert( new_list, {handler.label, pmid( v ) } );&lt;br /&gt;
		elseif k == &#039;S2CID&#039; then&lt;br /&gt;
			table.insert( new_list, {handler.label, s2cid( v, handler.access ) } );&lt;br /&gt;
		elseif k == &#039;SBN&#039; then&lt;br /&gt;
			local SBN = internal_link_id (handler);&lt;br /&gt;
			local check;														-- boolean validation result&lt;br /&gt;
			local err_type = &#039;&#039;;&lt;br /&gt;
			check, err_type = sbn (v);&lt;br /&gt;
			if not check then&lt;br /&gt;
				SBN = SBN .. set_error( &#039;bad_sbn&#039;, {err_type}, false, &amp;quot; &amp;quot;, &amp;quot;&amp;quot; );	-- display an error message&lt;br /&gt;
			end&lt;br /&gt;
			table.insert( new_list, {handler.label, SBN } );				&lt;br /&gt;
		elseif k == &#039;SSRN&#039; then&lt;br /&gt;
			table.insert( new_list, {handler.label, ssrn( v ) } );&lt;br /&gt;
		elseif k == &#039;USENETID&#039; then&lt;br /&gt;
			table.insert( new_list, {handler.label, usenet_id( v ) } );&lt;br /&gt;
		elseif k == &#039;ZBL&#039; then&lt;br /&gt;
			table.insert( new_list, {handler.label, zbl( v ) } );&lt;br /&gt;
		else&lt;br /&gt;
			error( cfg.messages[&#039;unknown_manual_ID&#039;] );&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local function comp( a, b )	-- used in following table.sort()&lt;br /&gt;
		return a[1]:lower() &amp;lt; b[1]:lower();&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	table.sort( new_list, comp );&lt;br /&gt;
	for k, v in ipairs( new_list ) do&lt;br /&gt;
		new_list[k] = v[2];&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return new_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 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 is 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 uc 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;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.&lt;br /&gt;
Parameters which have a predefined access level (e.g. arxiv) do not use this&lt;br /&gt;
function as they are directly rendered as free without using an additional parameter.&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;
					table.insert( z.message_tail, { set_error( &#039;invalid_param_val&#039;, {access_param, access_level}, true ) } );	&lt;br /&gt;
					access_level = nil;											-- invalid so unset&lt;br /&gt;
				end&lt;br /&gt;
				if not is_set(id_list[k]) then									-- identifer access-level must have a matching identifier&lt;br /&gt;
					table.insert( z.message_tail, { set_error( &#039;param_access_requires_param&#039;, {k:lower()}, true ) } );	-- param 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; 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;
	is_set = utilities_page_ptr.is_set;											-- import functions from select Module:Citation/CS1/Utilities module&lt;br /&gt;
	in_array = utilities_page_ptr.in_array;&lt;br /&gt;
	set_error = utilities_page_ptr.set_error;&lt;br /&gt;
	select_one = utilities_page_ptr.select_one;&lt;br /&gt;
	add_maint_cat = utilities_page_ptr.add_maint_cat;&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;
	build_id_list = build_id_list,&lt;br /&gt;
	extract_ids = extract_ids,&lt;br /&gt;
	extract_id_access_levels = 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>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Module:Citation/CS1/Date_validation&amp;diff=219</id>
		<title>Module:Citation/CS1/Date validation</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Module:Citation/CS1/Date_validation&amp;diff=219"/>
		<updated>2020-08-22T20:23:48Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&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 is_set, in_array;															-- 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 |accessdate= 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-Engish 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 timesatmp &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; 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 |embargo= is&lt;br /&gt;
set, the editor intended to embargo a pmc but |embargo= 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 (&#039;^%d%d%d%d%-%d%d%-%d%d$&#039;) or									-- ymd&lt;br /&gt;
		v:match (&#039;^%d%d?%s+%a+%s+%d%d%d%d$&#039;) or									-- dmy&lt;br /&gt;
		v:match (&#039;^%a+%s+%d%d?%s*,%s*%d%d%d%d$&#039;) 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; 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;
hemispere 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;
]]&lt;br /&gt;
&lt;br /&gt;
local function is_valid_year (year)&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 numbers for the comparison;&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)&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) then												-- no farther into the future than next year&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;
There is a special test for May because it can be either short or long form.&lt;br /&gt;
&lt;br /&gt;
Returns true when style for both months is the same&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function is_valid_month_range_style (month1, month2)&lt;br /&gt;
local len1 = month1:len();&lt;br /&gt;
local len2 = month2:len();&lt;br /&gt;
	if len1 == len2 then&lt;br /&gt;
		return true;															-- both months are short form so return true&lt;br /&gt;
	elseif &#039;May&#039; == month1 or &#039;May&#039;== month2 then&lt;br /&gt;
		return true;															-- both months are long form so return true&lt;br /&gt;
	elseif 3 == len1 or 3 == len2 then&lt;br /&gt;
		return false;															-- months are mixed form so return false&lt;br /&gt;
	else&lt;br /&gt;
		return true;															-- both months are long form so return true&lt;br /&gt;
	end&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 so ... 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) then&lt;br /&gt;
			return true;														-- any season pairing is accepted&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 then								-- range_start is a month; does range_start precede range_end?&lt;br /&gt;
		if 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;
	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 IS8601 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 / Gergorian 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;Q,y&#039;] = {&#039;^(Q%a* +[1-4]), +((%d%d%d%d)%a?)$&#039;},							-- Quarter n, yyyy&lt;br /&gt;
&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; 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 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, accessdate, embargo, archivedate, etc.)&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;Q,y&#039;][1]) then				-- quarter n, year; here because much the same as Mdy&lt;br /&gt;
--		month, anchor_year, year=mw.ustring.match(date_string, patterns[&#039;Q,y&#039;][1]);&lt;br /&gt;
--		if not is_valid_year(year) then return false; end&lt;br /&gt;
--		month = get_quarter_number (month, param);								-- get quarter 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;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;
&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;
&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;
		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;
		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);								-- for metadata&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;
		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;
		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);&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;
a single error message is created 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)&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 error_message = &amp;quot;&amp;quot;;&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								-- 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;);	--&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								-- 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;);	--&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;embargo&#039;==k then											-- if the parameter is |embargo=&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 |embargo= date a single dmy, mdy, or ymd formatted date? yes:returns embargo; 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;
				if is_set(error_message) then									-- once we&#039;ve added the first portion of the error message ...&lt;br /&gt;
					error_message=error_message .. &amp;quot;, &amp;quot;;						-- ... add a comma space separator&lt;br /&gt;
				end&lt;br /&gt;
				error_message=error_message .. &amp;quot;&amp;amp;#124;&amp;quot; .. v.name .. &amp;quot;=&amp;quot;;		-- add the failed parameter&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return anchor_year, embargo_date, error_message;							-- 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 returns a 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;
]]&lt;br /&gt;
&lt;br /&gt;
local function year_date_check (year_string, date_string)&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&lt;br /&gt;
		result = 0;																-- no recognizable year in date&lt;br /&gt;
	end&lt;br /&gt;
	return result;&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 patern_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;
--	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	-- not supported at en.wiki&lt;br /&gt;
	if &#039;yMd&#039; == format_param then												-- not supported at en.wiki&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&lt;br /&gt;
		t.y = t.a;																-- use the anchor year capture when reassembling the date&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_s&#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_l&#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;
		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_s&#039;][t[mon]]) or cfg.date_names[&#039;inv_local_l&#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) then&lt;br /&gt;
			if not mw.ustring.match (param_val.val, &#039;%d%d%d%d%-%d%d%-%d%d&#039;) 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;
	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 month names to local-language month 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;
	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 dates in the date (single date or date range)&lt;br /&gt;
				if cfg.date_names.en.long[month] then&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&lt;br /&gt;
					mode = &#039;M&#039;;													-- English name is short so use short local name&lt;br /&gt;
				else&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 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;
	is_set = utilities_page_ptr.is_set;											-- import functions from selected Module:Citation/CS1/Utilities module&lt;br /&gt;
	in_array = utilities_page_ptr.in_array;										-- import functions from selected Module:Citation/CS1/Utilities module&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>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Module:Citation/CS1/Configuration&amp;diff=217</id>
		<title>Module:Citation/CS1/Configuration</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Module:Citation/CS1/Configuration&amp;diff=217"/>
		<updated>2020-08-22T20:23:48Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&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.  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;
local uncategorized_namespaces = { &#039;User&#039;, &#039;Talk&#039;, &#039;User_talk&#039;, &#039;Wikipedia_talk&#039;, &#039;File_talk&#039;, &#039;Template_talk&#039;, &#039;Help_talk&#039;, &#039;Category_talk&#039;, &#039;Portal_talk&#039;, &#039;Book_talk&#039;, &#039;Draft_talk&#039;, &#039;Education_Program_talk&#039;, &#039;Module_talk&#039;, &#039;MediaWiki_talk&#039; };&lt;br /&gt;
&lt;br /&gt;
local uncategorized_subpages = {&#039;/[Ss]andbox&#039;, &#039;/[Tt]estcases&#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 ed.)&#039;,&lt;br /&gt;
	[&#039;episode&#039;] = &#039;Episode $1&#039;,&lt;br /&gt;
	[&#039;et al&#039;] = &#039;et 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;newsgroup&#039;] = &#039;[[Usenet newsgroup|Newsgroup]]:&amp;amp;nbsp;$1&#039;,&lt;br /&gt;
	[&#039;original&#039;] = &#039;the original&#039;,&lt;br /&gt;
	[&#039;origyear&#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;§ $1&#039;,&lt;br /&gt;
	[&#039;sections&#039;] = &#039;§§ $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&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;
	[&#039;parameter-separator&#039;] = &#039;, &#039;,&lt;br /&gt;
	[&#039;parameter-final-separator&#039;] = &#039;, and &#039;,&lt;br /&gt;
	[&#039;parameter-pair-separator&#039;] = &#039; and &#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;
	-- 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_manual_ID&#039;] = &#039;Unrecognized manual ID mode&#039;,&lt;br /&gt;
	[&#039;unknown_ID_mode&#039;] = &#039;Unrecognized ID mode&#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;
&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][Aa][%.\&amp;quot;&#039;]*$&amp;quot;,				-- variations on the &#039;et alia&#039; theme&lt;br /&gt;
	&amp;quot;[;,]? *%f[%a]and [Oo]thers&amp;quot;,												-- and alternate 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 bracketed form&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; E D I T O R _ M A R K U P _ 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;ed&amp;quot; and variants in name text&lt;br /&gt;
(author, editor, etc.). The main module uses these to identify and emit the&lt;br /&gt;
&#039;extra_text_names&#039; message. (It is not the only series of patterns for this message.)&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
local editor_markup_patterns = {												-- these patterns match annotations at end of name&lt;br /&gt;
	&#039;%f[%(%[][%(%[]%s*[Ee][Dd][Ss]?%.?%s*[%)%]]?$&#039;,								-- (ed) or (eds): leading &#039;(&#039;, case insensitive &#039;ed&#039;, optional &#039;s&#039;, &#039;.&#039; and/or &#039;)&#039;&lt;br /&gt;
	&#039;[,%.%s]%f[e]eds?%.?$&#039;,														-- ed or eds: without &#039;(&#039;or &#039;)&#039;; case sensitive (ED could be initials Ed could be name)&lt;br /&gt;
	&#039;%f[%(%[][%(%[]%s*[Ee][Dd][Ii][Tt][Oo][Rr][Ss]?%.?%s*[%)%]]?$&#039;,				-- (editor) or (editors): leading &#039;(&#039;, case insensitive, optional &#039;.&#039; and/or &#039;)&#039;&lt;br /&gt;
	&#039;[,%.%s]%f[Ee][Dd][Ii][Tt][Oo][Rr][Ss]?%.?$&#039;,								-- editor or editors: without &#039;(&#039;or &#039;)&#039;; case insensitive&lt;br /&gt;
		&lt;br /&gt;
																				-- these patterns match annotations at beginning of name&lt;br /&gt;
	&#039;^eds?[%.,;]&#039;,																-- ed. or eds.: lower case only, optional &#039;s&#039;, requires &#039;.&#039;&lt;br /&gt;
	&#039;^[%(%[]%s*[Ee][Dd][Ss]?%.?%s*[%)%]]&#039;,										-- (ed) or (eds): also sqare brackets, case insensitive, optional &#039;s&#039;, &#039;.&#039;&lt;br /&gt;
	&#039;^[%(%[]?%s*[Ee][Dd][Ii][Tt][Oo][Rr][Ss]?%A&#039;,								-- (editor or (editors: also sq brackets, case insensitive, optional brackets, &#039;s&#039;&lt;br /&gt;
	&#039;^[%(%[]?%s*[Ee][Dd][Ii][Tt][Ee][Dd]%A&#039;,									-- (edited: also sq brackets, case insensitive, optional brackets&lt;br /&gt;
&lt;br /&gt;
																				-- these patterns match annotations that are the &#039;name&#039;	&lt;br /&gt;
	&#039;^[Ee][Dd][Ii][Tt][Oo][Rr][Ss]?%.?$&#039;,										-- editor or editors; case insensitive&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 been moved into its own, more semantically&lt;br /&gt;
correct place.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local presentation = &lt;br /&gt;
	{&lt;br /&gt;
	-- Error output&lt;br /&gt;
	-- .error class is specified at https://git.wikimedia.org/blob/mediawiki%2Fcore.git/9553bd02a5595da05c184f7521721fb1b79b3935/skins%2Fcommon%2Fshared.css#L538&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 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 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;;									-- |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 |ref= is set&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;$1&amp;lt;/span&amp;gt;$2&#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;$2&amp;lt;/span&amp;gt;&#039;,				-- spacing to use when title contains trailing single or double quote mark&lt;br /&gt;
&lt;br /&gt;
																				-- these for simple wikilinked titles [[&amp;quot;text]], [[text&amp;quot;]] and [[&amp;quot;text&amp;quot;]]&lt;br /&gt;
																				-- span wraps entire wikilink&lt;br /&gt;
	[&#039;kern-wl-left&#039;] = &#039;&amp;lt;span class=&amp;quot;cs1-kern-wl-left&amp;quot;&amp;gt;$1&amp;lt;/span&amp;gt;&#039;,				-- when title contains leading single or double quote mark&lt;br /&gt;
	[&#039;kern-wl-right&#039;] = &#039;&amp;lt;span class=&amp;quot;cs1-kern-wl-left&amp;quot;&amp;gt;$1&amp;lt;/span&amp;gt;&#039;,				-- when title contains trailing single or double quote mark&lt;br /&gt;
	[&#039;kern-wl-both&#039;] = &#039;&amp;lt;span class=&amp;quot;cs1-kern-wl-left cs1-kern-wl-right&amp;quot;&amp;gt;$1&amp;lt;/span&amp;gt;&#039;,	-- when title contains leading and trailing single or double quote marks&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 authors is a semicolon&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;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;,&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 assignements in this table must have been defined in the Whitelist&lt;br /&gt;
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;, &#039;article-format&#039;, &#039;section-format&#039;};&lt;br /&gt;
	[&#039;ChapterURL&#039;] = {&#039;chapter-url&#039;, &#039;chapterurl&#039;, &#039;contribution-url&#039;, &#039;contributionurl&#039;, &#039;entry-url&#039;, &#039;article-url&#039;, &#039;section-url&#039;, &#039;sectionurl&#039;},	-- Used by InternetArchiveBot&lt;br /&gt;
	[&#039;ChapterUrlAccess&#039;] = {&#039;chapter-url-access&#039;, &#039;contribution-url-access&#039;, &#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 identifiers&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;, &#039;event-format&#039;},&lt;br /&gt;
	[&#039;ConferenceURL&#039;] = {&#039;conference-url&#039;, &#039;conferenceurl&#039;, &#039;event-url&#039;, &#039;eventurl&#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;displayauthors&#039;},&lt;br /&gt;
	[&#039;DisplayContributors&#039;] = &#039;display-contributors&#039;,&lt;br /&gt;
	[&#039;DisplayEditors&#039;] = {&#039;display-editors&#039;, &#039;displayeditors&#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&#039;, &#039;doi-broken-date&#039;, &#039;doi-inactive-date&#039;},&lt;br /&gt;
	[&#039;Edition&#039;] = &#039;edition&#039;,&lt;br /&gt;
	[&#039;Editors&#039;] = &#039;editors&#039;,&lt;br /&gt;
	[&#039;Embargo&#039;] = &#039;embargo&#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;IgnoreISBN&#039;] = {&#039;ignore-isbn-error&#039;, &#039;ignoreisbnerror&#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;LastAuthorAmp&#039;] = {&#039;last-author-amp&#039;, &#039;lastauthoramp&#039;},&lt;br /&gt;
	[&#039;LayDate&#039;] = {&#039;lay-date&#039;, &#039;laydate&#039;},&lt;br /&gt;
	[&#039;LayFormat&#039;] = &#039;lay-format&#039;,&lt;br /&gt;
	[&#039;LaySource&#039;] = {&#039;lay-source&#039;, &#039;laysource&#039;},&lt;br /&gt;
	[&#039;LayURL&#039;] = {&#039;lay-url&#039;, &#039;layurl&#039;},											-- Used by InternetArchiveBot&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;NameListFormat&#039;] = &#039;name-list-format&#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;template-doc-demo&#039;, &#039;no-cat&#039;, &#039;nocat&#039;, &#039;no-tracking&#039;, &#039;notracking&#039;},&lt;br /&gt;
	[&#039;Number&#039;] = &#039;number&#039;,														-- this case only for cite techreport&lt;br /&gt;
	[&#039;OrigYear&#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;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;, &#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;, &#039;script-periodical&#039;, &#039;script-website&#039;, &#039;script-work&#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;SeriesSeparator&#039;] = &#039;series-separator&#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;, &#039;seriesnumber&#039;, &#039;seriesno&#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;, &#039;timecaption&#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;titlelink&#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;, &#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;, &#039;trans-periodical&#039;, &#039;trans-website&#039;, &#039;trans-work&#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;
	[&#039;AuthorList-Last&#039;] = {&amp;quot;last#&amp;quot;, &amp;quot;author-last#&amp;quot;, &amp;quot;author#-last&amp;quot;, &amp;quot;author#&amp;quot;, &amp;quot;surname#&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;authorlink#&amp;quot;, &amp;quot;author#link&amp;quot;, &amp;quot;subject-link#&amp;quot;, &amp;quot;subject#-link&amp;quot;, &amp;quot;subjectlink#&amp;quot;, &amp;quot;subject#link&amp;quot;},&lt;br /&gt;
	[&#039;AuthorList-Mask&#039;] = {&amp;quot;author-mask#&amp;quot;, &amp;quot;author#-mask&amp;quot;, &amp;quot;authormask#&amp;quot;, &amp;quot;author#mask&amp;quot;},&lt;br /&gt;
	&lt;br /&gt;
	[&#039;ContributorList-First&#039;] = {&#039;contributor-first#&#039;, &#039;contributor#-first&#039;, &#039;contributor-given#&#039;, &#039;contributor#-given&#039;},&lt;br /&gt;
	[&#039;ContributorList-Last&#039;] = {&#039;contributor-last#&#039;, &#039;contributor#-last&#039;, &#039;contributor#&#039;, &#039;contributor-surname#&#039;, &#039;contributor#-surname&#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#&amp;quot;, &amp;quot;editor-surname#&amp;quot;, &amp;quot;editor#-surname&amp;quot;},&lt;br /&gt;
	[&#039;EditorList-Link&#039;] = {&amp;quot;editor-link#&amp;quot;, &amp;quot;editor#-link&amp;quot;, &amp;quot;editorlink#&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;, &amp;quot;editormask#&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;InterviewerList-Last&#039;] = {&#039;interviewer-last#&#039;, &#039;interviewer#-last&#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;, &#039;translator-given#&#039;, &#039;translator#-given&#039;},&lt;br /&gt;
	[&#039;TranslatorList-Last&#039;] = {&#039;translator-last#&#039;, &#039;translator#-last&#039;, &#039;translator#&#039;, &#039;translator-surname#&#039;, &#039;translator#-surname&#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_skip = {};&lt;br /&gt;
&lt;br /&gt;
local 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;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;
	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;
			punct_skip[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;
				punct_skip[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;
					punct_skip[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;
&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 this table are used, for example,&lt;br /&gt;
when an error message, category name, etc 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;
&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;
	[&#039;authors&#039;] = &#039;authors&#039;,													-- used to assemble maintenance category names&lt;br /&gt;
	[&#039;contributors&#039;] = &#039;contributors&#039;,											-- translation of these names plus translation of the base mainenance category names in maint_cats{} table below&lt;br /&gt;
	[&#039;editors&#039;] = &#039;editors&#039;,													-- must match the names of the actual categories&lt;br /&gt;
	[&#039;interviewers&#039;] = &#039;interviewers&#039;,											-- this group of translations used by get_display_names()&lt;br /&gt;
	[&#039;translators&#039;] = &#039;translators&#039;,&lt;br /&gt;
&lt;br /&gt;
																				-- lua patterns to match pseudo title used by Internet Archive bot and others as place holder for unknown |title= value&lt;br /&gt;
	[&#039;archived_copy&#039;] = {														-- used with CS1 maint: Archived 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;] = &#039;^archived?%s+copy$&#039;,										-- for the local language; lowercase only&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.  The code in Date_validation&lt;br /&gt;
will look first in the local table for valid date names.  If date names are not found in the local table, the code&lt;br /&gt;
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 required when the date-name translation&lt;br /&gt;
function date_name_xlate() is used.&lt;br /&gt;
&lt;br /&gt;
In these tables, 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;
hemispere seasons 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, Easter and Christmas are defined here as 98 and 99, which&lt;br /&gt;
should be out of the ISO 8601 (EDTF) range of uses for a while.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&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;
	[&#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_l&#039;] = {},														-- used in date reformatting; 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_s&#039;] = {},														-- used in date reformatting; 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;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;
for name, i in pairs (date_names[&#039;local&#039;].long) do								-- this table is [&#039;name&#039;] = i&lt;br /&gt;
	date_names[&#039;inv_local_l&#039;][i] = name;										-- invert to get [i] = &#039;name&#039; for conversions from ymd&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
for name, i in pairs (date_names[&#039;local&#039;].short) do								-- this table is [&#039;name&#039;] = i&lt;br /&gt;
	date_names[&#039;inv_local_s&#039;][i] = name;										-- invert to get [i] = &#039;name&#039; for conversions from ymd&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;,		-- 915k									-- sorted by approximate transclusion count&lt;br /&gt;
	&#039;{{ *[Uu]se *(mdy) *dates *[|}]&#039;,	-- 161k&lt;br /&gt;
	&#039;{{ *[Uu]se (DMY) dates *[|}]&#039;,		-- 2929&lt;br /&gt;
	&#039;{{ *[Uu]se *(dmy) *[|}]&#039;,			-- 250 + 34&lt;br /&gt;
	&#039;{{ *([Dd]my) *[|}]&#039;,				-- 272&lt;br /&gt;
	&#039;{{ *[Uu]se (MDY) dates *[|}]&#039;,		-- 173&lt;br /&gt;
	&#039;{{ *[Uu]se *(mdy) *[|}]&#039;,			-- 59 + 12&lt;br /&gt;
	&#039;{{ *([Mm]dy) *[|}]&#039;,				-- 9&lt;br /&gt;
	&#039;{{ *[Uu]se (MDY) *[|}]&#039;,			-- 3&lt;br /&gt;
	&#039;{{ *([Dd]MY) *[|}]&#039;,				-- 2&lt;br /&gt;
	&#039;{{ *([Mm]DY) *[|}]&#039;,				-- 0&lt;br /&gt;
--	&#039;{{ *[Uu]se(mdy) *[|}]&#039;,&lt;br /&gt;
--	&#039;{{ *[Uu]se(mdy)dates *[|}]&#039;,&lt;br /&gt;
--	&#039;{{ *[Uu]se(dmy) *[|}]&#039;,&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
local function get_date_format ()&lt;br /&gt;
	local content = mw.title.getCurrentTitle():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 = get_date_format ();&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;
--[[--------------------------&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 acceptible 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 synonymous keywords possibly from&lt;br /&gt;
different languages.&lt;br /&gt;
&lt;br /&gt;
for i18n: add local-language keywords to value table; do not change the key.  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, it is recommended that the English&lt;br /&gt;
keywords remain in these tables.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local keywords = {&lt;br /&gt;
	[&#039;affirmative&#039;] = {&#039;yes&#039;, &#039;true&#039;, &#039;y&#039;},										-- ignore-isbn-error, last-author-amp, no-tracking, nopp -- 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;},														-- 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;},														-- url-access -- Used by InternetArchiveBot&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;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-format&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].  Generally the keys in this table&lt;br /&gt;
are the canonical en.wiki parameter names though some are contrived because of use in multiple differently named&lt;br /&gt;
parameters: [&#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 appropriate list in keywords{}.&lt;br /&gt;
&lt;br /&gt;
The lists in this table are used to validate the keyword assignment for the 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-format&#039;] = make_keywords_list ({keywords.vanc}),&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 hunting for them if (when)&lt;br /&gt;
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 by Unicode group. Values are decimal&lt;br /&gt;
representations of UTF-8 codes.  The table is organized as a table of tables because the lua pairs keyword returns&lt;br /&gt;
table data in an arbitrary order.  Here, we want to process the table from top to bottom because the entries at&lt;br /&gt;
the top of the table are also found in the ranges specified 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 delete characters.  The nowiki&lt;br /&gt;
stripmarker is not an error but some others are because the parameter values that include them become part of the&lt;br /&gt;
template&#039;s metadata before stripmarker replacement.&lt;br /&gt;
&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;\226\128\141&#039;},										-- U+200D, E2 80 8D&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;\127&#039;},															-- U+007F (DEL), 7F; must be done after stripmarker test&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;
Indic script makes use of zero width joiner as a character modifier so zwj characters must be left in.  This&lt;br /&gt;
pattern covers all of the unicode characters 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;
TODO: find a better place for this?&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;
&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;
	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 local_lang_cat_enable = false;											-- set to true to categorize pages where |language=&amp;lt;local wiki&#039;s language&amp;gt;&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 language codes that apply only&lt;br /&gt;
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;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;,&lt;br /&gt;
	&#039;gu&#039;, &#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;,&lt;br /&gt;
	&#039;lo&#039;, &#039;mk&#039;, &#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;,&lt;br /&gt;
	&#039;sd&#039;, &#039;si&#039;, &#039;sr&#039;, &#039;ta&#039;, &#039;tg&#039;, &#039;th&#039;, &#039;ug&#039;, &#039;uk&#039;, &#039;ur&#039;, &#039;uz&#039;, &#039;yi&#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;crh&#039;] = &#039;Crimean Tatar&#039;,													-- synonymous with Crimean Turkish (return value from {{#language:crh|en}})&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=&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;crimean tatar&#039;] = {&#039;Crimean Tatar&#039;, &#039;crh&#039;},								-- MediaWiki uses &#039;crh&#039; as a subdomain name for Crimean Tatar Wikipedia: crh.wikipedia.org&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;siksika&#039;] = {&#039;Siksika&#039;, &#039;bla&#039;},											-- MediaWiki/IANA/ISO 639 preferred name: Siksika&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; M A I N T E N A N C E _ C A T E G O R I E S &amp;gt;----------------------------------&lt;br /&gt;
&lt;br /&gt;
Here we name maintenance categories to be used in maintenance messages.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local maint_cats = {&lt;br /&gt;
	[&#039;ASIN&#039;] = &#039;CS1 maint: ASIN uses ISBN&#039;,&lt;br /&gt;
	[&#039;archived_copy&#039;] = &#039;CS1 maint: archived copy as title&#039;,&lt;br /&gt;
	[&#039;authors&#039;] = &#039;CS1 maint: uses authors parameter&#039;,&lt;br /&gt;
	[&#039;bot:_unknown&#039;] = &#039;CS1 maint: BOT: original-url status unknown&#039;,&lt;br /&gt;
	[&#039;date_format&#039;] = &#039;CS1 maint: date format&#039;,&lt;br /&gt;
	[&#039;date_year&#039;] = &#039;CS1 maint: date and year&#039;,&lt;br /&gt;
	[&#039;disp_name&#039;] = &#039;CS1 maint: display-$1&#039;,									-- $1 is &#039;authors&#039;, &#039;contributors&#039;, &#039;editors&#039;, &#039;interviewers&#039;, &#039;translators&#039;; gets value from special_case_translation table&lt;br /&gt;
	[&#039;editors&#039;] = &#039;CS1 maint: uses editors parameter&#039;,&lt;br /&gt;
	[&#039;embargo&#039;] = &#039;CS1 maint: PMC embargo expired&#039;,&lt;br /&gt;
	[&#039;extra_punct&#039;] = &#039;CS1 maint: extra punctuation&#039;,&lt;br /&gt;
	[&#039;extra_text&#039;] = &#039;CS1 maint: extra text&#039;,&lt;br /&gt;
	[&#039;extra_text_names&#039;] = &#039;CS1 maint: extra text: $1&#039;,							-- $1 is &#039;&amp;lt;name&amp;gt;s list&#039;; gets value from special_case_translation table&lt;br /&gt;
	[&#039;ignore_isbn_err&#039;] = &#039;CS1 maint: ignored ISBN errors&#039;,&lt;br /&gt;
	[&#039;location&#039;] = &#039;CS1 maint: location&#039;,&lt;br /&gt;
	[&#039;mult_names&#039;] = &#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;
	[&#039;numeric_names&#039;] = &#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;
	[&#039;others&#039;] = &#039;CS1 maint: others&#039;,&lt;br /&gt;
	[&#039;pmc_format&#039;] = &#039;CS1 maint: PMC format&#039;,&lt;br /&gt;
	[&#039;ref_harv&#039;] = &#039;CS1 maint: ref=harv&#039;,&lt;br /&gt;
	[&#039;unfit&#039;] = &#039;CS1 maint: unfit url&#039;,&lt;br /&gt;
	[&#039;unknown_lang&#039;] = &#039;CS1 maint: unrecognized language&#039;,&lt;br /&gt;
	[&#039;untitled&#039;] = &#039;CS1 maint: untitled periodical&#039;,&lt;br /&gt;
	[&#039;zbl&#039;] = &#039;CS1 maint: ZBL&#039;,&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;
Here we name properties categories&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;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;script&#039;] = &#039;CS1 uses foreign language script&#039;,							-- when language specified by |script-title=xx: doesn&#039;t have its own category&lt;br /&gt;
	[&#039;script_with_name&#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;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;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;
	}&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;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;
&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 supplimented with additional specific text that describes the reason for&lt;br /&gt;
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;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;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;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&lt;br /&gt;
&lt;br /&gt;
The following contains a list of IDs for various error conditions defined in the code.  For each ID, we specify a&lt;br /&gt;
text message to display, an error category to 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;
]]&lt;br /&gt;
&lt;br /&gt;
local error_conditions = {&lt;br /&gt;
	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;Pages using citations with accessdate and no URL&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
 		},&lt;br /&gt;
	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;
	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;Pages with archiveurl citation errors&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	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;Pages with archiveurl citation errors&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	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;Pages with archiveurl citation errors&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	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;
	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;
	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;
	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;
	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;
	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;
	bad_date = {&lt;br /&gt;
		message = &#039;Check date values 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;bad_date&#039;,&lt;br /&gt;
		category = &#039;CS1 errors: dates&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	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;
	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;
	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;
	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;
	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;
	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;
	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;
	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;
	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;
	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;
	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;
	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;
	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;
	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;
	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;
	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;
	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;
	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;Pages with URL errors&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	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;
	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;Pages with citations having bare URLs&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	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;
	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;
	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;Pages with citations lacking titles&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	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;
	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;Pages using web citations with no URL&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	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;
	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;
	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;
	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;
	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;
	empty_citation = {&lt;br /&gt;
		message = &#039;Empty citation&#039;,&lt;br /&gt;
		anchor = &#039;empty_citation&#039;,&lt;br /&gt;
		category = &#039;Pages with empty citations&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	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;
	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;
	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;Pages using citations with format and no URL&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	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 paramter 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;
	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;
	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;
	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;
	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;
	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;
	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;
	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;Pages with citations using unsupported parameters&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	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 paramter $2 is suggested parameter name&lt;br /&gt;
		anchor = &#039;parameter_ignored_suggest&#039;,&lt;br /&gt;
		category = &#039;Pages with citations using unsupported parameters&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	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;Pages with citations having redundant parameters&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	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;
	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;
	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;Pages with citations using unnamed parameters&#039;,&lt;br /&gt;
		hidden = false&lt;br /&gt;
		},&lt;br /&gt;
	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;
	vancouver = {&lt;br /&gt;
		message = &#039;Vancouver style error: $1&#039;,									-- $1 is error detail&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;
	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;
&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 identifier we specify a&lt;br /&gt;
variety of information necessary to properly render the 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;
	mode: 	&#039;manual&#039; when there is a specific function in the code to handle the identifier;&lt;br /&gt;
			&#039;external&#039; for identifiers that link outside of Wikipedia;&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;
	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:....&lt;br /&gt;
		for identifiers that have COinS keywords, use the keyword: rft.isbn, rft.issn, rft.eissn&lt;br /&gt;
		for others make a url using the value in prefix, use the keyword: pre (not checked; any text other than &#039;info&#039; or &#039;rft&#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;
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;
		mode = &#039;manual&#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;
		mode = &#039;manual&#039;,&lt;br /&gt;
		prefix = &#039;//www.amazon.&#039;,&lt;br /&gt;
		COinS = nil,															-- no COinS for this id (needs thinking on implementation because |asin-tld=)&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;
		mode = &#039;manual&#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;
		mode = &#039;manual&#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;
		mode = &#039;manual&#039;,														-- manual for custom validation of the &amp;quot;doi&amp;quot;&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;
		mode = &#039;manual&#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;
		mode = &#039;manual&#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;
		mode = &#039;manual&#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;, &#039;isbn13&#039;, &#039;ISBN13&#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;
		mode = &#039;manual&#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;
		mode = &#039;manual&#039;,&lt;br /&gt;
		prefix = &#039;&#039;,															-- not currently used;&lt;br /&gt;
		COinS = &#039;nil&#039;,															-- 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;
		mode = &#039;manual&#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;
		mode = &#039;manual&#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;
		mode = &#039;external&#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;
		mode = &#039;manual&#039;,&lt;br /&gt;
		prefix = &#039;//lccn.loc.gov/&#039;, 											-- protocol relative tested 2015-12-28&lt;br /&gt;
		COinS = &#039;info:lccn&#039;,													-- use prefix value&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;
		mode = &#039;manual&#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;
		mode = &#039;manual&#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;
		},&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;
		mode = &#039;manual&#039;,&lt;br /&gt;
		prefix = &#039;//openlibrary.org/&#039;,&lt;br /&gt;
		COinS = nil,															-- no COinS for this id (needs thinking on implementation because /authors/books/works/OL)&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;
		mode = &#039;external&#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;
		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;
		mode = &#039;manual&#039;,&lt;br /&gt;
		prefix = &#039;//www.ncbi.nlm.nih.gov/pmc/articles/PMC&#039;,&lt;br /&gt;
		suffix = &amp;quot; &amp;quot;,&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 = 7500000,&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;&#039;,&lt;br /&gt;
		label = &#039;PMID&#039;,&lt;br /&gt;
		mode = &#039;manual&#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 = 33000000,&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;
		mode = &#039;external&#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;
		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;
		mode = &#039;manual&#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;
		mode = &#039;manual&#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 = 4000000,&lt;br /&gt;
		access = &#039;free&#039;,														-- always free to read&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;
		mode = &#039;manual&#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 = 230000000,&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;
		mode = &#039;manual&#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;
		mode = &#039;manual&#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&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;
	global_df = global_df,&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;
	indic_script = indic_script,&lt;br /&gt;
	local_lang_cat_enable = local_lang_cat_enable,&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;
	punct_skip = punct_skip,&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;
	}&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Module:Citation/CS1/COinS&amp;diff=215</id>
		<title>Module:Citation/CS1/COinS</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Module:Citation/CS1/COinS&amp;diff=215"/>
		<updated>2020-08-22T20:23:48Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&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 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;
	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 intital&lt;br /&gt;
value.  To replace multipe equations it is necesary 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.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;
																				-- 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 id then															-- when cfg.id_handlers[k].COinS is not nil&lt;br /&gt;
			OCinSoutput[&amp;quot;rft_id&amp;quot;] = table.concat{ cfg.id_handlers[k].prefix, v };	-- others; provide a url&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 strip markers, non-printing or invisible characers&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;
		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;
	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;
	is_set = utilities_page_ptr.is_set;											-- import functions from selected Module:Citation/CS1/Utilities module&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>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Module:Citation/CS1&amp;diff=213</id>
		<title>Module:Citation/CS1</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Module:Citation/CS1&amp;diff=213"/>
		<updated>2020-08-22T20:23:48Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&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 dates, year_date_check, reformat_dates, date_hyphen_to_dash,				-- functions in Module:Citation/CS1/Date_validation&lt;br /&gt;
	date_name_xlate&lt;br /&gt;
&lt;br /&gt;
local is_set, in_array, substitute, error_comment, set_error, select_one,		-- functions in Module:Citation/CS1/Utilities&lt;br /&gt;
	add_maint_cat, wrap_style, safe_for_italics, is_wikilink, make_wikilink,&lt;br /&gt;
	strip_apostrophe_markup;&lt;br /&gt;
&lt;br /&gt;
local z ={};																	-- tables in Module:Citation/CS1/Utilities&lt;br /&gt;
&lt;br /&gt;
local extract_ids, extract_id_access_levels, build_id_list, is_embargoed;		-- functions in Module:Citation/CS1/Identifiers&lt;br /&gt;
&lt;br /&gt;
local make_coins_title, get_coins_pages, COinS;									-- functions in Module:Citation/CS1/COinS&lt;br /&gt;
&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 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_prop_cats = {};														-- list of property categories that have been added to z.properties_cats&lt;br /&gt;
local added_vanc_errs;															-- boolean flag so we only emit one Vancouver error / category&lt;br /&gt;
&lt;br /&gt;
local Frame;																	-- holds the module&#039;s frame table&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 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 _ P R O P _ C A T &amp;gt;--------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Adds a category to z.properties_cats 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 function add_prop_cat (key, arguments)&lt;br /&gt;
	if not added_prop_cats [key] then&lt;br /&gt;
		added_prop_cats [key] = true;											-- note that we&#039;ve added this category&lt;br /&gt;
		key = key:gsub (&#039;(foreign_lang_source_?2?)%a%a%a?[%a%-]*&#039;, &#039;%1&#039;);		-- strip lang code from keyname&lt;br /&gt;
		table.insert( z.properties_cats, substitute (cfg.prop_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 _ 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)&lt;br /&gt;
	if not added_vanc_errs then&lt;br /&gt;
		added_vanc_errs = true;													-- note that we&#039;ve added this category&lt;br /&gt;
		table.insert( z.message_tail, { set_error( &#039;vancouver&#039;, {source}, true ) } );&lt;br /&gt;
	end&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;
rfc952 (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 incase 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 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;
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;
		authority = authority:gsub (&#039;//&#039;, &#039;&#039;, 1);								-- replace place 1 pair of &#039;/&#039; with nothing;&lt;br /&gt;
		if 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;
		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 wikilinked 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;
]]&lt;br /&gt;
&lt;br /&gt;
local function link_title_ok (link, lorig, title, torig)&lt;br /&gt;
local orig;&lt;br /&gt;
&lt;br /&gt;
	if 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;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if is_set (orig) then&lt;br /&gt;
		table.insert( z.message_tail, { set_error( &#039;bad_paramlink&#039;, orig)});	-- url or wikilink in |title= with |title-link=;&lt;br /&gt;
	end&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)&lt;br /&gt;
local error_message = &#039;&#039;;&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;
			if is_set(error_message) then										-- once we&#039;ve added the first portion of the error message ...&lt;br /&gt;
				error_message=error_message .. &amp;quot;, &amp;quot;;							-- ... add a comma space separator&lt;br /&gt;
			end&lt;br /&gt;
			error_message=error_message .. &amp;quot;&amp;amp;#124;&amp;quot; .. k .. &amp;quot;=&amp;quot;;				-- add the failed parameter&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if is_set (error_message) then												-- done looping, if there is an error message, display it&lt;br /&gt;
		table.insert( z.message_tail, { set_error( &#039;param_has_ext_link&#039;, {error_message}, true ) } );&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;
		table.insert( z.message_tail, { set_error( &#039;wikilink_in_url&#039;, {}, true ) } );&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 error_str = &amp;quot;&amp;quot;;&lt;br /&gt;
	local domain;&lt;br /&gt;
	local path;&lt;br /&gt;
	local base_url;&lt;br /&gt;
&lt;br /&gt;
	if not is_set( label ) then&lt;br /&gt;
		label = URL;&lt;br /&gt;
		if is_set( source ) then&lt;br /&gt;
			error_str = set_error( &#039;bare_url_missing_title&#039;, { wrap_style (&#039;parameter&#039;, source) }, false, &amp;quot; &amp;quot; );&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;
		error_str = set_error( &#039;bad_url&#039;, {wrap_style (&#039;parameter&#039;, source)}, false, &amp;quot; &amp;quot; ) .. error_str;&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 wikimarkup url&lt;br /&gt;
&lt;br /&gt;
	if is_set (access) then														-- access level (subscription, registration, limited)&lt;br /&gt;
		base_url = 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 table.concat ({base_url, error_str});&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;
		table.insert( z.message_tail, { set_error( &#039;deprecated_params&#039;, {name}, true ) } );	-- 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 wikimarkup) are not kerned.&lt;br /&gt;
&lt;br /&gt;
Replaces unicode quotemarks 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 cap2=&#039;&#039;;&lt;br /&gt;
	local wl_type, label, link;&lt;br /&gt;
&lt;br /&gt;
	wl_type, label, link = 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 = substitute (cfg.presentation[&#039;kern-wl-both&#039;], str);&lt;br /&gt;
		elseif mw.ustring.match (str, &#039;%[%[[\&amp;quot;“”\&#039;‘’].+%]%]&#039;)	then			-- leading quote marks&lt;br /&gt;
			str = substitute (cfg.presentation[&#039;kern-wl-left&#039;], str);&lt;br /&gt;
		elseif mw.ustring.match (str, &#039;%[%[.+[\&amp;quot;“”\&#039;‘’]%]%]&#039;) then				-- trailing quote marks&lt;br /&gt;
			str = substitute (cfg.presentation[&#039;kern-wl-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, cap2 = 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 is_set (cap) then&lt;br /&gt;
			label = substitute (cfg.presentation[&#039;kern-left&#039;], {cap, cap2});&lt;br /&gt;
		end&lt;br /&gt;
	&lt;br /&gt;
		cap, cap2 = 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 is_set (cap) then&lt;br /&gt;
			label = substitute (cfg.presentation[&#039;kern-right&#039;], {cap, cap2});&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		if 2 == wl_type then&lt;br /&gt;
			str = 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 ISO639-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 ISO639-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 is_set (lang) then&lt;br /&gt;
			table.insert( z.message_tail, { set_error( &#039;script_parameter&#039;, {script_param, &#039;missing title part&#039;}, true ) } );		-- 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 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 in_array (lang, cfg.script_lang_codes) then&lt;br /&gt;
				add_prop_cat (&#039;script_with_name&#039;, {name, lang})&lt;br /&gt;
			else&lt;br /&gt;
				table.insert( z.message_tail, { set_error( &#039;script_parameter&#039;, {script_param, &#039;unknown language code&#039;}, true ) } );	-- 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;
			table.insert( z.message_tail, { set_error( &#039;script_parameter&#039;, {script_param, &#039;invalid language code&#039;}, true ) } );		-- 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;
		table.insert( z.message_tail, { set_error( &#039;script_parameter&#039;, {script_param, &#039;missing prefix&#039;}, true ) } );				-- no language code prefix; add error message&lt;br /&gt;
	end&lt;br /&gt;
	script_value = 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 value has been &lt;br /&gt;
wrapped in &amp;lt;bdi&amp;gt; tags.&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function script_concatenate (title, script, script_param)&lt;br /&gt;
	if is_set (script) then&lt;br /&gt;
		script = format_script_value (script, script_param);					-- &amp;lt;bdi&amp;gt; tags, lang atribute, categorization, etc; returns empty string on error&lt;br /&gt;
		if 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 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 substitute( msg, str );											-- including template text&lt;br /&gt;
	else&lt;br /&gt;
		return 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 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 = 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 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 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 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;=, and |trans-&amp;lt;periodical&amp;gt;= into a single Periodical meta-&lt;br /&gt;
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;
	local periodical_error = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
	if not is_set (periodical) then&lt;br /&gt;
		periodical = &#039;&#039;;														-- to be safe for concatenation&lt;br /&gt;
	else&lt;br /&gt;
		periodical = 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 atribute, categorization, etc; must be done after title is wrapped&lt;br /&gt;
&lt;br /&gt;
	if is_set (trans_periodical) then&lt;br /&gt;
		trans_periodical = wrap_style (&#039;trans-italic-title&#039;, trans_periodical);&lt;br /&gt;
		if 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;
			periodical_error = &#039; &#039; .. set_error (&#039;trans_missing_title&#039;, {&#039;periodical&#039;});&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return periodical .. periodical_error;&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=, and |chapter-url= into a single Chapter meta-&lt;br /&gt;
parameter (chapter_url_source used 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 chapter_error = &#039;&#039;;&lt;br /&gt;
&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 separaters with space characters&lt;br /&gt;
		chapter = ws_label;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if not 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 = 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 atribute, categorization, etc; must be done after title is wrapped&lt;br /&gt;
&lt;br /&gt;
	if 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 = 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 is_set (trans_chapter) then&lt;br /&gt;
		trans_chapter = wrap_style (&#039;trans-quoted-title&#039;, trans_chapter);&lt;br /&gt;
		if 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;
			chapter_error = &#039; &#039; .. set_error (&#039;trans_missing_title&#039;, {chapter_source});&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return chapter .. chapter_error;&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 nonprintable or invisible characters.  The search stops at the&lt;br /&gt;
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 (gallery, math, pre, ref)&lt;br /&gt;
and identifies them with a slightly different error message.  See also coins_cleanup().&lt;br /&gt;
&lt;br /&gt;
Output of this function is an error message that identifies the character or the Unicode group, or the stripmarker&lt;br /&gt;
that was detected along with its position (or, for multi-byte characters, the position of its first byte) in the&lt;br /&gt;
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 dummy;																-- end of matching string; not used but required to hold end position when a capture is returned&lt;br /&gt;
	local capture;																-- used by stripmarker detection to hold name of the stripmarker&lt;br /&gt;
	local i=1;&lt;br /&gt;
	local stripmarker, apostrophe;&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;
	while cfg.invisible_chars[i] do&lt;br /&gt;
		local char=cfg.invisible_chars[i][1]									-- the character or group name&lt;br /&gt;
		local pattern=cfg.invisible_chars[i][2]									-- the pattern used to find it&lt;br /&gt;
		position, dummy, 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 (char == &#039;zero width joiner&#039;) then						-- if we found a zero width joiner character&lt;br /&gt;
			if mw.ustring.find (v, cfg.indic_script) then						-- its ok if one of the indic scripts&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 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 &#039;delete&#039; == char 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 then&lt;br /&gt;
					err_msg = capture .. &#039; &#039; .. char;&lt;br /&gt;
				else&lt;br /&gt;
					err_msg = char .. &#039; &#039; .. &#039;character&#039;;&lt;br /&gt;
				end&lt;br /&gt;
&lt;br /&gt;
				table.insert( z.message_tail, { set_error( &#039;invisible_char&#039;, {err_msg, wrap_style (&#039;parameter&#039;, param), position}, true ) } );	-- add error message&lt;br /&gt;
				return;															-- and done with this parameter&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		i=i+1;																	-- bump our index&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 in the configuration file so that&lt;br /&gt;
multiple names can be transparently aliased to 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] = select_one( args, list, &#039;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 = cfg.defaults[k] or &#039;&#039;;&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;.  When date is DD MMMM YYYY or is&lt;br /&gt;
MMMM DD, YYYY then wrap in nowrap span: &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 = 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 = 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 |type=&amp;lt;default value&amp;gt;) for those templates that have defaults.&lt;br /&gt;
Also handles the special case where it is desirable to omit the title type from the rendered citation (|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 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; 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 like items; unlike items are&lt;br /&gt;
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 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 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;
	str, count = str:gsub (&#039;^%(%((.+)%)%)$&#039;, &#039;%1&#039;);								-- remove accept-this-as-written markup when it wraps all of str&lt;br /&gt;
	if 0 ~= count then															-- non-zero when markup removed; zero else&lt;br /&gt;
		return str;																-- nothing to do, we&#039;re done&lt;br /&gt;
	end&lt;br /&gt;
	&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;
		if 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 white space&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		item = item:gsub (&#039;^%(%((.+)%)%)$&#039;, &#039;%1&#039;);								-- remove the accept-this-as-written markup&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;
	return table.concat (out, &#039;, &#039;);											-- concatenate the output table into a comma separated string&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;dupicate 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 wikimarkup&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 wikimarkup&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 is suffix is properly formed Jr, Sr, or ordinal in the range 2–9.  Puncutation not allowed.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function is_suffix (suffix)&lt;br /&gt;
	if in_array (suffix, {&#039;Jr&#039;, &#039;Sr&#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 (read ASCII) characters.  When a name&lt;br /&gt;
uses characters that contain diacritical marks, those characters are to converted to the corresponding Latin character.&lt;br /&gt;
When a name is written using a non-Latin alphabet or logogram, that name is to be transliterated into Latin characters.&lt;br /&gt;
These things are not currently possible in this module so are left to the editor to do.&lt;br /&gt;
&lt;br /&gt;
This test allows |first= and |last= names to contain any of the letters defined 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. (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;) or nil == mw.ustring.find (first, &amp;quot;^[A-Za-zÀ-ÖØ-öø-ƿǄ-ɏ%-%s%&#039;%.]+[2-6%a]*$&amp;quot;) then&lt;br /&gt;
was written ouside of the code editor and pasted here because the code editor gets confused between character insertion point and cursor position.&lt;br /&gt;
The test has been rewritten to use decimal character escape sequence for the individual bytes of the unicode characters so that it is not necessary&lt;br /&gt;
to use an external editor 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)&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 is_set (suffix) then&lt;br /&gt;
		if not is_suffix (suffix) then&lt;br /&gt;
			add_vanc_error (cfg.err_msg_supl.suffix);&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;]);&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-format=vanc.  &lt;br /&gt;
&lt;br /&gt;
Names in |firstn= may be separated by spaces or hyphens, or for initials, a period. 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 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 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 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)&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 intials?&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);					-- 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 intial 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 (e.g. authors / editors) &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 lastauthoramp = control.lastauthoramp;&lt;br /&gt;
	local text = {}&lt;br /&gt;
&lt;br /&gt;
	if &#039;vanc&#039; == format then													-- Vancouver-like author/editor name styling?&lt;br /&gt;
		sep = cfg.presentation[&#039;sep_nl_vanc&#039;];									-- name-list separator between authors is a comma&lt;br /&gt;
		namesep = cfg.presentation[&#039;sep_name_vanc&#039;];							-- last/first separator is a space&lt;br /&gt;
		lastauthoramp = nil;													-- unset because isn&#039;t used by Vancouver style&lt;br /&gt;
	else&lt;br /&gt;
		sep = cfg.presentation[&#039;sep_nl&#039;];										-- name-list separator between authors 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 is_set (maximum) and maximum &amp;lt; 1 then return &amp;quot;&amp;quot;, 0; end					-- returned 0 is for EditorCount; not used for authors&lt;br /&gt;
	&lt;br /&gt;
	for i,person in ipairs(people) do&lt;br /&gt;
		if 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;
			if is_set (maximum) and i &amp;gt; maximum then&lt;br /&gt;
				etal = true;&lt;br /&gt;
				break;&lt;br /&gt;
			elseif (mask ~= nil) then&lt;br /&gt;
				local n = tonumber(mask)&lt;br /&gt;
				if (n ~= nil) then&lt;br /&gt;
					one = string.rep(&amp;quot;&amp;amp;mdash;&amp;quot;,n)&lt;br /&gt;
				else&lt;br /&gt;
					one = mask;&lt;br /&gt;
					sep_one = &amp;quot; &amp;quot;;&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				one = person.last&lt;br /&gt;
				local first = person.first&lt;br /&gt;
				if 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) then		-- and name is all Latin characters; corporate authors not tested&lt;br /&gt;
							first = reduce_to_initials(first)					-- 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 is_set (person.link) then&lt;br /&gt;
				one = make_wikilink (person.link, one);							-- link author/editor&lt;br /&gt;
			end&lt;br /&gt;
			table.insert (text, one)&lt;br /&gt;
			table.insert (text, sep_one)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local count = #text / 2;													-- (number of names + number of separators) divided by 2&lt;br /&gt;
	if count &amp;gt; 0 then &lt;br /&gt;
		if count &amp;gt; 1 and is_set(lastauthoramp) and not etal then&lt;br /&gt;
			text[#text-2] = &amp;quot; &amp;amp; &amp;quot;;												-- replace last separator with ampersand text&lt;br /&gt;
		end&lt;br /&gt;
		text[#text] = nil;														-- erase the last separator&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local result = table.concat(text)											-- construct list&lt;br /&gt;
	if etal and 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 go a last-first list and etal so add et al.&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return result, count&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; A N C H O R _ 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 returns an empty string.&lt;br /&gt;
&lt;br /&gt;
namelist is one of the contributor-, author-, or editor-name lists chosen in that order.  year is Year or anchor_year.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function anchor_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 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; 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 the theme of et al.  If found,&lt;br /&gt;
the et al. is removed, a flag is set to true and 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 it&#039;s previous state because it may have been set by&lt;br /&gt;
previous passes through this function or by the associated |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 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;
					table.insert( z.message_tail, {set_error (&#039;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 mixed alphanumeric names so&lt;br /&gt;
|last=A. Green (1922-1987) does not get caught in the 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 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;
			add_maint_cat (&#039;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 _ E D _ M A R K U P &amp;gt;------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Evaluates the content of author and editor parameters for extranious editor annotations: ed, ed., eds, (Ed.), etc.&lt;br /&gt;
These annotation do not belong in author parameters and are redundant in editor parameters.  If found, the function&lt;br /&gt;
adds the editor markup 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_ed_markup (name, list_name)&lt;br /&gt;
	local patterns = cfg.editor_markup_patterns;								-- get patterns from configuration&lt;br /&gt;
&lt;br /&gt;
	if is_set (name) then&lt;br /&gt;
		for _, pattern in ipairs (patterns) do									-- spin through patterns table and&lt;br /&gt;
			if name:match (pattern) then&lt;br /&gt;
				add_maint_cat (&#039;extra_text_names&#039;, cfg.special_case_translation [list_name]);	-- add a maint cat for this template&lt;br /&gt;
				break;&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 _ H A S _ M U L T _ N A M E S &amp;gt;----------------------------------------&lt;br /&gt;
&lt;br /&gt;
Evaluates the content of author and editor (surnames only) parameters for multiple names.  Multiple names are&lt;br /&gt;
indicated if there is more than one comma and or semicolon.  If found, the function adds the multiple name&lt;br /&gt;
(author or editor) 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 _, count;&lt;br /&gt;
	if is_set (name) then&lt;br /&gt;
		_, count = name:gsub (&#039;[;,]&#039;, &#039;&#039;);										-- count the number of separator-like characters&lt;br /&gt;
		&lt;br /&gt;
		if 1 &amp;lt; count then														-- param could be |author= or |editor= so one separator character is acceptable&lt;br /&gt;
			add_maint_cat (&#039;mult_names&#039;, cfg.special_case_translation [list_name]);	-- more than one separator indicates multiple names so 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 _ 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&lt;br /&gt;
parameters.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function name_checks (last, first, list_name)&lt;br /&gt;
	if is_set (last) then&lt;br /&gt;
		if last:match (&#039;^%(%(.*%)%)$&#039;) then										-- if wrapped in doubled parentheses, accept as written &lt;br /&gt;
			last = last:match (&#039;^%(%((.*)%)%)$&#039;);								-- strip parens&lt;br /&gt;
		else&lt;br /&gt;
			name_has_mult_names (last, list_name);								-- check for multiple names in the parameter (last only)&lt;br /&gt;
			name_has_ed_markup (last, list_name);								-- check for extraneous &#039;editor&#039; annotation&lt;br /&gt;
			name_is_numeric (last, list_name);									-- check for names that are compsed of digits and punctuation&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if is_set (first) then&lt;br /&gt;
		if first:match (&#039;^%(%(.*%)%)$&#039;) then									-- if wrapped in doubled parentheses, accept as written &lt;br /&gt;
			first = first:match (&#039;^%(%((.*)%)%)$&#039;);								-- strip parens&lt;br /&gt;
		else&lt;br /&gt;
			name_has_ed_markup (first, list_name);								-- check for extraneous &#039;editor&#039; annotation&lt;br /&gt;
			name_is_numeric (first, list_name);									-- check for names that are compsed of digits and punctuation&lt;br /&gt;
		end&lt;br /&gt;
	end&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;
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 (or their aliases), and their matching link and mask parameters.&lt;br /&gt;
Stops searching when both |lastn= and |firstn= are not found in args after two sequential attempts: found |last1=, |last2=, and |last3= but doesn&#039;t&lt;br /&gt;
find |last4= and |last5= then the search is done.&lt;br /&gt;
&lt;br /&gt;
This function emits an error message when there is a |firstn= without a matching |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 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; is stripped from the parameter and a flag (etal) returned&lt;br /&gt;
that will cause list_people() to add the static &#039;et al.&#039; text from Module:Citation/CS1/Configuration.  This keeps &#039;et al.&#039; out of the &lt;br /&gt;
template&#039;s metadata.  When this occurs, the page is added to a maintenance category.&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 = select_one( args, cfg.aliases[list_name .. &#039;-Last&#039;], &#039;redundant_parameters&#039;, i );		-- search through args for name components beginning at 1&lt;br /&gt;
		first, first_alias = select_one( args, cfg.aliases[list_name .. &#039;-First&#039;], &#039;redundant_parameters&#039;, i );&lt;br /&gt;
		link, link_alias = select_one( args, cfg.aliases[list_name .. &#039;-Link&#039;], &#039;redundant_parameters&#039;, i );&lt;br /&gt;
		mask = select_one( args, cfg.aliases[list_name .. &#039;-Mask&#039;], &#039;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);						-- 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;
			table.insert( z.message_tail, { set_error( &#039;first_missing_last&#039;, {first_alias, first_alias:gsub(&#039;first&#039;, &#039;last&#039;)}, true ) } );	-- 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;
			link_title_ok (link, link_alias, last, last_alias);					-- check for improper wikimarkup&lt;br /&gt;
			if first then&lt;br /&gt;
				link_title_ok (link, link_alias, first, first_alias);			-- check for improper wikimarkup&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;
				table.insert( z.message_tail, { set_error( &#039;missing_name&#039;, {list_name:match (&amp;quot;(%w+)List&amp;quot;):lower(), i-1}, true ) } );	-- 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&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; G E T _ I S O 6 3 9 _ C O D E &amp;gt;------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Validates language names provided in |language= parameter if not an ISO639-1 or 639-2 code.&lt;br /&gt;
&lt;br /&gt;
Returns the language name and associated two- or three-character code.  Because case of the source may be incorrect&lt;br /&gt;
or different from the case that WikiMedia uses, the name comparisons are done in lower case and when a match is&lt;br /&gt;
found, the Wikimedia version (assumed to be correct) is returned along with the code.  When there is no match, we&lt;br /&gt;
return the original language name string.&lt;br /&gt;
&lt;br /&gt;
mw.language.fetchLanguageNames(&amp;lt;local wiki language&amp;gt;, &#039;all&#039;) returns a list of languages that in some cases may include&lt;br /&gt;
extensions. For example, code &#039;cbk-zam&#039; and its associated name &#039;Chavacano de Zamboanga&#039; (MediaWiki does not support&lt;br /&gt;
code &#039;cbk&#039; or name &#039;Chavacano&#039;.  Most (all?) of these languages are not used a &#039;language&#039; codes per se, rather they&lt;br /&gt;
are used as sub-domain names: cbk-zam.wikipedia.org.  A list of language names and codes supported by fetchLanguageNames()&lt;br /&gt;
can be found at Template:Citation Style documentation/language/doc&lt;br /&gt;
&lt;br /&gt;
Names that are included in the list will be found if that name is provided in the |language= parameter.  For example,&lt;br /&gt;
if |language=Chavacano de Zamboanga, that name will be found with the associated code &#039;cbk-zam&#039;.  When names are found&lt;br /&gt;
and the associated code is not two or three characters, this function returns only the WikiMedia language name.&lt;br /&gt;
&lt;br /&gt;
Some language names have multiple entries under different codes:&lt;br /&gt;
	Aromanian has code rup and code roa-rup&lt;br /&gt;
When this occurs, this function returns the language name and the 2- or 3-character code&lt;br /&gt;
&lt;br /&gt;
Adapted from code taken from Module:Check ISO 639-1.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function get_iso639_code (lang, this_wiki_code)&lt;br /&gt;
	if cfg.lang_name_remap[lang:lower()] then									-- if there is a remapped name (because MediaWiki uses something that we don&#039;t think is correct)&lt;br /&gt;
		return cfg.lang_name_remap[lang:lower()][1], cfg.lang_name_remap[lang:lower()][2];	-- for this language &#039;name&#039;, return a possibly new name and appropriate code&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local ietf_code;															-- because some languages have both ietf-like codes and iso 639-like codes&lt;br /&gt;
	local ietf_name;&lt;br /&gt;
	&lt;br /&gt;
	local languages = mw.language.fetchLanguageNames(this_wiki_code, &#039;all&#039;)		-- get a list of language names known to Wikimedia&lt;br /&gt;
																				-- (&#039;all&#039; is required for North Ndebele, South Ndebele, and Ojibwa)&lt;br /&gt;
	local langlc = mw.ustring.lower(lang);										-- lower case version for comparisons&lt;br /&gt;
&lt;br /&gt;
	for code, name in pairs(languages) do										-- scan the list to see if we can find our language&lt;br /&gt;
		if langlc == mw.ustring.lower(name) then&lt;br /&gt;
			if 2 == code:len() or 3 == code:len() then							-- two- or three-character codes only; extensions not supported&lt;br /&gt;
				return name, code;												-- so return the name and the code&lt;br /&gt;
			end&lt;br /&gt;
			ietf_code = code;													-- remember that we found an ietf-like code and save its name&lt;br /&gt;
			ietf_name = name;													-- but keep looking for a 2- or 3-char code&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
																				-- didn&#039;t find name with 2- or 3-char code; if ietf-like code found return&lt;br /&gt;
	return ietf_code and ietf_name or lang;										-- associated name; return original language text else&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 is recognized by MediaWiki,&lt;br /&gt;
use the returned name; if not, then use the value that 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 assigned to the category for&lt;br /&gt;
that code: Category:Norwegian-language sources (no).  For valid three-character code languages, the page is assigned&lt;br /&gt;
to the single category 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 not recognize three-character&lt;br /&gt;
equivalents of two-character codes: code &#039;ar&#039; is 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 where the language names or codes are&lt;br /&gt;
separated from each other by commas with optional space characters.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function language_parameter (lang)&lt;br /&gt;
	local code;																	-- the two- or three-character language code&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_table = {};														-- 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_table = 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_table) do										-- reuse lang&lt;br /&gt;
		name = cfg.lang_code_remap[lang:lower()];								-- first see if this is a code that is not supported by MediaWiki but is in remap&lt;br /&gt;
&lt;br /&gt;
		if name then															-- there was a remapped code so&lt;br /&gt;
			if not lang:match (&#039;^%a%a%a?%-x%-%a+$&#039;) then						-- if not a private ietf tag&lt;br /&gt;
				lang = lang:gsub (&#039;^(%a%a%a?)%-.*&#039;, &#039;%1&#039;);						-- strip ietf tags from code&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			lang = lang:gsub (&#039;^(%a%a%a?)%-.*&#039;, &#039;%1&#039;);							-- strip any ietf-like tags from code&lt;br /&gt;
			if 2 == lang:len() or 3 == lang:len() then							-- if two-or three-character code&lt;br /&gt;
				name = mw.language.fetchLanguageName (lang:lower(), cfg.this_wiki_code);	-- get language name if |language= is a proper code&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		if is_set (name) then													-- if |language= specified a valid code&lt;br /&gt;
			code = lang:lower();												-- save it&lt;br /&gt;
		else&lt;br /&gt;
			name, code = get_iso639_code (lang, cfg.this_wiki_code);				-- attempt to get code from name (assign name here so that we are sure of proper capitalization)&lt;br /&gt;
		end&lt;br /&gt;
	&lt;br /&gt;
		if is_set (code) then													-- only 2- or 3-character codes&lt;br /&gt;
			name = cfg.lang_code_remap[code] or name;							-- override wikimedia when they misuse language codes/names&lt;br /&gt;
&lt;br /&gt;
			if cfg.this_wiki_code ~= code then									-- when the language is not the same as this wiki&#039;s language&lt;br /&gt;
				if 2 == code:len() then											-- and is a two-character code&lt;br /&gt;
					add_prop_cat (&#039;foreign_lang_source&#039; .. code, {name, code});	-- categorize it; code appended to allow for multiple language categorization&lt;br /&gt;
				else															-- or is a recognized language (but has a three-character code)&lt;br /&gt;
					add_prop_cat (&#039;foreign_lang_source_2&#039; .. code, {code});		-- categorize it differently TODO: support multiple three-character code 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;
				add_prop_cat (&#039;local_lang_source&#039;, {name, code});				-- categorize it&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			add_maint_cat (&#039;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;
	code = #language_list														-- reuse code as number of languages in the list&lt;br /&gt;
	if 2 &amp;gt;= code then&lt;br /&gt;
		name = table.concat (language_list, cfg.messages[&#039;parameter-pair-separator&#039;])		-- insert &#039;&amp;lt;space&amp;gt;and&amp;lt;space&amp;gt;&#039; between two language names&lt;br /&gt;
	elseif 2 &amp;lt; code then&lt;br /&gt;
		name = table.concat (language_list, cfg.messages[&#039;parameter-separator&#039;], 1, code-1);			-- concatenate all but last&lt;br /&gt;
		name = table.concat ({name, language_list[code]}, cfg.messages[&#039;parameter-final-separator&#039;]);	-- concatenate last with final separator&lt;br /&gt;
	end&lt;br /&gt;
	if this_wiki_name == name then&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 1 _ S T Y L E &amp;gt;----------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Set style settings for CS1 citation templates. Returns separator and postscript settings&lt;br /&gt;
At en.wiki, for cs1:&lt;br /&gt;
	ps gets:	&#039;.&#039;&lt;br /&gt;
	sep gets:	&#039;.&#039;&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function set_cs1_style (ps)&lt;br /&gt;
	if not is_set (ps) then														-- unless explicitly set to something&lt;br /&gt;
		ps = cfg.presentation[&#039;ps_cs1&#039;];										-- terminate the rendered citation&lt;br /&gt;
	end&lt;br /&gt;
	return cfg.presentation[&#039;sep_cs1&#039;], ps;										-- element separator&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S E T _ C S 2 _ S T Y L E &amp;gt;----------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Set style settings for CS2 citation templates. Returns separator, postscript, ref settings&lt;br /&gt;
At en.wiki, for cs2:&lt;br /&gt;
	ps gets:	&#039;&#039; (empty string - no terminal punctuation)&lt;br /&gt;
	sep gets:	&#039;,&#039;&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function set_cs2_style (ps, ref)&lt;br /&gt;
	if not is_set (ps) then														-- if |postscript= has not been set, set cs2 default&lt;br /&gt;
		ps = cfg.presentation[&#039;ps_cs2&#039;];										-- terminate the rendered citation&lt;br /&gt;
	end&lt;br /&gt;
	if not is_set (ref) then													-- if |ref= is not set&lt;br /&gt;
		ref = &amp;quot;harv&amp;quot;;															-- set default |ref=harv&lt;br /&gt;
	end&lt;br /&gt;
	return cfg.presentation[&#039;sep_cs2&#039;], ps, ref;								-- element separator&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; G E T _ S E T T I N G S _ F R O M _ C I T E _ C L A S S &amp;gt;----------------------&lt;br /&gt;
&lt;br /&gt;
When |mode= is not set or when its value is invalid, use config.CitationClass and parameter values to establish&lt;br /&gt;
rendered style.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function get_settings_from_cite_class (ps, ref, cite_class)&lt;br /&gt;
	local sep;&lt;br /&gt;
	if (cite_class == &amp;quot;citation&amp;quot;) then											-- for citation templates (CS2)&lt;br /&gt;
		sep, ps, ref = set_cs2_style (ps, ref);&lt;br /&gt;
	else																		-- not a citation template so CS1&lt;br /&gt;
		sep, ps = set_cs1_style (ps);&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return sep, ps, ref															-- return them all&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S E T _ S T Y L E &amp;gt;------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Establish basic style settings to be used when rendering the citation.  Uses |mode= if set and valid or uses&lt;br /&gt;
config.CitationClass from the template&#039;s #invoke: to establish style.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function set_style (mode, ps, ref, cite_class)&lt;br /&gt;
	local sep;&lt;br /&gt;
	if &#039;cs2&#039; == mode then														-- if this template is to be rendered in CS2 (citation) style&lt;br /&gt;
		sep, ps, ref = set_cs2_style (ps, ref);&lt;br /&gt;
	elseif &#039;cs1&#039; == mode then													-- if this template is to be rendered in CS1 (cite xxx) style&lt;br /&gt;
		sep, ps = set_cs1_style (ps);&lt;br /&gt;
	else																		-- anything but cs1 or cs2&lt;br /&gt;
		sep, ps, ref = get_settings_from_cite_class (ps, ref, cite_class);		-- get settings based on the template&#039;s CitationClass&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if cfg.keywords_xlate[ps:lower()] == &#039;none&#039; then							-- if assigned value is &#039;none&#039; then&lt;br /&gt;
		ps = &#039;&#039;;																-- set to empty string&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return sep, ps, ref&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 used by [[MediaWiki:Common.css]] when&lt;br /&gt;
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 if the format parameter does&lt;br /&gt;
not have a matching url parameter.  If the format parameter is not set and the url contains a file extension that&lt;br /&gt;
is recognized as a pdf document 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 is_set (format) then&lt;br /&gt;
		format = wrap_style (&#039;format&#039;, format);									-- add leading space, parentheses, resize&lt;br /&gt;
		if not is_set (url) then&lt;br /&gt;
			format = format .. set_error( &#039;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 = 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 name lists and a boolean flag&lt;br /&gt;
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, return the number and&lt;br /&gt;
the previous state of the &#039;etal&#039; flag (false by default but may have been set to true if the name list contains&lt;br /&gt;
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 that is one greater than the&lt;br /&gt;
number of authors in the list and set the &#039;etal&#039; flag true.  This will cause the list_people() to display all of&lt;br /&gt;
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)&lt;br /&gt;
	if 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;
				add_maint_cat (&#039;disp_name&#039;, cfg.special_case_translation [list_name]);&lt;br /&gt;
			end&lt;br /&gt;
		else																	-- not a valid keyword or number&lt;br /&gt;
			table.insert( z.message_tail, { set_error( &#039;invalid_param_val&#039;, {&#039;display-&#039; .. list_name, max}, true ) } );		-- 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 page to Category:CS1 maint: extra text if |page= or |pages= has what appears to be some form of p. or pp. &lt;br /&gt;
abbreviation in the first characters of the parameter content.&lt;br /&gt;
&lt;br /&gt;
check Page and Pages for extraneous p, p., pp, and pp. at start of parameter value:&lt;br /&gt;
	good pattern: &#039;^P[^%.P%l]&#039; matches when |page(s)= begins PX or P# but not Px where x and X are letters and # is a dgiit&lt;br /&gt;
	bad pattern: &#039;^[Pp][Pp]&#039; matches matches when |page(s)= begins pp or pP or Pp or PP&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function extra_text_in_page_check (page)&lt;br /&gt;
	local good_pattern = &#039;^P[^%.Pp]&#039;;											-- ok to begin with uppercase P: P7 (pg 7 of section P) but not p123 (page 123) TODO: add Gg for PG or Pg?&lt;br /&gt;
	local bad_pattern = &#039;^[Pp]?[Pp]%.?[ %d]&#039;;&lt;br /&gt;
&lt;br /&gt;
	if not page:match (good_pattern) and (page:match (bad_pattern) or  page:match (&#039;^[Pp]ages?&#039;)) then&lt;br /&gt;
		add_maint_cat (&#039;extra_text&#039;);&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 parnetheses 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 place holder&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 parens&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 parens&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 = 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 paranethese ((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 reqired 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;
		if v_name:match (&#039;^%(%(.+%)%)$&#039;) then									-- corporate authors are wrapped in doubled parentheses to supress vanc formatting and error detection&lt;br /&gt;
			last = v_name:match (&#039;^%(%((.+)%)%)$&#039;)								-- remove doubled parntheses&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);&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 intials 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 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);&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;]);				-- 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.name);							-- matches a space between two intiials&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 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);						-- 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);							-- check first and last before restoring the suffix which may have a non-Latin digit&lt;br /&gt;
			if 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;);&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		link = select_one( args, cfg.aliases[list_name .. &#039;-Link&#039;], &#039;redundant_parameters&#039;, i ) or v_link_table[i];&lt;br /&gt;
		mask = select_one( args, cfg.aliases[list_name .. &#039;-Mask&#039;], &#039;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 |editors=, |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 and&lt;br /&gt;
similarly, |editorn= (and aliases) highest and |editors= lowest&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 or editors 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 select_one( args, cfg.aliases[list_name .. &#039;-Last&#039;], &#039;none&#039;, 1 ) or		-- do this twice incase we have a |first1= without a |last1=; this ...&lt;br /&gt;
		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;
		select_one( args, cfg.aliases[list_name .. &#039;-Last&#039;], &#039;none&#039;, 2 ) or&lt;br /&gt;
		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 (is_set (vxxxxors) and true == lastfirst) or								-- these are the three error conditions&lt;br /&gt;
		(is_set (vxxxxors) and is_set (xxxxors)) or&lt;br /&gt;
		(true == lastfirst and 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;
			table.insert( z.message_tail, { set_error( &#039;redundant_parameters&#039;,&lt;br /&gt;
				{err_name .. &#039;-name-list parameters&#039;}, true ) } );				-- 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 is_set (vxxxxors) then return 2 end;&lt;br /&gt;
	if 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;
]]&lt;br /&gt;
&lt;br /&gt;
local function is_valid_parameter_value (value, name, possible, ret_val)&lt;br /&gt;
	if not is_set (value) then&lt;br /&gt;
		return ret_val;															-- an empty parameter is ok&lt;br /&gt;
	elseif in_array (value, possible) then&lt;br /&gt;
		return cfg.keywords_xlate[value];										-- return translation of parameter keyword&lt;br /&gt;
	else&lt;br /&gt;
		table.insert( z.message_tail, { set_error( &#039;invalid_param_val&#039;, {name, value}, true ) } );	-- 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 terninate 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 is_set (volume) and not is_set (issue) then&lt;br /&gt;
		return &#039;&#039;;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if &#039;magazine&#039; == cite_class or (in_array (cite_class, {&#039;citation&#039;, &#039;map&#039;}) and &#039;magazine&#039; == origin) then&lt;br /&gt;
		if is_set (volume) and is_set (issue) then&lt;br /&gt;
			return wrap_msg (&#039;vol-no&#039;, {sepc, volume, issue}, lower);&lt;br /&gt;
		elseif is_set (volume) then&lt;br /&gt;
			return wrap_msg (&#039;vol&#039;, {sepc, 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;
	if &#039;podcast&#039; == cite_class and 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;
	local vol = &#039;&#039;;																-- here for all cites except magazine&lt;br /&gt;
		&lt;br /&gt;
	if is_set (volume) then&lt;br /&gt;
		if volume:match (&#039;^[MDCLXVI]+$&#039;) or volume:match (&#039;^%d+$&#039;)then			-- volume value is all digits or all uppercase roman numerals&lt;br /&gt;
			vol = substitute (cfg.presentation[&#039;vol-bold&#039;], {sepc, hyphen_to_dash(volume)});	-- render in bold face&lt;br /&gt;
		elseif (4 &amp;lt; mw.ustring.len(volume)) then								-- not all digits or roman numerals and longer than 4 characters&lt;br /&gt;
			vol = substitute (cfg.messages[&#039;j-vol&#039;], {sepc, volume});			-- not bold&lt;br /&gt;
			add_prop_cat (&#039;long_vol&#039;);&lt;br /&gt;
		else																	-- four or less characters&lt;br /&gt;
			vol = substitute (cfg.presentation[&#039;vol-bold&#039;], {sepc, hyphen_to_dash(volume)});	-- bold&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if is_set (issue) then&lt;br /&gt;
		return vol .. 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;
&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 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 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 (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 is_set (page) then&lt;br /&gt;
		if is_journal then&lt;br /&gt;
			return 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 substitute (cfg.messages[&#039;p-prefix&#039;], {sepc, page}), &#039;&#039;, &#039;&#039;, &#039;&#039;;&lt;br /&gt;
		else&lt;br /&gt;
			return substitute (cfg.messages[&#039;nopp&#039;], {sepc, page}), &#039;&#039;, &#039;&#039;, &#039;&#039;;&lt;br /&gt;
		end&lt;br /&gt;
	elseif is_set(pages) then&lt;br /&gt;
		if is_journal then&lt;br /&gt;
			return 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;, 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;, substitute (cfg.messages[&#039;pp-prefix&#039;], {sepc, pages}), &#039;&#039;, &#039;&#039;;&lt;br /&gt;
		else&lt;br /&gt;
			return &#039;&#039;, 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 interwikilink as plain text&lt;br /&gt;
for use in COinS.  This COinS thing is done because here we convert an interwiki link to and 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, pages, at)&lt;br /&gt;
	local ws_url, ws_label, coins_pages, L;										-- for wikisource interwikilinks; TODO: this corrupts page metadata (span remains in place after cleanup; fix there?)&lt;br /&gt;
&lt;br /&gt;
	if is_set (page) then&lt;br /&gt;
		if is_set (pages) or 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);										-- add this page to maint cat if |page= value begins with what looks like p. or pp.&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 tool tip 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 = 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 is_set (pages) then&lt;br /&gt;
		if is_set (at) then&lt;br /&gt;
			at = &#039;&#039;;															-- unset&lt;br /&gt;
		end&lt;br /&gt;
		extra_text_in_page_check (pages);										-- add this page to maint cat if |pages= value begins with what looks like p. or pp.&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 tool tip 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 = 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 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 tool tip 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 = 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;
&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 funct 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.or 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;
		&lt;br /&gt;
		if not is_set(timestamp) or 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;
				url=url:gsub (&#039;(//web%.archive%.org/[^%d]*%d?%d?%d?%d?%d?%d?)[^/]*&#039;, &#039;%1*&#039;, 1)	-- for preview, modify ts to be yearmo* max (0-6 digits plus splat)&lt;br /&gt;
			end&lt;br /&gt;
		elseif 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 is_set (flag) and not 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 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;
	table.insert( z.message_tail, { set_error( &#039;archive_url&#039;, {err_msg}, true ) } );	-- add error message and&lt;br /&gt;
	if is_set (Frame:preprocess(&#039;{{REVISIONID}}&#039;)) then&lt;br /&gt;
		return &#039;&#039;, &#039;&#039;;															-- return empty strings for ArchiveURL and ArchiveDate&lt;br /&gt;
	else&lt;br /&gt;
		return url, date;														-- preview mode so return 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 mis-use 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 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;
		add_maint_cat (&#039;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; 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 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;
&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;
&lt;br /&gt;
	local NameListFormat = is_valid_parameter_value (A[&#039;NameListFormat&#039;], A:ORIGIN(&#039;NameListFormat&#039;), cfg.keywords_lists[&#039;name-list-format&#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;
			NameListFormat = &#039;vanc&#039;;											-- override whatever |name-list-format= 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;
				add_maint_cat (&#039;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 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 Others = A[&#039;Others&#039;];&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;
	local Editors;&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;], A[&#039;Editors&#039;], args, &#039;EditorList&#039;);&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;
			NameListFormat = &#039;vanc&#039;;											-- override whatever |name-list-format= 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;
		elseif 3 == selected then&lt;br /&gt;
			Editors = A[&#039;Editors&#039;];												-- use content of |editors=&lt;br /&gt;
			add_maint_cat (&#039;editors&#039;);											-- but add a maint cat because use of this parameter is discouraged&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local translator_etal;&lt;br /&gt;
	local t = {};																-- translators list from |translator-lastn= / translator-firstn= pairs&lt;br /&gt;
	local Translators;															-- assembled translators name list&lt;br /&gt;
	t = extract_names (args, &#039;TranslatorList&#039;);									-- fetch translator list from |translatorn= / |translator-lastn=, -firstn=, -linkn=, -maskn=&lt;br /&gt;
&lt;br /&gt;
	local interviewer_etal;&lt;br /&gt;
	local interviewers_list = {};												&lt;br /&gt;
	local Interviewers;															-- used later&lt;br /&gt;
	interviewers_list = extract_names (args, &#039;InterviewerList&#039;);				-- process preferred interviewers parameters&lt;br /&gt;
&lt;br /&gt;
	local contributor_etal;&lt;br /&gt;
	local c = {};																-- contributors list from |contributor-lastn= / contributor-firstn= pairs&lt;br /&gt;
	local Contributors;															-- assembled contributors name list&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; == A:ORIGIN (&#039;Chapter&#039;) then&lt;br /&gt;
			Contribution = A[&#039;Chapter&#039;];										-- get the name of the contribution&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
	if in_array(config.CitationClass, {&amp;quot;book&amp;quot;,&amp;quot;citation&amp;quot;}) and not 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 is_set (Contribution) then									-- |contributor= requires |contribution=&lt;br /&gt;
				table.insert( z.message_tail, { set_error( &#039;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;
				table.insert( z.message_tail, { set_error( &#039;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 select_one (args, cfg.aliases[&#039;ContributorList-Last&#039;], &#039;redundant_parameters&#039;, 1 ) then	-- are there contributor name list parameters?&lt;br /&gt;
			table.insert( z.message_tail, { set_error( &#039;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;
	if is_set (Others) then&lt;br /&gt;
		if 0 == #a and 0 == #e then												-- add maint cat when |others= has value and used without |author=, |editor=&lt;br /&gt;
			add_maint_cat (&#039;others&#039;);&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local Year = A[&#039;Year&#039;];&lt;br /&gt;
	local PublicationDate = A[&#039;PublicationDate&#039;];&lt;br /&gt;
	local OrigYear = A[&#039;OrigYear&#039;];&lt;br /&gt;
	local Date = A[&#039;Date&#039;];&lt;br /&gt;
	local LayDate = A[&#039;LayDate&#039;];&lt;br /&gt;
	------------------------------------------------- Get title data&lt;br /&gt;
	local Title = A[&#039;Title&#039;];&lt;br /&gt;
	local ScriptTitle = A[&#039;ScriptTitle&#039;];&lt;br /&gt;
	local BookTitle = A[&#039;BookTitle&#039;];&lt;br /&gt;
	local Conference = A[&#039;Conference&#039;];&lt;br /&gt;
	local TransTitle = A[&#039;TransTitle&#039;];&lt;br /&gt;
	local TransTitle_origin = A:ORIGIN (&#039;TransTitle&#039;);&lt;br /&gt;
	local TitleNote = A[&#039;TitleNote&#039;];&lt;br /&gt;
	local TitleLink = A[&#039;TitleLink&#039;];&lt;br /&gt;
			link_title_ok (TitleLink, A:ORIGIN (&#039;TitleLink&#039;), Title, &#039;title&#039;);	-- check for wikimarkup in |title-link= or wikimarkup 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 concatnation if not used&lt;br /&gt;
		if &#039;map&#039; == config.CitationClass and &#039;section&#039; == A:ORIGIN (&#039;Chapter&#039;) 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 ScriptChapter = A[&#039;ScriptChapter&#039;];&lt;br /&gt;
	local ScriptChapter_origin = A:ORIGIN (&#039;ScriptChapter&#039;);&lt;br /&gt;
	local ChapterLink	-- = A[&#039;ChapterLink&#039;];									-- deprecated as a parameter but still used internally by cite episode&lt;br /&gt;
	local TransChapter = A[&#039;TransChapter&#039;];&lt;br /&gt;
	local TransChapter_origin = A:ORIGIN (&#039;TransChapter&#039;);&lt;br /&gt;
	local TitleType = A[&#039;TitleType&#039;];&lt;br /&gt;
	local Degree = A[&#039;Degree&#039;];&lt;br /&gt;
	local Docket = A[&#039;Docket&#039;];&lt;br /&gt;
	local ArchiveFormat = A[&#039;ArchiveFormat&#039;];&lt;br /&gt;
&lt;br /&gt;
	local ArchiveDate;&lt;br /&gt;
	local ArchiveURL;&lt;br /&gt;
&lt;br /&gt;
	ArchiveURL, ArchiveDate = archive_url_check (A[&#039;ArchiveURL&#039;], A[&#039;ArchiveDate&#039;])&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;
&lt;br /&gt;
&lt;br /&gt;
	local URL = A[&#039;URL&#039;]&lt;br /&gt;
	local URL_origin = A:ORIGIN(&#039;URL&#039;);											-- get name of parameter that holds URL&lt;br /&gt;
	local ChapterURL = A[&#039;ChapterURL&#039;];&lt;br /&gt;
	local ChapterURL_origin = A:ORIGIN(&#039;ChapterURL&#039;);							-- get name of parameter that holds ChapterURL&lt;br /&gt;
	local ConferenceFormat = A[&#039;ConferenceFormat&#039;];&lt;br /&gt;
	local ConferenceURL = A[&#039;ConferenceURL&#039;];&lt;br /&gt;
	local ConferenceURL_origin = A:ORIGIN(&#039;ConferenceURL&#039;);						-- get name of parameter that holds ConferenceURL&lt;br /&gt;
&lt;br /&gt;
	local Periodical = A[&#039;Periodical&#039;];&lt;br /&gt;
	local Periodical_origin = &#039;&#039;;&lt;br /&gt;
		if 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 = strip_apostrophe_markup (Periodical);				-- strip appostrophe 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;
				table.insert( z.message_tail, {set_error (&#039;apostrophe_markup&#039;, {Periodical_origin}, true)});&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 is_set (Periodical) and is_set (A [&#039;MailingList&#039;]) then						-- both set emit an error&lt;br /&gt;
			table.insert( z.message_tail, { set_error(&#039;redundant_parameters&#039;, {wrap_style (&#039;parameter&#039;, Periodical_origin) .. &#039; and &#039; .. wrap_style (&#039;parameter&#039;, &#039;mailinglist&#039;)}, true )});&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;
&lt;br /&gt;
&lt;br /&gt;
																				&lt;br /&gt;
	local ScriptPeriodical = A[&#039;ScriptPeriodical&#039;];&lt;br /&gt;
	local ScriptPeriodical_origin = A:ORIGIN(&#039;ScriptPeriodical&#039;);&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 (is_set (Periodical) or 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;
				table.insert( z.message_tail, {set_error (&#039;missing_periodical&#039;, {config.CitationClass, p[config.CitationClass]}, true)});&lt;br /&gt;
			end&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;
&lt;br /&gt;
	local Series = A[&#039;Series&#039;];&lt;br /&gt;
	&lt;br /&gt;
	local Volume;&lt;br /&gt;
	local Issue;&lt;br /&gt;
	local Page;&lt;br /&gt;
	local Pages;&lt;br /&gt;
	local At;&lt;br /&gt;
&lt;br /&gt;
	if &#039;citation&#039; == config.CitationClass then&lt;br /&gt;
		if is_set (Periodical) then&lt;br /&gt;
			if not in_array (Periodical_origin, {&#039;website&#039;, &#039;mailinglist&#039;}) then	-- {{citation}} does not render volume for these &#039;periodicals&#039;&lt;br /&gt;
				Volume = A[&#039;Volume&#039;];											-- but does for all other &#039;periodicals&#039;&lt;br /&gt;
			end&lt;br /&gt;
		elseif 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 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;
&lt;br /&gt;
	if &#039;citation&#039; == config.CitationClass then&lt;br /&gt;
		if is_set (Periodical) and in_array (Periodical_origin, {&#039;journal&#039;, &#039;magazine&#039;, &#039;newspaper&#039;, &#039;periodical&#039;, &#039;work&#039;}) or	-- {{citation}} renders issue for these &#039;periodicals&#039;&lt;br /&gt;
			is_set (ScriptPeriodical) and in_array (ScriptPeriodical_origin, {&#039;script-journal&#039;, &#039;script-magazine&#039;, &#039;script-newspaper&#039;, &#039;script-periodical&#039;, &#039;script-work&#039;}) then -- and these &#039;script-periodicals&#039;&lt;br /&gt;
				Issue = hyphen_to_dash (A[&#039;Issue&#039;]);&lt;br /&gt;
		end&lt;br /&gt;
	elseif 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 (in_array (config.CitationClass, {&#039;conference&#039;, &#039;map&#039;, &#039;citation&#039;}) and not (is_set (Periodical) or is_set (ScriptPeriodical))) then&lt;br /&gt;
			Issue = hyphen_to_dash (A[&#039;Issue&#039;]);&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local Position = &#039;&#039;;&lt;br /&gt;
	if not in_array (config.CitationClass, cfg.templates_not_using_page) then&lt;br /&gt;
		Page = A[&#039;Page&#039;];&lt;br /&gt;
		Pages = 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 is_set (PublisherName) then&lt;br /&gt;
			local i=0;&lt;br /&gt;
			PublisherName, i = strip_apostrophe_markup (PublisherName);			-- strip appostrophe markup so that metadata isn&#039;t contaminated; publisher is never italicized&lt;br /&gt;
&lt;br /&gt;
			if i then															-- non-zero when markup was stripped so emit an error message&lt;br /&gt;
				table.insert( z.message_tail, {set_error (&#039;apostrophe_markup&#039;, {PublisherName_origin}, true)});&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 is_set (PublisherName) then											-- general use parmeter |publisher= not allowed in cite newsgroup&lt;br /&gt;
			local error_text = set_error (&#039;parameter_ignored&#039;, {PublisherName_origin}, true);&lt;br /&gt;
			if is_set (error_text) then&lt;br /&gt;
				table.insert( z.message_tail, {error_text, error_state} );&lt;br /&gt;
			end				&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 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;
		if not is_set(URL) and is_set(UrlAccess) then&lt;br /&gt;
			UrlAccess = nil;&lt;br /&gt;
			table.insert( z.message_tail, { set_error( &#039;param_access_requires_param&#039;, {&#039;url&#039;}, true ) } );&lt;br /&gt;
		end&lt;br /&gt;
		&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 is_set(ChapterURL) and is_set(ChapterUrlAccess) then&lt;br /&gt;
			ChapterUrlAccess = nil;&lt;br /&gt;
			table.insert( z.message_tail, { set_error( &#039;param_access_requires_param&#039;, {A:ORIGIN(&#039;ChapterUrlAccess&#039;):gsub (&#039;%-access&#039;, &#039;&#039;)}, true ) } );&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 is_set(A[&#039;MapURL&#039;]) and is_set(MapUrlAccess) then&lt;br /&gt;
			MapUrlAccess = nil;&lt;br /&gt;
			table.insert( z.message_tail, { set_error( &#039;param_access_requires_param&#039;, {&#039;map-url&#039;}, true ) } );&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
	local Via = A[&#039;Via&#039;];&lt;br /&gt;
	local AccessDate = A[&#039;AccessDate&#039;];&lt;br /&gt;
	local Agency = A[&#039;Agency&#039;];&lt;br /&gt;
&lt;br /&gt;
	local Language = A[&#039;Language&#039;];&lt;br /&gt;
	local Format = A[&#039;Format&#039;];&lt;br /&gt;
	local ChapterFormat = A[&#039;ChapterFormat&#039;];&lt;br /&gt;
	local DoiBroken = A[&#039;DoiBroken&#039;];&lt;br /&gt;
	local ID = A[&#039;ID&#039;];&lt;br /&gt;
	local ASINTLD = A[&#039;ASINTLD&#039;];&lt;br /&gt;
	local IgnoreISBN = is_valid_parameter_value (A[&#039;IgnoreISBN&#039;], A:ORIGIN(&#039;IgnoreISBN&#039;), cfg.keywords_lists[&#039;yes_true_y&#039;], nil);&lt;br /&gt;
	local Embargo = A[&#039;Embargo&#039;];&lt;br /&gt;
	local Class = A[&#039;Class&#039;];													-- arxiv class identifier&lt;br /&gt;
&lt;br /&gt;
	local ID_list = extract_ids( args );&lt;br /&gt;
		if is_set (DoiBroken) and not ID_list[&#039;DOI&#039;] then&lt;br /&gt;
			table.insert( z.message_tail, { set_error( &#039;doibroken_missing_doi&#039;, A:ORIGIN(&#039;DoiBroken&#039;))});&lt;br /&gt;
		end&lt;br /&gt;
	local ID_access_levels = extract_id_access_levels( args, ID_list );&lt;br /&gt;
&lt;br /&gt;
	local Quote = A[&#039;Quote&#039;];&lt;br /&gt;
&lt;br /&gt;
	local LayFormat = A[&#039;LayFormat&#039;];&lt;br /&gt;
	local LayURL = A[&#039;LayURL&#039;];&lt;br /&gt;
	local LaySource = A[&#039;LaySource&#039;];&lt;br /&gt;
	local Transcript = A[&#039;Transcript&#039;];&lt;br /&gt;
	local TranscriptFormat = A[&#039;TranscriptFormat&#039;];&lt;br /&gt;
	local TranscriptURL = A[&#039;TranscriptURL&#039;] &lt;br /&gt;
	local TranscriptURL_origin = A:ORIGIN(&#039;TranscriptURL&#039;);						-- get name of parameter that holds TranscriptURL&lt;br /&gt;
&lt;br /&gt;
	local LastAuthorAmp = is_valid_parameter_value (A[&#039;LastAuthorAmp&#039;], A:ORIGIN(&#039;LastAuthorAmp&#039;), cfg.keywords_lists[&#039;yes_true_y&#039;], nil);&lt;br /&gt;
&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;
	--local variables that are not cs1 parameters&lt;br /&gt;
	local use_lowercase;														-- controls capitalization of certain static text&lt;br /&gt;
	local this_page = mw.title.getCurrentTitle();								-- also used for COinS and for language&lt;br /&gt;
	local anchor_year;															-- used in the CITEREF identifier&lt;br /&gt;
	local COinS_date = {};														-- holds date info extracted from |date= for the COinS metadata by Module:Date verification&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 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 sepc;																	-- separator between citation elements for CS1 a period, for CS2, a comma&lt;br /&gt;
	local PostScript;&lt;br /&gt;
	local Ref = A[&#039;Ref&#039;];&lt;br /&gt;
	if &#039;harv&#039; == Ref then&lt;br /&gt;
		add_maint_cat (&#039;ref_harv&#039;);												-- add maint cat to identify templates that have this now-extraneous param value&lt;br /&gt;
	elseif not is_set (Ref) then&lt;br /&gt;
		Ref = &#039;harv&#039;;															-- set as default when not set externally&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	sepc, PostScript, Ref = set_style (Mode:lower(), A[&#039;PostScript&#039;], Ref, config.CitationClass);&lt;br /&gt;
	use_lowercase = ( sepc == &#039;,&#039; );											-- used to control capitalization for certain static text&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 is_set (no_tracking_cats) then										-- ignore if we are already not going to categorize this page&lt;br /&gt;
		if 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;
	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;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, Pages, 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 is_set (PublicationPlace) and is_set (Place) then						-- both |publication-place= and |place= (|location=) allowed if different&lt;br /&gt;
		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 is_set (PublicationPlace) and 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;
	--[[&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 |chapterurl 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 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;
			table.insert (z.message_tail, {set_error (&#039;parameter_ignored&#039;, {A:ORIGIN (&#039;Encyclopedia&#039;)}, true)});&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 is_set (Encyclopedia)) then&lt;br /&gt;
		if is_set (Periodical) and is_set (Encyclopedia) then					-- when both set emit an error&lt;br /&gt;
			table.insert (z.message_tail, {set_error(&#039;redundant_parameters&#039;, {wrap_style (&#039;parameter&#039;, A:ORIGIN (&#039;Encyclopedia&#039;)) .. &#039; and &#039; .. wrap_style (&#039;parameter&#039;, Periodical_origin)}, true )});&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		if 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 is_set (Periodical) then												-- Periodical is set when |encyclopedia is set&lt;br /&gt;
			if is_set(Title) or is_set (ScriptTitle) then&lt;br /&gt;
				if not 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 = A:ORIGIN(&#039;URL&#039;)&lt;br /&gt;
&lt;br /&gt;
					ChapterUrlAccess = UrlAccess;&lt;br /&gt;
&lt;br /&gt;
					if not is_set (ChapterURL) and is_set (TitleLink) then&lt;br /&gt;
						Chapter = 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 is_set (Chapter) 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;
	if (config.CitationClass == &amp;quot;techreport&amp;quot;) then								-- special case for cite techreport&lt;br /&gt;
		if 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 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;
				table.insert( z.message_tail, { set_error(&#039;redundant_parameters&#039;, {wrap_style (&#039;parameter&#039;, &#039;id&#039;) .. &#039; and &#039; .. wrap_style (&#039;parameter&#039;, &#039;number&#039;)}, true )});&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;
	if &#039;conference&#039; == config.CitationClass then&lt;br /&gt;
		if is_set(BookTitle) then&lt;br /&gt;
			Chapter = Title;&lt;br /&gt;
			Chapter_origin = &#039;title&#039;;&lt;br /&gt;
	--		ChapterLink = TitleLink;											-- |chapterlink= 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;
	-- 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 is_set (Chapter) then&lt;br /&gt;
			table.insert( z.message_tail, { set_error( &#039;redundant_parameters&#039;, {wrap_style (&#039;parameter&#039;, &#039;map&#039;) .. &#039; and &#039; .. wrap_style (&#039;parameter&#039;, Chapter_origin)}, true ) } );	-- 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 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 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;
	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;
		link_title_ok (SeriesLink, A:ORIGIN (&#039;SeriesLink&#039;), Series, &#039;series&#039;);	-- check for wikimarkup in |series-link= or wikimarkup 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 is_set(Network) then table.insert(n, Network); end&lt;br /&gt;
		if 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 is_set (Season) and is_set (SeriesNumber) then					-- these are mutually exclusive so if both are set&lt;br /&gt;
				table.insert( z.message_tail, { set_error( &#039;redundant_parameters&#039;, {wrap_style (&#039;parameter&#039;, &#039;season&#039;) .. &#039; and &#039; .. wrap_style (&#039;parameter&#039;, &#039;seriesno&#039;)}, true ) } );		-- 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 is_set(Season) then table.insert(s, wrap_msg (&#039;season&#039;, Season, use_lowercase)); end&lt;br /&gt;
			if is_set(SeriesNumber) then table.insert(s, wrap_msg (&#039;seriesnum&#039;, SeriesNumber, use_lowercase)); end&lt;br /&gt;
			if 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 episodelink&lt;br /&gt;
			TransChapter = TransTitle;&lt;br /&gt;
			ChapterURL = URL;&lt;br /&gt;
			ChapterUrlAccess = UrlAccess;&lt;br /&gt;
			ChapterURL_origin = A:ORIGIN(&#039;URL&#039;);&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 is_set (ChapterLink) and not is_set (ChapterURL) then			-- link but not URL&lt;br /&gt;
				Chapter = make_wikilink (ChapterLink, Chapter);&lt;br /&gt;
			elseif is_set (ChapterLink) and is_set (ChapterURL) then			-- if both are set, URL links episode;&lt;br /&gt;
				Series = 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;
			&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 is_set (Series) and is_set (SeriesLink) then&lt;br /&gt;
				Series = make_wikilink (SeriesLink, Series);&lt;br /&gt;
			end&lt;br /&gt;
			Series = 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;
	-- Account for the oddities that are {{cite arxiv}}, {{cite biorxiv}}, {{cite citeseerx}}, {{cite ssrn}}, before generation of COinS data.&lt;br /&gt;
	do&lt;br /&gt;
		if in_array (config.CitationClass, whitelist.preprint_template_list) then&lt;br /&gt;
			if not is_set (ID_list[config.CitationClass:upper()]) then			-- |arxiv= or |eprint= required for cite arxiv; |biorxiv= &amp;amp; |citeseerx= required for their templates&lt;br /&gt;
				table.insert( z.message_tail, { set_error( config.CitationClass .. &#039;_missing&#039;, {}, true ) } );	-- 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;
	end&lt;br /&gt;
&lt;br /&gt;
	-- handle type parameter for those CS1 citations that have default values&lt;br /&gt;
	if in_array(config.CitationClass, {&amp;quot;AV-media-notes&amp;quot;, &amp;quot;interview&amp;quot;, &amp;quot;mailinglist&amp;quot;, &amp;quot;map&amp;quot;, &amp;quot;podcast&amp;quot;, &amp;quot;pressrelease&amp;quot;, &amp;quot;report&amp;quot;, &amp;quot;techreport&amp;quot;, &amp;quot;thesis&amp;quot;}) then&lt;br /&gt;
		TitleType = set_titletype (config.CitationClass, TitleType);&lt;br /&gt;
		if 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 is_set(TitleType) then													-- if type parameter is specified&lt;br /&gt;
		TitleType = 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_origin;															-- to hold the name of parameter promoted to Date; required for date error messaging&lt;br /&gt;
&lt;br /&gt;
	if not 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 is_set (Date) and 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;
	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;embargo&#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;
		anchor_year, Embargo, error_message = dates(date_parameters_list, COinS_date);&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;
			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 is_set (Year) and is_set (Date) then									-- both |date= and |year= not normally needed; &lt;br /&gt;
			local mismatch = year_date_check (Year, Date)&lt;br /&gt;
			if 0 == mismatch then												-- |year= does not match a year-value in |date=&lt;br /&gt;
				if is_set (error_message) then									-- if there is already an error message&lt;br /&gt;
					error_message = error_message .. &#039;, &#039;;						-- tack on this additional message&lt;br /&gt;
				end&lt;br /&gt;
				error_message = error_message .. &#039;&amp;amp;#124;year= / &amp;amp;#124;date= mismatch&#039;;&lt;br /&gt;
			elseif 1 == mismatch then											-- |year= matches year-value in |date=&lt;br /&gt;
				add_maint_cat (&#039;date_year&#039;);&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		if not is_set(error_message) then										-- error free dates only&lt;br /&gt;
			local modified = false;												-- flag&lt;br /&gt;
			&lt;br /&gt;
			if is_set (DF) then													-- if we need to reformat dates&lt;br /&gt;
				modified = reformat_dates (date_parameters_list, DF, false);	-- reformat to DF format, use long month names if appropriate&lt;br /&gt;
			end&lt;br /&gt;
&lt;br /&gt;
			if true == date_hyphen_to_dash (date_parameters_list) then			-- convert hyphens to dashes where appropriate&lt;br /&gt;
				modified = true;&lt;br /&gt;
				add_maint_cat (&#039;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,&lt;br /&gt;
	-- uncomment these three lines.  Not supported by en.wiki (for obvious reasons)&lt;br /&gt;
	-- set date_name_xlate() second argument to true to translate English digits to local digits (will translate ymd dates)&lt;br /&gt;
	--		if date_name_xlate (date_parameters_list, false) then&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;
			table.insert( z.message_tail, { set_error( &#039;bad_date&#039;, {error_message}, true ) } );	-- add this error message&lt;br /&gt;
		end&lt;br /&gt;
	end	-- end of do&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;
	-- Here we unset Embargo if PMC not embargoed (|embargo= not set in the citation) or if the embargo time has expired. Otherwise, holds embargo date&lt;br /&gt;
	Embargo = is_embargoed (Embargo);&lt;br /&gt;
	&lt;br /&gt;
	if config.CitationClass == &amp;quot;journal&amp;quot; and not is_set(URL) and not is_set(TitleLink) then&lt;br /&gt;
		if is_set(ID_list[&#039;PMC&#039;]) and not is_set (Embargo) then											-- if not embargoed or embargo has expired&lt;br /&gt;
			URL=cfg.id_handlers[&#039;PMC&#039;].prefix .. ID_list[&#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 is_set(ID_list[&#039;DOI&#039;]) and ID_access_levels[&#039;DOI&#039;] == &amp;quot;free&amp;quot; then&lt;br /&gt;
			URL=cfg.id_handlers[&#039;DOI&#039;].prefix .. ID_list[&#039;DOI&#039;];&lt;br /&gt;
			URL_origin = cfg.id_handlers[&#039;DOI&#039;].parameters[1];&lt;br /&gt;
		end&lt;br /&gt;
		if is_set(URL) and is_set(AccessDate) then								-- access date requires |url=; pmc or doi created url is not |url=&lt;br /&gt;
			table.insert( z.message_tail, { set_error( &#039;accessdate_missing_url&#039;, {}, true ) } );&lt;br /&gt;
			AccessDate = &#039;&#039;;												-- unset&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 is_set(Title) and not is_set(TransTitle) and not is_set(ScriptTitle) then	-- has special case for cite episode&lt;br /&gt;
		table.insert( z.message_tail, { set_error( &#039;citation_missing_title&#039;, {&#039;episode&#039; == config.CitationClass and &#039;series&#039; or &#039;title&#039;}, true ) } );&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if cfg.keywords_xlate[Title] == &#039;none&#039; and&lt;br /&gt;
			in_array (config.CitationClass, {&#039;journal&#039;, &#039;citation&#039;}) and&lt;br /&gt;
			(is_set (Periodical) or 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;
				add_maint_cat (&#039;untitled&#039;);&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	check_for_url ({															-- add error message when any of these parameters hold a URL&lt;br /&gt;
		[&#039;title&#039;]=Title,&lt;br /&gt;
		[A:ORIGIN(&#039;Chapter&#039;)]=Chapter,&lt;br /&gt;
		[Periodical_origin] = Periodical,&lt;br /&gt;
		[PublisherName_origin] = PublisherName&lt;br /&gt;
		});&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 is_set (Encyclopedia)) then&lt;br /&gt;
		if is_set (Chapter) and is_set (Title) and 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;
	-- this is the function call to COinS()&lt;br /&gt;
	local OCinSoutput = COinS({&lt;br /&gt;
		[&#039;Periodical&#039;] = 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;] = make_coins_title (coins_chapter, ScriptChapter),			-- Chapter and ScriptChapter stripped of bold / italic wikimarkup&lt;br /&gt;
		[&#039;Degree&#039;] = Degree;													-- cite thesis only&lt;br /&gt;
		[&#039;Title&#039;] = make_coins_title (coins_title, ScriptTitle),				-- Title and ScriptTitle stripped of bold / italic wikimarkup&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 get_coins_pages (first_set ({Sheet, Sheets, Page, Pages, At}, 5)),	-- 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,&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 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 is_set (Newsgroup) then&lt;br /&gt;
		PublisherName = 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;
	-- 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;
	local EditorCount;															-- used only for choosing {ed.) or (eds.) annotation at end of editor name-list&lt;br /&gt;
	do&lt;br /&gt;
		local last_first_list;&lt;br /&gt;
		local control = { &lt;br /&gt;
			format = NameListFormat,											-- empty string or &#039;vanc&#039;&lt;br /&gt;
			maximum = nil,														-- as if display-authors or display-editors not set&lt;br /&gt;
			lastauthoramp = LastAuthorAmp,&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);&lt;br /&gt;
			last_first_list, EditorCount = list_people(control, e, editor_etal);&lt;br /&gt;
&lt;br /&gt;
			if is_set (Editors) then&lt;br /&gt;
				Editors, editor_etal = name_has_etal (Editors, editor_etal, false, &#039;editors&#039;);	-- find and remove variations on et al.&lt;br /&gt;
				if editor_etal then&lt;br /&gt;
					Editors = Editors .. &#039; &#039; .. cfg.messages[&#039;et al&#039;];			-- add et al. to editors parameter beause |display-editors=etal&lt;br /&gt;
				end&lt;br /&gt;
				EditorCount = 2;												-- we don&#039;t know but assume |editors= is multiple names; spoof to display (eds.) annotation&lt;br /&gt;
			else&lt;br /&gt;
				Editors = last_first_list;										-- either an author name list or an empty string&lt;br /&gt;
			end&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);&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);&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);&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);&lt;br /&gt;
&lt;br /&gt;
			last_first_list = list_people(control, a, author_etal);&lt;br /&gt;
&lt;br /&gt;
			if 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 is_set (Authors) and 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;
	-- apply |[xx-]format= styling; at the end, these parameters hold correctly styled format annotation,&lt;br /&gt;
	-- an error message if the associated url is not set, or an empty string for concatenation&lt;br /&gt;
	ArchiveFormat = style_format (ArchiveFormat, ArchiveURL, &#039;archive-format&#039;, &#039;archive-url&#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;
	LayFormat = style_format (LayFormat, LayURL, &#039;lay-format&#039;, &#039;lay-url&#039;);&lt;br /&gt;
	TranscriptFormat = style_format (TranscriptFormat, TranscriptURL, &#039;transcript-format&#039;, &#039;transcripturl&#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 (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 (is_set (Periodical) or is_set (ScriptPeriodical)) and not 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 is_set(URL) then&lt;br /&gt;
		if 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;
				table.insert( z.message_tail, { set_error( &#039;cite_web_url&#039;, {}, true ) } );&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		-- do we have |accessdate= without either |url= or |chapter-url=?&lt;br /&gt;
		if is_set(AccessDate) and not is_set(ChapterURL)then					-- ChapterURL may be set when URL is not set;&lt;br /&gt;
			table.insert( z.message_tail, { set_error( &#039;accessdate_missing_url&#039;, {}, true ) } );&lt;br /&gt;
			AccessDate = &#039;&#039;;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local OriginalURL, OriginalURL_origin, OriginalFormat, OriginalAccess;&lt;br /&gt;
	UrlStatus = UrlStatus:lower();												-- used later when assembling archived text&lt;br /&gt;
	if is_set( ArchiveURL ) then&lt;br /&gt;
		if 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 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;
	end&lt;br /&gt;
&lt;br /&gt;
	if 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 (is_set (Periodical) or is_set (ScriptPeriodical)) and not is_set (Encyclopedia)) then&lt;br /&gt;
			local chap_param;&lt;br /&gt;
			if 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 is_set (TransChapter) then&lt;br /&gt;
				chap_param = A:ORIGIN (&#039;TransChapter&#039;)&lt;br /&gt;
			elseif is_set (ChapterURL) then&lt;br /&gt;
				chap_param = A:ORIGIN (&#039;ChapterURL&#039;)&lt;br /&gt;
			elseif is_set (ScriptChapter) then&lt;br /&gt;
				chap_param = ScriptChapter_origin;&lt;br /&gt;
			else is_set (ChapterFormat)&lt;br /&gt;
				chap_param = A:ORIGIN (&#039;ChapterFormat&#039;)&lt;br /&gt;
			end&lt;br /&gt;
&lt;br /&gt;
			if is_set (chap_param) then											-- if we found one&lt;br /&gt;
				table.insert( z.message_tail, { set_error( &#039;chapter_ignored&#039;, {chap_param}, true ) } );		-- 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 is_set (Contribution) and 0 &amp;lt; #c then								-- if this is a contribution with contributor(s)&lt;br /&gt;
			if 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 is_set (Chapter) then&lt;br /&gt;
			Chapter = Chapter .. ChapterFormat ;&lt;br /&gt;
			if &#039;map&#039; == config.CitationClass and 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 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;
	if is_set (ArchiveURL) and &lt;br /&gt;
		(mw.ustring.match (mw.ustring.lower(Title), cfg.special_case_translation.archived_copy.en) or	-- if title is &#039;Archived copy&#039; (place holder added by bots that can&#039;t find proper title)&lt;br /&gt;
		mw.ustring.match (mw.ustring.lower(Title), cfg.special_case_translation.archived_copy[&#039;local&#039;])) then	-- local-wiki&#039;s form&lt;br /&gt;
			add_maint_cat (&#039;archived_copy&#039;);									-- add maintenance category before we modify the content of Title&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if Title:match (&#039;^%(%(.*%)%)$&#039;) then										-- if keep as written markup:&lt;br /&gt;
		Title= Title:gsub (&#039;^%(%((.*)%)%)$&#039;, &#039;%1&#039;)								-- remove the markup&lt;br /&gt;
	else&lt;br /&gt;
		if &#039;...&#039; == Title:sub (-3) then											-- if elipsis 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;
	end&lt;br /&gt;
&lt;br /&gt;
	if 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 (is_set (Periodical) or is_set (ScriptPeriodical)) and not is_set (Encyclopedia)) or&lt;br /&gt;
		(&#039;map&#039; == config.CitationClass and (is_set (Periodical) or 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 = 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 atribute, categorization, etc; must be done after title is wrapped&lt;br /&gt;
			TransTitle= wrap_style (&#039;trans-quoted-title&#039;, TransTitle );&lt;br /&gt;
	elseif &#039;report&#039; == config.CitationClass then								-- no styling for cite report&lt;br /&gt;
		Title = script_concatenate (Title, ScriptTitle, &#039;script-title&#039;);		-- &amp;lt;bdi&amp;gt; tags, lang atribute, categorization, etc; must be done after title is wrapped&lt;br /&gt;
		TransTitle= 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 = 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 atribute, categorization, etc; must be done after title is wrapped&lt;br /&gt;
		TransTitle = wrap_style (&#039;trans-italic-title&#039;, TransTitle);&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local TransError = &amp;quot;&amp;quot;;&lt;br /&gt;
	if is_set(TransTitle) then&lt;br /&gt;
		if is_set(Title) then&lt;br /&gt;
			TransTitle = &amp;quot; &amp;quot; .. TransTitle;&lt;br /&gt;
		else&lt;br /&gt;
			TransError = &amp;quot; &amp;quot; .. set_error( &#039;trans_missing_title&#039;, {&#039;title&#039;} );&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if is_set (Title) then														-- TODO: is this the right place to be making wikisource urls?&lt;br /&gt;
		if is_set (TitleLink) and is_set (URL) then&lt;br /&gt;
			table.insert( z.message_tail, { set_error( &#039;wikilink_in_url&#039;, {}, true ) } );	-- 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 is_set (TitleLink) and is_set (URL) then&lt;br /&gt;
			Title = external_link (URL, Title, URL_origin, UrlAccess) .. TransTitle .. TransError .. 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 is_set (TitleLink) and not 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 = substitute (cfg.presentation[&#039;interwiki-icon&#039;], {cfg.presentation[&#039;class-wikisource&#039;], TitleLink, Title});				&lt;br /&gt;
				Title = Title .. TransTitle .. TransError;&lt;br /&gt;
			else&lt;br /&gt;
				Title = make_wikilink (TitleLink, Title) .. TransTitle .. TransError;&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			local ws_url, ws_label;												-- 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 tool tip 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 = substitute (cfg.presentation[&#039;interwiki-icon&#039;], {cfg.presentation[&#039;class-wikisource&#039;], L, Title});				&lt;br /&gt;
				Title = Title .. TransTitle .. TransError;&lt;br /&gt;
			else&lt;br /&gt;
				Title = Title .. TransTitle .. TransError;&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		Title = TransTitle .. TransError;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if 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;
	if is_set (Conference) then&lt;br /&gt;
		if 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 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;
	if not 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 is_set(Minutes) then&lt;br /&gt;
			if is_set (Time) then&lt;br /&gt;
				table.insert( z.message_tail, { set_error( &#039;redundant_parameters&#039;, {wrap_style (&#039;parameter&#039;, &#039;minutes&#039;) .. &#039; and &#039; .. wrap_style (&#039;parameter&#039;, &#039;time&#039;)}, true ) } );&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 is_set(Time) then&lt;br /&gt;
				local TimeCaption = A[&#039;TimeCaption&#039;]&lt;br /&gt;
				if not 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 = is_set(At) and (sepc .. &amp;quot; &amp;quot; .. At) or &amp;quot;&amp;quot;;&lt;br /&gt;
	Position = 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 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 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 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;
	if 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=&amp;quot;&amp;quot;;															-- 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;
	Others = is_set(Others) and (sepc .. &amp;quot; &amp;quot; .. Others) or &amp;quot;&amp;quot;;&lt;br /&gt;
	&lt;br /&gt;
	if 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 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;
	TitleNote = is_set(TitleNote) and (sepc .. &amp;quot; &amp;quot; .. TitleNote) or &amp;quot;&amp;quot;;&lt;br /&gt;
	if is_set (Edition) then&lt;br /&gt;
		if Edition:match (&#039;%f[%a][Ee]d%.?$&#039;) or Edition:match (&#039;%f[%a][Ee]dition$&#039;) then&lt;br /&gt;
			add_maint_cat (&#039;extra_text&#039;, &#039;edition&#039;);&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 = is_set (Series) and wrap_msg (&#039;series&#039;, {sepc, Series}) or &amp;quot;&amp;quot;;		-- not the same as SeriesNum&lt;br /&gt;
	OrigYear = is_set (OrigYear) and wrap_msg (&#039;origyear&#039;, OrigYear) or &#039;&#039;;&lt;br /&gt;
	Agency = 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;
	------------------------------------ totally unrelated data&lt;br /&gt;
	Via = is_set (Via) and  wrap_msg (&#039;via&#039;, Via) or &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
	if 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 = substitute (retrv_text, AccessDate);						-- add retrieved text&lt;br /&gt;
&lt;br /&gt;
		AccessDate = substitute (cfg.presentation[&#039;accessdate&#039;], {sepc, AccessDate});	-- allow editors to hide accessdates&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if is_set(ID) then ID = sepc ..&amp;quot; &amp;quot;.. ID; end&lt;br /&gt;
   	if &amp;quot;thesis&amp;quot; == config.CitationClass and 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 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;
	ID_list = build_id_list( ID_list, {IdAccessLevels=ID_access_levels, DoiBroken = DoiBroken, ASINTLD = ASINTLD, IgnoreISBN = IgnoreISBN, Embargo=Embargo, Class = Class} );&lt;br /&gt;
&lt;br /&gt;
	if 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;
	if 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;
		Quote = sepc ..&amp;quot; &amp;quot; .. wrap_style (&#039;quoted-text&#039;, Quote ); 				-- wrap in &amp;lt;q&amp;gt;...&amp;lt;/q&amp;gt; tags&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;
	local Archived&lt;br /&gt;
	if is_set(ArchiveURL) then&lt;br /&gt;
		local arch_text;&lt;br /&gt;
		if not is_set(ArchiveDate) then&lt;br /&gt;
			ArchiveDate = set_error(&#039;archive_missing_date&#039;);&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;
			Archived = sepc .. &amp;quot; &amp;quot; .. 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;
			if not is_set (OriginalURL) then&lt;br /&gt;
				Archived = Archived .. &amp;quot; &amp;quot; .. set_error(&#039;archive_missing_url&#039;);							   &lt;br /&gt;
			end&lt;br /&gt;
		elseif is_set(OriginalURL) then											-- UrlStatus is empty, &#039;dead&#039;, &#039;unfit&#039;, &#039;usurped&#039;, &#039;bot: unknown&#039;&lt;br /&gt;
			if 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 .. &amp;quot; &amp;quot; .. arch_text .. ArchiveDate;				-- format already styled&lt;br /&gt;
				if &#039;bot: unknown&#039; == UrlStatus then&lt;br /&gt;
					add_maint_cat (&#039;bot:_unknown&#039;);								-- and add a category if not already added&lt;br /&gt;
				else&lt;br /&gt;
					add_maint_cat (&#039;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;
				Archived = sepc .. &amp;quot; &amp;quot; .. 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;
			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;
			Archived = sepc .. &amp;quot; &amp;quot; .. substitute( arch_text, &lt;br /&gt;
				{ set_error(&#039;archive_missing_url&#039;), ArchiveDate } );&lt;br /&gt;
		end&lt;br /&gt;
	elseif 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 = &amp;quot;&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local Lay = &#039;&#039;;&lt;br /&gt;
	if is_set(LayURL) then&lt;br /&gt;
		if is_set(LayDate) then LayDate = &amp;quot; (&amp;quot; .. LayDate .. &amp;quot;)&amp;quot; end&lt;br /&gt;
		if is_set(LaySource) then &lt;br /&gt;
			LaySource = &amp;quot; &amp;amp;ndash; &#039;&#039;&amp;quot; .. 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 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;
	if is_set(Transcript) then&lt;br /&gt;
		if 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 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 is_set(PublicationDate) then&lt;br /&gt;
		PublicationDate = wrap_msg (&#039;published&#039;, PublicationDate);&lt;br /&gt;
	end&lt;br /&gt;
	if is_set(PublisherName) then&lt;br /&gt;
		if 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 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;
	-- Several of the above rely upon detecting this as nil, so do it last.&lt;br /&gt;
	if (is_set (Periodical) or is_set (ScriptPeriodical) or is_set (TransPeriodical)) then&lt;br /&gt;
		if is_set(Title) or 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;
	--[[&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 = &amp;quot; (Speech)&amp;quot;;												-- annotate the citation&lt;br /&gt;
		if is_set (Periodical) then												-- if Periodical, perhaps because of an included |website= or |journal= parameter &lt;br /&gt;
			if 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 in_array(config.CitationClass, {&amp;quot;journal&amp;quot;,&amp;quot;citation&amp;quot;}) and is_set(Periodical) then&lt;br /&gt;
		if 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 in_array(config.CitationClass, {&amp;quot;book&amp;quot;,&amp;quot;citation&amp;quot;}) and not is_set(Periodical) then		-- special cases for book cites&lt;br /&gt;
		if 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 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 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 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;
	if is_set(Date) then&lt;br /&gt;
		if is_set (Authors) or 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; .. OrigYear .. sepc .. &amp;quot; &amp;quot;;				-- in paranetheses&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 .. OrigYear;									-- Date does not begin with sepc&lt;br /&gt;
			else&lt;br /&gt;
				Date = sepc .. &amp;quot; &amp;quot; .. Date .. OrigYear;							-- Date begins with sepc&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end	&lt;br /&gt;
	if is_set(Authors) then&lt;br /&gt;
		if (not 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 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 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 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 is_set (Editors) and 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 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 is_set(Editors) then&lt;br /&gt;
		if 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 in_array(config.CitationClass, {&amp;quot;journal&amp;quot;,&amp;quot;citation&amp;quot;}) and 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 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 = {};&lt;br /&gt;
	&lt;br /&gt;
	if is_set(config.CitationClass) and config.CitationClass ~= &amp;quot;citation&amp;quot; then&lt;br /&gt;
		options.class = string.format (&#039;%s %s %s&#039;, &#039;citation&#039;, config.CitationClass, is_set (Mode) and Mode or &#039;cs1&#039;);	-- class=citation required for blue highlight when used with |ref=&lt;br /&gt;
	else&lt;br /&gt;
		options.class = string.format (&#039;%s %s&#039;, &#039;citation&#039;, is_set (Mode) and Mode or &#039;cs2&#039;);&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if is_set(Ref) and &#039;none&#039; ~= cfg.keywords_xlate[Ref:lower()] then&lt;br /&gt;
		local id = Ref&lt;br /&gt;
		if (&#039;harv&#039; == Ref ) then&lt;br /&gt;
			local namelist = {};												-- 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 = c;													-- select it&lt;br /&gt;
			elseif #a &amp;gt; 0 then													-- or an author list&lt;br /&gt;
				namelist = a;&lt;br /&gt;
			elseif #e &amp;gt; 0 then													-- or an editor list&lt;br /&gt;
				namelist = e;&lt;br /&gt;
			end&lt;br /&gt;
			if #namelist &amp;gt; 0 then												-- if there are names in namelist&lt;br /&gt;
				id = anchor_id (namelist, year);								-- go make the CITEREF anchor&lt;br /&gt;
			else&lt;br /&gt;
				id = &#039;&#039;;														-- unset&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		options.id = id;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if string.len(text:gsub(&amp;quot;&amp;lt;span[^&amp;gt;/]*&amp;gt;(.-)&amp;lt;/span&amp;gt;&amp;quot;, &amp;quot;%1&amp;quot;):gsub(&amp;quot;%b&amp;lt;&amp;gt;&amp;quot;,&amp;quot;&amp;quot;)) &amp;lt;= 2 then	-- remove &amp;lt;span&amp;gt; tags and other html-like markup; then get length of what remains&lt;br /&gt;
		z.error_categories = {};&lt;br /&gt;
		text = set_error(&#039;empty_citation&#039;);&lt;br /&gt;
		z.message_tail = {};&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local render = {};															-- here we collect the final bits for concatenation into the rendered citation&lt;br /&gt;
&lt;br /&gt;
	if is_set(options.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, substitute (cfg.presentation[&#039;cite-id&#039;], {mw.uri.anchorEncode(options.id), mw.text.nowiki(options.class), text}));	-- when |ref= is set&lt;br /&gt;
	else&lt;br /&gt;
		table.insert (render, substitute (cfg.presentation[&#039;cite&#039;], {mw.text.nowiki(options.class), text}));	-- all other cases&lt;br /&gt;
	end		&lt;br /&gt;
&lt;br /&gt;
	table.insert (render, substitute (cfg.presentation[&#039;ocins&#039;], {OCinSoutput}));	-- append metadata to the citation&lt;br /&gt;
&lt;br /&gt;
	if 0 ~= #z.message_tail then&lt;br /&gt;
		table.insert (render, &#039; &#039;);&lt;br /&gt;
		for i,v in ipairs( z.message_tail ) do&lt;br /&gt;
			if is_set(v[1]) then&lt;br /&gt;
				if i == #z.message_tail then&lt;br /&gt;
					table.insert (render, error_comment( v[1], v[2] ));&lt;br /&gt;
				else&lt;br /&gt;
					table.insert (render, error_comment( v[1] .. &amp;quot;; &amp;quot;, v[2] ));&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if 0 ~= #z.maintenance_cats then&lt;br /&gt;
		local maint_msgs = {};													-- here we collect all of the maint messages&lt;br /&gt;
		for _, v in ipairs( z.maintenance_cats ) do								-- append maintenance categories&lt;br /&gt;
			local maint = {};													-- here we assemble a maintenence message&lt;br /&gt;
			table.insert (maint, v);											-- maint msg is the category name&lt;br /&gt;
			table.insert (maint, &#039; (&#039;);											-- open the link text&lt;br /&gt;
			table.insert (maint, make_wikilink (&#039;:Category:&#039; .. v, &#039;link&#039;));	-- add the link&lt;br /&gt;
			table.insert (maint, &#039;)&#039;);											-- and close it&lt;br /&gt;
			table.insert (maint_msgs, table.concat (maint));					-- assemble new maint message and add it to the maint_msgs table&lt;br /&gt;
		end&lt;br /&gt;
		table.insert (render, substitute (cfg.presentation[&#039;hidden-maint&#039;], table.concat (maint_msgs, &#039; &#039;)));	-- wrap the group of maint message 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_categories ) do&lt;br /&gt;
			table.insert (render, make_wikilink (&#039;Category:&#039; .. v));&lt;br /&gt;
		end&lt;br /&gt;
		for _, v in ipairs( z.maintenance_cats ) do								-- append maintenance categories&lt;br /&gt;
			table.insert (render, make_wikilink (&#039;Category:&#039; .. v));&lt;br /&gt;
		end&lt;br /&gt;
		for _, v in ipairs( z.properties_cats ) do								-- append properties categories&lt;br /&gt;
			table.insert (render, make_wikilink (&#039;Category:&#039; .. v));&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return table.concat (render);	&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)&lt;br /&gt;
	local name = tostring (name);&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;
			deprecated_parameter (name);										-- parameter is deprecated but still supported&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 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;
		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[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 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;
	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[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; 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 atributes: 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;
		table.insert( z.message_tail, {set_error (&#039;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;
		add_maint_cat (&#039;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; 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 incase we need to display an error message in preview mode&lt;br /&gt;
	local pframe = frame:getParent()&lt;br /&gt;
	local validation, utilities, identifiers, metadata, styles;&lt;br /&gt;
	&lt;br /&gt;
	if nil ~= string.find (frame:getTitle(), &#039;sandbox&#039;, 1, true) then			-- did the {{#invoke:}} use sandbox version?&lt;br /&gt;
		cfg = mw.loadData (&#039;Module:Citation/CS1/Configuration/sandbox&#039;);		-- load sandbox versions of support modules&lt;br /&gt;
		whitelist = mw.loadData (&#039;Module:Citation/CS1/Whitelist/sandbox&#039;);&lt;br /&gt;
		utilities = require (&#039;Module:Citation/CS1/Utilities/sandbox&#039;);&lt;br /&gt;
		validation = require (&#039;Module:Citation/CS1/Date_validation/sandbox&#039;);&lt;br /&gt;
		identifiers = require (&#039;Module:Citation/CS1/Identifiers/sandbox&#039;);&lt;br /&gt;
		metadata = require (&#039;Module:Citation/CS1/COinS/sandbox&#039;);&lt;br /&gt;
		styles = &#039;Module:Citation/CS1/sandbox/styles.css&#039;;&lt;br /&gt;
		&lt;br /&gt;
	else																		-- otherwise&lt;br /&gt;
		cfg = mw.loadData (&#039;Module:Citation/CS1/Configuration&#039;);				-- load live versions of support modules&lt;br /&gt;
		whitelist = mw.loadData (&#039;Module:Citation/CS1/Whitelist&#039;);&lt;br /&gt;
		utilities = require (&#039;Module:Citation/CS1/Utilities&#039;);&lt;br /&gt;
		validation = require (&#039;Module:Citation/CS1/Date_validation&#039;);&lt;br /&gt;
		identifiers = require (&#039;Module:Citation/CS1/Identifiers&#039;);&lt;br /&gt;
		metadata = require (&#039;Module:Citation/CS1/COinS&#039;);&lt;br /&gt;
		styles = &#039;Module:Citation/CS1/styles.css&#039;;&lt;br /&gt;
&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	utilities.set_selected_modules (cfg);										-- so that functions in Utilities can see the 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;
	dates = validation.dates;													-- imported functions from Module:Citation/CS1/Date validation&lt;br /&gt;
	year_date_check = validation.year_date_check;&lt;br /&gt;
	reformat_dates = validation.reformat_dates;&lt;br /&gt;
	date_hyphen_to_dash = validation.date_hyphen_to_dash;&lt;br /&gt;
	date_name_xlate = validation.date_name_xlate;&lt;br /&gt;
&lt;br /&gt;
	is_set = utilities.is_set;													-- imported functions from Module:Citation/CS1/Utilities&lt;br /&gt;
	in_array = utilities.in_array;&lt;br /&gt;
	substitute = utilities.substitute;&lt;br /&gt;
	error_comment = utilities.error_comment;&lt;br /&gt;
	set_error = utilities.set_error;&lt;br /&gt;
	select_one = utilities.select_one;&lt;br /&gt;
	add_maint_cat = utilities.add_maint_cat;&lt;br /&gt;
	wrap_style = utilities.wrap_style;&lt;br /&gt;
	safe_for_italics = utilities.safe_for_italics;&lt;br /&gt;
	is_wikilink = utilities.is_wikilink;&lt;br /&gt;
	make_wikilink = utilities.make_wikilink;&lt;br /&gt;
	strip_apostrophe_markup = utilities.strip_apostrophe_markup;&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;
	extract_ids = identifiers.extract_ids;										-- imported functions from Module:Citation/CS1/Identifiers&lt;br /&gt;
	build_id_list = identifiers.build_id_list;&lt;br /&gt;
	is_embargoed = identifiers.is_embargoed;&lt;br /&gt;
	extract_id_access_levels = identifiers.extract_id_access_levels;&lt;br /&gt;
	&lt;br /&gt;
	make_coins_title = metadata.make_coins_title;								-- imported functions from Module:Citation/CS1/COinS&lt;br /&gt;
	get_coins_pages = metadata.get_coins_pages;&lt;br /&gt;
	COinS = metadata.COinS;&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, error_state;&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;
	for k, v in pairs( pframe.args ) do											-- get parameters from the parent (template) frame&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;
				error_text = &amp;quot;&amp;quot;;&lt;br /&gt;
				if type( k ) ~= &#039;string&#039; then&lt;br /&gt;
					-- Exclude empty numbered parameters&lt;br /&gt;
					if v:match(&amp;quot;%S+&amp;quot;) ~= nil then&lt;br /&gt;
						error_text, error_state = set_error( &#039;text_ignored&#039;, {v}, true );&lt;br /&gt;
					end&lt;br /&gt;
				elseif validate( k:lower(), config.CitationClass ) then &lt;br /&gt;
					error_text, error_state = set_error( &#039;parameter_ignored_suggest&#039;, {k, k:lower()}, true );	-- 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 nil ~= string.find (frame:getTitle(), &#039;sandbox&#039;, 1, true) 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 caputre in pattern else the capture if a match&lt;br /&gt;
						if capture then											-- if the pattern matches &lt;br /&gt;
							param = 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, error_state = set_error (&#039;parameter_ignored_suggest&#039;, {k, param}, true);	-- set the suggestion error message&lt;br /&gt;
							else&lt;br /&gt;
								error_text, error_state = set_error( &#039;parameter_ignored&#039;, {param}, true );	-- 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 is_set (error_text) then								-- couldn&#039;t match with a pattern, is there an expicit suggestion?&lt;br /&gt;
						if suggestions.suggestions[ k:lower() ] ~= nil then&lt;br /&gt;
							error_text, error_state = set_error( &#039;parameter_ignored_suggest&#039;, {k, suggestions.suggestions[ k:lower() ]}, true );&lt;br /&gt;
						else&lt;br /&gt;
							error_text, error_state = set_error( &#039;parameter_ignored&#039;, {k}, true );&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;
				if error_text ~= &#039;&#039; then&lt;br /&gt;
					table.insert( z.message_tail, {error_text, error_state} );&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;
																				-- 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;
	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;
	end&lt;br /&gt;
&lt;br /&gt;
	return table.concat ({citation0( config, args), frame:extensionTag (&#039;templatestyles&#039;, &#039;&#039;, {src=styles})});&lt;br /&gt;
end&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>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Module:Check_isxn&amp;diff=211</id>
		<title>Module:Check isxn</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Module:Check_isxn&amp;diff=211"/>
		<updated>2020-08-22T20:23:48Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This template is a copy of the ISXN validation code from [[Module:Citation/CS1]]&lt;br /&gt;
-- which allows for validating ISBN, ISMN, and ISSN without invoking a citation template&lt;br /&gt;
&lt;br /&gt;
local p = {}&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. ISBN-13 is checked in check_isbn().&lt;br /&gt;
If the number is valid the result will be 0. Before calling this function, issbn/issn must be checked for length and stripped of dashes,&lt;br /&gt;
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;
--[[--------------------------&amp;lt; C H E C K _ 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 check_isbn( isbn_str, error_string )&lt;br /&gt;
	if nil ~= isbn_str:match(&amp;quot;[^%s-0-9X]&amp;quot;) then -- fail if isbn_str contains anything but digits, hyphens, or the uppercase X&lt;br /&gt;
		return error_string;&lt;br /&gt;
	end&lt;br /&gt;
	isbn_str = isbn_str:gsub( &amp;quot;-&amp;quot;, &amp;quot;&amp;quot; ):gsub( &amp;quot; &amp;quot;, &amp;quot;&amp;quot; );	-- remove hyphens and spaces&lt;br /&gt;
	local len = isbn_str:len();&lt;br /&gt;
 &lt;br /&gt;
	if len ~= 10 and len ~= 13 then&lt;br /&gt;
		return error_string;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if len == 10 then&lt;br /&gt;
		if isbn_str:match( &amp;quot;^%d*X?$&amp;quot; ) == nil then &lt;br /&gt;
			return error_string; &lt;br /&gt;
		end&lt;br /&gt;
		return is_valid_isxn(isbn_str, 10) and &#039;&#039; or error_string;&lt;br /&gt;
	else&lt;br /&gt;
		local temp = 0;&lt;br /&gt;
		if isbn_str:match( &amp;quot;^97[89]%d*$&amp;quot; ) == nil then -- isbn13 begins with 978 or 979; ismn begins with 979&lt;br /&gt;
			return error_string; &lt;br /&gt;
		end&lt;br /&gt;
		return is_valid_isxn_13 (isbn_str) and &#039;&#039; or error_string;&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; C H E C K _ 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 begining 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;
]]&lt;br /&gt;
&lt;br /&gt;
local function check_ismn (id, error_string)&lt;br /&gt;
	local text;&lt;br /&gt;
	local valid_ismn = true;&lt;br /&gt;
&lt;br /&gt;
	id=id:gsub( &amp;quot;[%s-–]&amp;quot;, &amp;quot;&amp;quot; );													-- strip spaces, hyphens, and endashes from the ismn&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 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;
	return valid_ismn and &#039;&#039; or error_string&lt;br /&gt;
end&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 has separated the two groups of four&lt;br /&gt;
digits with a space.  When that condition occurred, the resulting link looked 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 and makes sure that the checkdigit agrees&lt;br /&gt;
with the calculated value.  Incorrect length (8 digits), characters other than 0-9 and X, or checkdigit / calculated value mismatch will all cause a check issn&lt;br /&gt;
error message.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function check_issn(id, error_string)&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;
	if not id:match (&#039;^%d%d%d%d%-%d%d%d[%dX]$&#039;) then&lt;br /&gt;
		return error_string;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	id=id:gsub( &amp;quot;[%s-–]&amp;quot;, &amp;quot;&amp;quot; );									-- strip spaces, hyphens, and endashes from the issn&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;
	return valid_issn and &#039;&#039; or error_string&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
------------------------------&amp;lt; E N T R Y   P O I N T S &amp;gt;--------------------------------------------------====&lt;br /&gt;
&lt;br /&gt;
function p.check_isbn(frame)&lt;br /&gt;
	return check_isbn(frame.args[1] or frame:getParent().args[1], frame.args[&#039;error&#039;] or frame:getParent().args[&#039;error&#039;] or &#039;error&#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.check_ismn(frame)&lt;br /&gt;
	return check_ismn(frame.args[1] or frame:getParent().args[1], frame.args[&#039;error&#039;] or frame:getParent().args[&#039;error&#039;] or &#039;error&#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.check_issn(frame)&lt;br /&gt;
	return check_issn(frame.args[1] or frame:getParent().args[1], frame.args[&#039;error&#039;] or frame:getParent().args[&#039;error&#039;] or &#039;error&#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Module:Check_for_unknown_parameters&amp;diff=209</id>
		<title>Module:Check for unknown parameters</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Module:Check_for_unknown_parameters&amp;diff=209"/>
		<updated>2020-08-22T20:23:48Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 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;
	local ignoreblank = isnotempty(args[&#039;ignoreblank&#039;])&lt;br /&gt;
	local showblankpos = isnotempty(args[&#039;showblankpositional&#039;])&lt;br /&gt;
	local knownargs = {}&lt;br /&gt;
	local unknown = args[&#039;unknown&#039;] or &#039;Found _VALUE_, &#039;&lt;br /&gt;
	local preview = args[&#039;preview&#039;]&lt;br /&gt;
&lt;br /&gt;
	local values = {}&lt;br /&gt;
	local res = {}&lt;br /&gt;
	local regexps = {}&lt;br /&gt;
&lt;br /&gt;
	-- create the list of known args, regular expressions, and the return string&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;
	if isnotempty(preview) then&lt;br /&gt;
		preview = &#039;&amp;lt;div class=&amp;quot;hatnote&amp;quot; style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;strong&amp;gt;Warning:&amp;lt;/strong&amp;gt; &#039; .. preview .. &#039; (this message is shown only in preview).&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
	elseif preview == nil then&lt;br /&gt;
		preview = unknown&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;
	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&lt;br /&gt;
			knownargs[tostring(k)] == nil and&lt;br /&gt;
			( showblankpos or isnotempty(v) )&lt;br /&gt;
		then&lt;br /&gt;
			table.insert(values, k .. &#039; = &#039; .. clean(v))&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- add results to the output tables&lt;br /&gt;
	if #values &amp;gt; 0 then&lt;br /&gt;
		if mw.getCurrentFrame():preprocess( &amp;quot;{{REVISIONID}}&amp;quot; ) == &amp;quot;&amp;quot; then&lt;br /&gt;
			unknown = preview&lt;br /&gt;
		end&lt;br /&gt;
		for _, v in pairs(values) do&lt;br /&gt;
			if v == &#039;&#039; then&lt;br /&gt;
				-- Fix odd bug for | = which gets stripped to the empty string and&lt;br /&gt;
				-- breaks category links&lt;br /&gt;
				v = &#039; &#039;&lt;br /&gt;
			end&lt;br /&gt;
			-- avoid error with v = &#039;example%2&#039; (&amp;quot;invalid capture index&amp;quot;)&lt;br /&gt;
			local r =  unknown: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>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Module:Category_see_also&amp;diff=207</id>
		<title>Module:Category see also</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Module:Category_see_also&amp;diff=207"/>
		<updated>2020-08-22T20:23:47Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module implements {{Category see also}}&lt;br /&gt;
&lt;br /&gt;
local mHatnote = require(&#039;Module:Hatnote&#039;)&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
local function makeWikitextError(msg)&lt;br /&gt;
	return string.format(&lt;br /&gt;
		&#039;&amp;lt;strong class=&amp;quot;error&amp;quot;&amp;gt;Error: %s ([[Template:Category see also]])&amp;lt;/strong&amp;gt;&#039;,&lt;br /&gt;
		msg&lt;br /&gt;
	)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Gets the length of the sequence seq. Usually this should be done with the #&lt;br /&gt;
-- operator, but we need to work with tables that get their values through an&lt;br /&gt;
-- __index metamethod.&lt;br /&gt;
local function getSequenceLength(seq)&lt;br /&gt;
	local length = 0&lt;br /&gt;
	for i in ipairs(seq) do&lt;br /&gt;
		length = i&lt;br /&gt;
	end&lt;br /&gt;
	return length&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Given a table of options, returns a function that formats categories for&lt;br /&gt;
-- those options.&lt;br /&gt;
--&lt;br /&gt;
-- Options:&lt;br /&gt;
-- project - a project code such as &amp;quot;fr&amp;quot; (for the French Wikipedia)&lt;br /&gt;
-- showPrefix - a boolean value for whether to show the &amp;quot;Category:&amp;quot; prefix&lt;br /&gt;
--              (and the project prefix if specified)&lt;br /&gt;
--&lt;br /&gt;
-- This is implemented as a function generator rather than a simple function&lt;br /&gt;
-- so that we can just process the options once, instead of every time we&lt;br /&gt;
-- generate a category.&lt;br /&gt;
local function newCategoryLinker(options)&lt;br /&gt;
	local formatString&lt;br /&gt;
	if options.project then&lt;br /&gt;
		if options.showPrefix then&lt;br /&gt;
			formatString = &#039;[[:&#039; .. options.project .. &#039;:Category:%s]]&#039;&lt;br /&gt;
		else&lt;br /&gt;
			formatString = &#039;[[:&#039; .. options.project .. &#039;:Category:%s|%s]]&#039;&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		if options.showPrefix then&lt;br /&gt;
			formatString = &#039;[[:Category:%s]]&#039;&lt;br /&gt;
		else&lt;br /&gt;
			formatString = &#039;[[:Category:%s|%s]]&#039;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return function (category)&lt;br /&gt;
		local title = mw.title.new(category)&lt;br /&gt;
		local pageName, display&lt;br /&gt;
		if not title then&lt;br /&gt;
			-- category is not a valid title, usually because of invalid&lt;br /&gt;
			-- characters like &amp;lt; or [. Raise an error and suppress the stack&lt;br /&gt;
			-- level information so that we can catch it and format the error&lt;br /&gt;
			-- message as wikitext.&lt;br /&gt;
			error(string.format(&lt;br /&gt;
				&amp;quot;&#039;%s&#039; is not a valid category name&amp;quot;,&lt;br /&gt;
				category&lt;br /&gt;
			), 0)&lt;br /&gt;
		elseif title.namespace == 14 then -- Category namespace&lt;br /&gt;
			pageName = title.text&lt;br /&gt;
			display = title.text&lt;br /&gt;
		else&lt;br /&gt;
			pageName = title.prefixedText&lt;br /&gt;
			display = category&lt;br /&gt;
		end&lt;br /&gt;
		-- We can get away with using two arguments even when&lt;br /&gt;
		-- options.showDisplay is false, as string.format ignores extra&lt;br /&gt;
		-- arguments as long as there is an argument for each flag in the&lt;br /&gt;
		-- format string.&lt;br /&gt;
		return formatString:format(pageName, display)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._main(args)&lt;br /&gt;
	local nLinks = getSequenceLength(args)&lt;br /&gt;
&lt;br /&gt;
	if nLinks &amp;lt; 1 then&lt;br /&gt;
		return makeWikitextError(&#039;at least one parameter required&#039;)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local makeCategoryLink = newCategoryLinker{&lt;br /&gt;
		project = args.project,&lt;br /&gt;
		showPrefix = nLinks == 1,&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	local links = {}&lt;br /&gt;
	for i, cat in ipairs(args) do&lt;br /&gt;
		local success, categoryLink = pcall(makeCategoryLink, cat)&lt;br /&gt;
		if success then&lt;br /&gt;
			links[i] = categoryLink&lt;br /&gt;
		else&lt;br /&gt;
			-- If there was an error, then categoryLink is the error message.&lt;br /&gt;
			return makeWikitextError(categoryLink)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local formatString&lt;br /&gt;
	if nLinks == 1 then&lt;br /&gt;
		formatString = &#039;%s: %s.&#039;&lt;br /&gt;
	else&lt;br /&gt;
		formatString = &#039;%s: the categories %s.&#039;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Don&#039;t output a comma before the &amp;quot;and&amp;quot; if we have only two links.&lt;br /&gt;
	local conjunction&lt;br /&gt;
	if nLinks == 2 then&lt;br /&gt;
		conjunction = &#039; and &#039;&lt;br /&gt;
	else&lt;br /&gt;
		conjunction = &#039;, and &#039;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local hatnoteText = formatString:format(&lt;br /&gt;
		args.LABEL or &#039;See also&#039;,&lt;br /&gt;
		mw.text.listToText(links, &#039;, &#039;, conjunction)&lt;br /&gt;
	)&lt;br /&gt;
	return mHatnote._hatnote(hatnoteText, {selfref = true})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.main(frame)&lt;br /&gt;
	local args = require(&#039;Module:Arguments&#039;).getArgs(frame, {&lt;br /&gt;
		wrappers = &#039;Template:Category see also&#039;,&lt;br /&gt;
	})&lt;br /&gt;
	return p._main(args)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Module:Category_handler/shared&amp;diff=205</id>
		<title>Module:Category handler/shared</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Module:Category_handler/shared&amp;diff=205"/>
		<updated>2020-08-22T20:23:47Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module contains shared functions used by [[Module:Category handler]]&lt;br /&gt;
-- and its submodules.&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
function p.matchesBlacklist(page, blacklist)&lt;br /&gt;
	for i, pattern in ipairs(blacklist) do&lt;br /&gt;
		local match = mw.ustring.match(page, pattern)&lt;br /&gt;
		if match then&lt;br /&gt;
			return true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.getParamMappings(useLoadData)&lt;br /&gt;
	local dataPage = &#039;Module:Namespace detect/data&#039;&lt;br /&gt;
	if useLoadData then&lt;br /&gt;
		return mw.loadData(dataPage).mappings&lt;br /&gt;
	else&lt;br /&gt;
		return require(dataPage).mappings&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.getNamespaceParameters(titleObj, mappings)&lt;br /&gt;
	-- We don&#039;t use title.nsText for the namespace name because it adds&lt;br /&gt;
	-- underscores.&lt;br /&gt;
	local mappingsKey&lt;br /&gt;
	if titleObj.isTalkPage then&lt;br /&gt;
		mappingsKey = &#039;talk&#039;&lt;br /&gt;
	else&lt;br /&gt;
		mappingsKey = mw.site.namespaces[titleObj.namespace].name&lt;br /&gt;
	end&lt;br /&gt;
	mappingsKey = mw.ustring.lower(mappingsKey)&lt;br /&gt;
	return mappings[mappingsKey] or {}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Module:Category_handler/data&amp;diff=203</id>
		<title>Module:Category handler/data</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Module:Category_handler/data&amp;diff=203"/>
		<updated>2020-08-22T20:23:47Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module assembles data to be passed to [[Module:Category handler]] using&lt;br /&gt;
-- mw.loadData. This includes the configuration data and whether the current&lt;br /&gt;
-- page matches the title blacklist.&lt;br /&gt;
&lt;br /&gt;
local data = require(&#039;Module:Category handler/config&#039;)&lt;br /&gt;
local mShared = require(&#039;Module:Category handler/shared&#039;)&lt;br /&gt;
local blacklist = require(&#039;Module:Category handler/blacklist&#039;)&lt;br /&gt;
local title = mw.title.getCurrentTitle()&lt;br /&gt;
&lt;br /&gt;
data.currentTitleMatchesBlacklist = mShared.matchesBlacklist(&lt;br /&gt;
	title.prefixedText,&lt;br /&gt;
	blacklist&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
data.currentTitleNamespaceParameters = mShared.getNamespaceParameters(&lt;br /&gt;
	title,&lt;br /&gt;
	mShared.getParamMappings()&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
return data&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Module:Category_handler/config&amp;diff=201</id>
		<title>Module:Category handler/config</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Module:Category_handler/config&amp;diff=201"/>
		<updated>2020-08-22T20:23:47Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--------------------------------------------------------------------------------&lt;br /&gt;
--            [[Module:Category handler]] configuration data                  --&lt;br /&gt;
--       Language-specific parameter names and values can be set here.        --&lt;br /&gt;
--       For blacklist config, see [[Module:Category handler/blacklist]].     --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local cfg = {} -- Don&#039;t edit this line.&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
--                       Start configuration data                             --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
--                              Parameter names                               --&lt;br /&gt;
-- These configuration items specify custom parameter names.                  --&lt;br /&gt;
-- To add one extra name, you can use this format:                            --&lt;br /&gt;
--                                                                            --&lt;br /&gt;
-- foo = &#039;parameter name&#039;,                                                    --&lt;br /&gt;
--                                                                            --&lt;br /&gt;
-- To add multiple names, you can use this format:                            --&lt;br /&gt;
--                                                                            --&lt;br /&gt;
-- foo = {&#039;parameter name 1&#039;, &#039;parameter name 2&#039;, &#039;parameter name 3&#039;},        --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
cfg.parameters = {&lt;br /&gt;
	&lt;br /&gt;
	-- The nocat and categories parameter suppress&lt;br /&gt;
	-- categorisation. They are used with Module:Yesno, and work as follows:&lt;br /&gt;
	--&lt;br /&gt;
	-- cfg.nocat:&lt;br /&gt;
	-- Result of yesno()                        Effect&lt;br /&gt;
	-- true                                     Categorisation is suppressed&lt;br /&gt;
	-- false                                    Categorisation is allowed, and&lt;br /&gt;
	--                                          the blacklist check is skipped&lt;br /&gt;
	-- nil                                      Categorisation is allowed&lt;br /&gt;
	--&lt;br /&gt;
	-- cfg.categories:&lt;br /&gt;
	-- Result of yesno()                        Effect&lt;br /&gt;
	-- true                                     Categorisation is allowed, and&lt;br /&gt;
	--                                          the blacklist check is skipped&lt;br /&gt;
	-- false                                    Categorisation is suppressed&lt;br /&gt;
	-- nil                                      Categorisation is allowed&lt;br /&gt;
	nocat = &#039;nocat&#039;,&lt;br /&gt;
	categories = &#039;categories&#039;,&lt;br /&gt;
	&lt;br /&gt;
	-- The parameter name for the legacy &amp;quot;category2&amp;quot; parameter. This skips the&lt;br /&gt;
	-- blacklist if set to the cfg.category2Yes value, and suppresses&lt;br /&gt;
	-- categorisation if present but equal to anything other than&lt;br /&gt;
	-- cfg.category2Yes or cfg.category2Negative.&lt;br /&gt;
	category2 = &#039;category2&#039;,&lt;br /&gt;
	&lt;br /&gt;
	-- cfg.subpage is the parameter name to specify how to behave on subpages.&lt;br /&gt;
	subpage = &#039;subpage&#039;,&lt;br /&gt;
	&lt;br /&gt;
	-- The parameter for data to return in all namespaces.&lt;br /&gt;
	all = &#039;all&#039;,&lt;br /&gt;
	&lt;br /&gt;
	-- The parameter name for data to return if no data is specified for the&lt;br /&gt;
	-- namespace that is detected.&lt;br /&gt;
	other = &#039;other&#039;,&lt;br /&gt;
	&lt;br /&gt;
	-- The parameter name used to specify a page other than the current page;&lt;br /&gt;
	-- used for testing and demonstration.&lt;br /&gt;
	demopage = &#039;page&#039;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
--                              Parameter values                              --&lt;br /&gt;
-- These are set values that can be used with certain parameters. Only one    --&lt;br /&gt;
-- value can be specified, like this:                                         --&lt;br /&gt;
--                                                                            --&lt;br /&gt;
-- cfg.foo = &#039;value name&#039;                                                     --                                               --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- The following settings are used with the cfg.category2 parameter. Setting&lt;br /&gt;
-- cfg.category2 to cfg.category2Yes skips the blacklist, and if cfg.category2&lt;br /&gt;
-- is present but equal to anything other than cfg.category2Yes or&lt;br /&gt;
-- cfg.category2Negative then it supresses cateogrisation.&lt;br /&gt;
cfg.category2Yes = &#039;yes&#039;&lt;br /&gt;
cfg.category2Negative = &#039;¬&#039;&lt;br /&gt;
&lt;br /&gt;
-- The following settings are used with the cfg.subpage parameter.&lt;br /&gt;
-- cfg.subpageNo is the value to specify to not categorise on subpages;&lt;br /&gt;
-- cfg.subpageOnly is the value to specify to only categorise on subpages.&lt;br /&gt;
cfg.subpageNo = &#039;no&#039;&lt;br /&gt;
cfg.subpageOnly = &#039;only&#039;&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
--                           Default namespaces                               --&lt;br /&gt;
-- This is a table of namespaces to categorise by default. The keys are the   --&lt;br /&gt;
-- namespace numbers.                                                         --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
cfg.defaultNamespaces = {&lt;br /&gt;
	[  0] = true, -- main&lt;br /&gt;
	[  6] = true, -- file&lt;br /&gt;
	[ 12] = true, -- help&lt;br /&gt;
	[ 14] = true, -- category&lt;br /&gt;
	[100] = true, -- portal&lt;br /&gt;
	[108] = true, -- book&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
--                                Wrappers                                    --&lt;br /&gt;
-- This is a wrapper template or a list of wrapper templates to be passed to  --&lt;br /&gt;
-- [[Module:Arguments]].                                                      --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
cfg.wrappers = &#039;Template:Category handler&#039;&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
--                           End configuration data                           --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
return cfg -- Don&#039;t edit this line.&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Module:Category_handler/blacklist&amp;diff=199</id>
		<title>Module:Category handler/blacklist</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Module:Category_handler/blacklist&amp;diff=199"/>
		<updated>2020-08-22T20:23:47Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module contains the blacklist used by [[Module:Category handler]].&lt;br /&gt;
-- Pages that match Lua patterns in this list will not be categorised unless&lt;br /&gt;
-- categorisation is explicitly requested.&lt;br /&gt;
&lt;br /&gt;
return {&lt;br /&gt;
	&#039;^Main Page$&#039;, -- don&#039;t categorise the main page.&lt;br /&gt;
&lt;br /&gt;
	-- Don&#039;t categorise the following pages or their subpages.&lt;br /&gt;
	-- &amp;quot;%f[/\0]&amp;quot; matches if the next character is &amp;quot;/&amp;quot; or the end of the string.&lt;br /&gt;
	&#039;^Wikipedia:Cascade%-protected items%f[/\0]&#039;,&lt;br /&gt;
	&#039;^User:UBX%f[/\0]&#039;, -- The userbox &amp;quot;template&amp;quot; space.&lt;br /&gt;
	&#039;^User talk:UBX%f[/\0]&#039;,&lt;br /&gt;
&lt;br /&gt;
	-- Don&#039;t categorise subpages of these pages, but allow&lt;br /&gt;
	-- categorisation of the base page.&lt;br /&gt;
	&#039;^Wikipedia:Template index/.*$&#039;,&lt;br /&gt;
&lt;br /&gt;
	-- Don&#039;t categorise archives.&lt;br /&gt;
	&#039;/[aA]rchive&#039;,&lt;br /&gt;
	&amp;quot;^Wikipedia:Administrators&#039; noticeboard/IncidentArchive%d+$&amp;quot;,&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Module:Category_handler&amp;diff=197</id>
		<title>Module:Category handler</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Module:Category_handler&amp;diff=197"/>
		<updated>2020-08-22T20:23:47Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--------------------------------------------------------------------------------&lt;br /&gt;
--                                                                            --&lt;br /&gt;
--                              CATEGORY HANDLER                              --&lt;br /&gt;
--                                                                            --&lt;br /&gt;
--      This module implements the {{category handler}} template in Lua,      --&lt;br /&gt;
--      with a few improvements: all namespaces and all namespace aliases     --&lt;br /&gt;
--      are supported, and namespace names are detected automatically for     --&lt;br /&gt;
--      the local wiki. This module requires [[Module:Namespace detect]]      --&lt;br /&gt;
--      and [[Module:Yesno]] to be available on the local wiki. It can be     --&lt;br /&gt;
--      configured for different wikis by altering the values in              --&lt;br /&gt;
--      [[Module:Category handler/config]], and pages can be blacklisted      --&lt;br /&gt;
--      from categorisation by using [[Module:Category handler/blacklist]].   --&lt;br /&gt;
--                                                                            --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- Load required modules&lt;br /&gt;
local yesno = require(&#039;Module:Yesno&#039;)&lt;br /&gt;
&lt;br /&gt;
-- Lazily load things we don&#039;t always need&lt;br /&gt;
local mShared, mappings&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Helper functions&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local function trimWhitespace(s, removeBlanks)&lt;br /&gt;
	if type(s) ~= &#039;string&#039; then&lt;br /&gt;
		return s&lt;br /&gt;
	end&lt;br /&gt;
	s = s:match(&#039;^%s*(.-)%s*$&#039;)&lt;br /&gt;
	if removeBlanks then&lt;br /&gt;
		if s ~= &#039;&#039; then&lt;br /&gt;
			return s&lt;br /&gt;
		else&lt;br /&gt;
			return nil&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		return s&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- CategoryHandler class&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local CategoryHandler = {}&lt;br /&gt;
CategoryHandler.__index = CategoryHandler&lt;br /&gt;
&lt;br /&gt;
function CategoryHandler.new(data, args)&lt;br /&gt;
	local obj = setmetatable({ _data = data, _args = args }, CategoryHandler)&lt;br /&gt;
	&lt;br /&gt;
	-- Set the title object&lt;br /&gt;
	do&lt;br /&gt;
		local pagename = obj:parameter(&#039;demopage&#039;)&lt;br /&gt;
		local success, titleObj&lt;br /&gt;
		if pagename then&lt;br /&gt;
			success, titleObj = pcall(mw.title.new, pagename)&lt;br /&gt;
		end&lt;br /&gt;
		if success and titleObj then&lt;br /&gt;
			obj.title = titleObj&lt;br /&gt;
			if titleObj == mw.title.getCurrentTitle() then&lt;br /&gt;
				obj._usesCurrentTitle = true&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			obj.title = mw.title.getCurrentTitle()&lt;br /&gt;
			obj._usesCurrentTitle = true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Set suppression parameter values&lt;br /&gt;
	for _, key in ipairs{&#039;nocat&#039;, &#039;categories&#039;} do&lt;br /&gt;
		local value = obj:parameter(key)&lt;br /&gt;
		value = trimWhitespace(value, true)&lt;br /&gt;
		obj[&#039;_&#039; .. key] = yesno(value)&lt;br /&gt;
	end&lt;br /&gt;
	do&lt;br /&gt;
		local subpage = obj:parameter(&#039;subpage&#039;)&lt;br /&gt;
		local category2 = obj:parameter(&#039;category2&#039;)&lt;br /&gt;
		if type(subpage) == &#039;string&#039; then&lt;br /&gt;
			subpage = mw.ustring.lower(subpage)&lt;br /&gt;
		end&lt;br /&gt;
		if type(category2) == &#039;string&#039; then&lt;br /&gt;
			subpage = mw.ustring.lower(category2)&lt;br /&gt;
		end&lt;br /&gt;
		obj._subpage = trimWhitespace(subpage, true)&lt;br /&gt;
		obj._category2 = trimWhitespace(category2) -- don&#039;t remove blank values&lt;br /&gt;
	end&lt;br /&gt;
	return obj&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function CategoryHandler:parameter(key)&lt;br /&gt;
	local parameterNames = self._data.parameters[key]&lt;br /&gt;
	local pntype = type(parameterNames)&lt;br /&gt;
	if pntype == &#039;string&#039; or pntype == &#039;number&#039; then&lt;br /&gt;
		return self._args[parameterNames]&lt;br /&gt;
	elseif pntype == &#039;table&#039; then&lt;br /&gt;
		for _, name in ipairs(parameterNames) do&lt;br /&gt;
			local value = self._args[name]&lt;br /&gt;
			if value ~= nil then&lt;br /&gt;
				return value&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		return nil&lt;br /&gt;
	else&lt;br /&gt;
		error(string.format(&lt;br /&gt;
			&#039;invalid config key &amp;quot;%s&amp;quot;&#039;,&lt;br /&gt;
			tostring(key)&lt;br /&gt;
		), 2)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function CategoryHandler:isSuppressedByArguments()&lt;br /&gt;
	return&lt;br /&gt;
		-- See if a category suppression argument has been set.&lt;br /&gt;
		self._nocat == true&lt;br /&gt;
		or self._categories == false&lt;br /&gt;
		or (&lt;br /&gt;
			self._category2&lt;br /&gt;
			and self._category2 ~= self._data.category2Yes&lt;br /&gt;
			and self._category2 ~= self._data.category2Negative&lt;br /&gt;
		)&lt;br /&gt;
&lt;br /&gt;
		-- Check whether we are on a subpage, and see if categories are&lt;br /&gt;
		-- suppressed based on our subpage status.&lt;br /&gt;
		or self._subpage == self._data.subpageNo and self.title.isSubpage&lt;br /&gt;
		or self._subpage == self._data.subpageOnly and not self.title.isSubpage&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function CategoryHandler:shouldSkipBlacklistCheck()&lt;br /&gt;
	-- Check whether the category suppression arguments indicate we&lt;br /&gt;
	-- should skip the blacklist check.&lt;br /&gt;
	return self._nocat == false&lt;br /&gt;
		or self._categories == true&lt;br /&gt;
		or self._category2 == self._data.category2Yes&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function CategoryHandler:matchesBlacklist()&lt;br /&gt;
	if self._usesCurrentTitle then&lt;br /&gt;
		return self._data.currentTitleMatchesBlacklist&lt;br /&gt;
	else&lt;br /&gt;
		mShared = mShared or require(&#039;Module:Category handler/shared&#039;)&lt;br /&gt;
		return mShared.matchesBlacklist(&lt;br /&gt;
			self.title.prefixedText,&lt;br /&gt;
			mw.loadData(&#039;Module:Category handler/blacklist&#039;)&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function CategoryHandler:isSuppressed()&lt;br /&gt;
	-- Find if categories are suppressed by either the arguments or by&lt;br /&gt;
	-- matching the blacklist.&lt;br /&gt;
	return self:isSuppressedByArguments()&lt;br /&gt;
		or not self:shouldSkipBlacklistCheck() and self:matchesBlacklist()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function CategoryHandler:getNamespaceParameters()&lt;br /&gt;
	if self._usesCurrentTitle then&lt;br /&gt;
		return self._data.currentTitleNamespaceParameters&lt;br /&gt;
	else&lt;br /&gt;
		if not mappings then&lt;br /&gt;
			mShared = mShared or require(&#039;Module:Category handler/shared&#039;)&lt;br /&gt;
			mappings = mShared.getParamMappings(true) -- gets mappings with mw.loadData&lt;br /&gt;
		end&lt;br /&gt;
		return mShared.getNamespaceParameters(&lt;br /&gt;
			self.title,&lt;br /&gt;
			mappings&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function CategoryHandler:namespaceParametersExist()&lt;br /&gt;
	-- Find whether any namespace parameters have been specified.&lt;br /&gt;
	-- We use the order &amp;quot;all&amp;quot; --&amp;gt; namespace params --&amp;gt; &amp;quot;other&amp;quot; as this is what&lt;br /&gt;
	-- the old template did.&lt;br /&gt;
	if self:parameter(&#039;all&#039;) then&lt;br /&gt;
		return true&lt;br /&gt;
	end&lt;br /&gt;
	if not mappings then&lt;br /&gt;
		mShared = mShared or require(&#039;Module:Category handler/shared&#039;)&lt;br /&gt;
		mappings = mShared.getParamMappings(true) -- gets mappings with mw.loadData&lt;br /&gt;
	end&lt;br /&gt;
	for ns, params in pairs(mappings) do&lt;br /&gt;
		for i, param in ipairs(params) do&lt;br /&gt;
			if self._args[param] then&lt;br /&gt;
				return true&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if self:parameter(&#039;other&#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;
function CategoryHandler:getCategories()&lt;br /&gt;
	local params = self:getNamespaceParameters()&lt;br /&gt;
	local nsCategory&lt;br /&gt;
	for i, param in ipairs(params) do&lt;br /&gt;
		local value = self._args[param]&lt;br /&gt;
		if value ~= nil then&lt;br /&gt;
			nsCategory = value&lt;br /&gt;
			break&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if nsCategory ~= nil or self:namespaceParametersExist() then&lt;br /&gt;
		-- Namespace parameters exist - advanced usage.&lt;br /&gt;
		if nsCategory == nil then&lt;br /&gt;
			nsCategory = self:parameter(&#039;other&#039;)&lt;br /&gt;
		end&lt;br /&gt;
		local ret = {self:parameter(&#039;all&#039;)}&lt;br /&gt;
		local numParam = tonumber(nsCategory)&lt;br /&gt;
		if numParam and numParam &amp;gt;= 1 and math.floor(numParam) == numParam then&lt;br /&gt;
			-- nsCategory is an integer&lt;br /&gt;
			ret[#ret + 1] = self._args[numParam]&lt;br /&gt;
		else&lt;br /&gt;
			ret[#ret + 1] = nsCategory&lt;br /&gt;
		end&lt;br /&gt;
		if #ret &amp;lt; 1 then&lt;br /&gt;
			return nil&lt;br /&gt;
		else&lt;br /&gt;
			return table.concat(ret)&lt;br /&gt;
		end&lt;br /&gt;
	elseif self._data.defaultNamespaces[self.title.namespace] then&lt;br /&gt;
		-- Namespace parameters don&#039;t exist, simple usage.&lt;br /&gt;
		return self._args[1]&lt;br /&gt;
	end&lt;br /&gt;
	return nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Exports&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
function p._exportClasses()&lt;br /&gt;
	-- Used for testing purposes.&lt;br /&gt;
	return {&lt;br /&gt;
		CategoryHandler = CategoryHandler&lt;br /&gt;
	}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._main(args, data)&lt;br /&gt;
	data = data or mw.loadData(&#039;Module:Category handler/data&#039;)&lt;br /&gt;
	local handler = CategoryHandler.new(data, args)&lt;br /&gt;
	if handler:isSuppressed() then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	return handler:getCategories()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.main(frame, data)&lt;br /&gt;
	data = data or mw.loadData(&#039;Module:Category handler/data&#039;)&lt;br /&gt;
	local args = require(&#039;Module:Arguments&#039;).getArgs(frame, {&lt;br /&gt;
		wrappers = data.wrappers,&lt;br /&gt;
		valueFunc = function (k, v)&lt;br /&gt;
			v = trimWhitespace(v)&lt;br /&gt;
			if type(k) == &#039;number&#039; then&lt;br /&gt;
				if v ~= &#039;&#039; then&lt;br /&gt;
					return v&lt;br /&gt;
				else&lt;br /&gt;
					return nil&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				return v&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	})&lt;br /&gt;
	return p._main(args, data)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Module:Catalog_lookup_link&amp;diff=195</id>
		<title>Module:Catalog lookup link</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Module:Catalog_lookup_link&amp;diff=195"/>
		<updated>2020-08-22T20:23:46Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--[[&lt;br /&gt;
|1=, |2=, |3=, |4=, |5=, |6=, |7=, |8=, |9=: Optional unnamed parameters for 0 to 9 items to be listed.&lt;br /&gt;
	Whitespace is trimmed off both ends and the strings are urlencoded as if they were query strings.&lt;br /&gt;
|article-link=: Optional Wikipedia article name to link to.&lt;br /&gt;
|article-name=: Optional alternative text to be displayed for |article-link= link in front of catalog link.&lt;br /&gt;
	If not specified, |article-link= is used for display as well. If both parameters are not specified, the prefix is omitted completely.&lt;br /&gt;
|article-suffix=: Optional symbol to be displayed after article name or link (f.e. &amp;quot;:&amp;quot;; omitted, if not defined).&lt;br /&gt;
|link-prefix=: Optional prefix portion of url to external catalog item(s).&lt;br /&gt;
|link-suffix=: Optional suffix portion of url to external catalog item(s).&lt;br /&gt;
|item-prefix=: Optional text displayed in front of each external link (omitted, if not defined)&lt;br /&gt;
|item-suffix=: Optional text displayed immediately after each external link (omitted, if not defined)&lt;br /&gt;
|list-separator=: Optional alternative separator displayed between list items (default: &amp;quot;, &amp;quot;, if not specified). Whitespace must be encoded.&lt;br /&gt;
|list-leadout=: Optional alternative leadout text displayed between the last two list items (f.e. &amp;quot;and&amp;quot;, &amp;quot;or&amp;quot;, &amp;quot;as well as&amp;quot;, etc., default is the |list-separator= or &amp;quot;, &amp;quot;.)&lt;br /&gt;
|leadout-suffix=: Optional alternative suffix text of the leadout (see |list-leadout=) displayed between the last two list items.&lt;br /&gt;
	This gets added in front of the last list item instead of the default whitespace which is added without this parameter.&lt;br /&gt;
	This may be necessary if |list-separator= is used not only to define the list separator but also parts of the item prefix&lt;br /&gt;
	(except for the first one). (At present, this is used only to cope with format oddities of the {{MR}} template.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
new parameters that support access icons:&lt;br /&gt;
|allowed_icons= – comma-separated list of keywords: free, limited, registration, subscription, none, all (default; &#039;all&#039; implied when this parameter empty or omitted)&lt;br /&gt;
	the icons specified in the following parameters are checked agains the list in |allowed-icons=; not in the list? not displayed&lt;br /&gt;
|url-access-all= – applies specified icon to all items in the list; accepted keywords: free, limited, registration, subscription;&lt;br /&gt;
|url-accessn= – applies specified icon to item n of the list (the nth positional parameter); accepted keywords: free, limited, registration, subscription;&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
require(&#039;Module:No globals&#039;);&lt;br /&gt;
local getArgs = require (&#039;Module:Arguments&#039;).getArgs;&lt;br /&gt;
local lock_icons = {															--icon classes are defined in Module:Citation/CS1/styles.css&lt;br /&gt;
	[&#039;free&#039;] = {&#039;id-lock-free&#039;, &#039;Freely accessible&#039;},&lt;br /&gt;
	[&#039;registration&#039;] = {&#039;id-lock-registration&#039;, &#039;Free registration required&#039;},&lt;br /&gt;
	[&#039;limited&#039;] = {&#039;id-lock-limited&#039;, &#039;Free access subject to limited trial, subscription normally required&#039;},&lt;br /&gt;
	[&#039;subscription&#039;] = {&#039;id-lock-subscription&#039;, &#039;Paid subscription required&#039;},&lt;br /&gt;
	}&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; M A K E _ L A B E L &amp;gt;----------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Makes a wikilinked or plain text label from arguments; when both link and display text is provided, makes a&lt;br /&gt;
wikilink in the form [[L|D]]; if only link is provided, makes a wikilinked label in the form [[L]]; if only display&lt;br /&gt;
is provided, makes a plain-text label; if neither are provided makes a label from suffix, returns an empty string else.&lt;br /&gt;
&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local function make_label (link, display, suffix)&lt;br /&gt;
local label = &#039;&#039;;&lt;br /&gt;
	if is_set (link) then&lt;br /&gt;
		if is_set (display) then&lt;br /&gt;
			label = table.concat ({&#039;[[&#039;, link, &#039;|&#039;, display, &#039;]]&#039;});			-- make [[L|D]] wikilinked label&lt;br /&gt;
		else&lt;br /&gt;
			label = table.concat ({&#039;[[&#039;, link, &#039;]]&#039;});							-- make [[L]] wikilinked label&lt;br /&gt;
		end&lt;br /&gt;
	elseif is_set (display) then&lt;br /&gt;
		label = display;														-- plain-text label&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if is_set (label) then														&lt;br /&gt;
		return table.concat ({label, suffix, &#039;&amp;amp;nbsp;&#039;});						-- assemble the complete label&lt;br /&gt;
	else&lt;br /&gt;
		return suffix;															-- no space after suffix if no label&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; I C O N _ I N D E X _ G E T &amp;gt;--------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
returns index into lock_icons[] if value assigned to |url-access= or |url-access-all= is a valid icon selector&lt;br /&gt;
(free, limited, registration, subscription)&lt;br /&gt;
&lt;br /&gt;
icon selection may be limited to a subset of the icons with:&lt;br /&gt;
	|allow_icons=&amp;lt;comma-separated list of allowed icons&amp;gt;&lt;br /&gt;
&amp;lt;comma-separated list of allowed icons&amp;gt; may be any of the keywords: free, limited, registration, subscription, none, all&lt;br /&gt;
&lt;br /&gt;
keyword &#039;all&#039; is default condition; &#039;all&#039; is implied when |allowed=icons= is empty or omitted&lt;br /&gt;
&lt;br /&gt;
keyword &#039;none&#039; for use with identifiers where icons are inappropriate (isbn, issn, oclc)&lt;br /&gt;
&lt;br /&gt;
Templates using this module should set:&lt;br /&gt;
	|allow_icons=free for most identifiers;&lt;br /&gt;
	|allow_icons=none for isbn, issn, oclc, etc&lt;br /&gt;
&lt;br /&gt;
|url-access= is alias of |url-access1=&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function icon_index_get (args, k)&lt;br /&gt;
	local icon;&lt;br /&gt;
	local param_name = (1 == k and is_set (args[&#039;url-access&#039;]) and &#039;url-access&#039;) or table.concat ({&#039;url-access&#039;, k});	-- make an enumerated parameter name&lt;br /&gt;
&lt;br /&gt;
	if is_set (args[&#039;url-access-all&#039;]) and lock_icons[args[&#039;url-access-all&#039;]] then	-- if set and valid&lt;br /&gt;
		icon = args[&#039;url-access-all&#039;];											-- tentatively &lt;br /&gt;
&lt;br /&gt;
	elseif is_set (args[param_name]) and lock_icons[args[param_name]] then		-- if set and valid&lt;br /&gt;
		icon = args[param_name];												-- tentatively&lt;br /&gt;
&lt;br /&gt;
	else&lt;br /&gt;
		return nil;																-- neither |url-access-all= nor |url-accessn= set so return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if args[&#039;allow_icons&#039;] and args[&#039;allow_icons&#039;]:find (&#039;none&#039;) then			-- if &#039;none&#039; keyword is present&lt;br /&gt;
		return nil;																-- icons display not allowed&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if not is_set (args[&#039;allow_icons&#039;]) or args[&#039;allow_icons&#039;]:find (&#039;all&#039;) or args[&#039;allow_icons&#039;]:find (icon) then	--if all allowed or specified icon is allowed&lt;br /&gt;
		return icon;															-- return selected icon as index into icon table&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; M A I N &amp;gt;----------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Template entrypoint to this module; arguments come primarily from the parent frame though in templates that use&lt;br /&gt;
this module, |allowed-icons= is typically set, if needed, in the {{#invoke:}}.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function main (frame)&lt;br /&gt;
	local args = getArgs (frame);&lt;br /&gt;
	local out_text = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
	if is_set(args[1]) then&lt;br /&gt;
		local result = {};&lt;br /&gt;
		local label;&lt;br /&gt;
		&lt;br /&gt;
		local article_suffix = args[&#039;article-suffix&#039;] or args[&#039;article-postfix&#039;] or &#039;&#039;;&lt;br /&gt;
		local link_prefix = args[&#039;link-prefix&#039;] or &#039;&#039;;&lt;br /&gt;
		local link_suffix = args[&#039;link-suffix&#039;] or args[&#039;link-postfix&#039;] or &#039;&#039;;&lt;br /&gt;
		local item_prefix = args[&#039;item-prefix&#039;] or &#039;&#039;;&lt;br /&gt;
		local item_suffix = args[&#039;item-suffix&#039;] or args[&#039;item-postfix&#039;] or &#039;&#039;;&lt;br /&gt;
		local list_separator = args[&#039;list-separator&#039;] or &#039;, &#039;;&lt;br /&gt;
		local leadout_suffix = args[&#039;leadout-suffix&#039;] or args[&#039;leadout-postfix&#039;] or &#039; &#039;;&lt;br /&gt;
		local list_leadout;&lt;br /&gt;
&lt;br /&gt;
		local icon_index;&lt;br /&gt;
		&lt;br /&gt;
		if is_set (args[&#039;list-leadout&#039;]) then&lt;br /&gt;
			list_leadout = table.concat ({&lt;br /&gt;
				mw.ustring.gsub (args[&#039;list-leadout&#039;], &#039;^(%a)&#039;, &#039; %1&#039;),			-- insert leading space if first character is a letter&lt;br /&gt;
				leadout_suffix,&lt;br /&gt;
			});&lt;br /&gt;
		else&lt;br /&gt;
			list_leadout = &#039;&#039;;&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		label = make_label (args[&#039;article-link&#039;], args[&#039;article-name&#039;], article_suffix);&lt;br /&gt;
&lt;br /&gt;
		for k, item in ipairs (args) do											-- for each of the positional parameters&lt;br /&gt;
			item = mw.text.trim (item);											-- remove extraneous whitespace&lt;br /&gt;
			if is_set (link_prefix) then										-- if there is link prefix...&lt;br /&gt;
				item = table.concat ({											-- create an external link item&lt;br /&gt;
					&#039;[&#039;,														-- open ext link markup&lt;br /&gt;
					link_prefix,												-- url prefix&lt;br /&gt;
					mw.uri.encode (item),										-- item is part of url&lt;br /&gt;
					link_suffix,												-- url suffix&lt;br /&gt;
					&#039; &#039;,														-- required space between url and label&lt;br /&gt;
					item_prefix,												-- label prefix&lt;br /&gt;
					item,														-- item as label&lt;br /&gt;
					item_suffix,												-- item suffix&lt;br /&gt;
					&#039;]&#039;															-- close ext link markup&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				icon_index = icon_index_get (args, k);							-- set if icon specified and allowed for this item; nil else&lt;br /&gt;
				if icon_index then&lt;br /&gt;
					item = table.concat ({										-- add access icon markup to this item&lt;br /&gt;
						&#039;&amp;lt;span class=&amp;quot;&#039;,										-- open the opening span tag; icon classes are defined in Module:Citation/CS1/styles.css&lt;br /&gt;
						lock_icons[icon_index][1],								-- add the appropriate lock icon class&lt;br /&gt;
						&#039;&amp;quot; title=&amp;quot;&#039;,											-- and the title attribute&lt;br /&gt;
						lock_icons[icon_index][2],								-- for an appropriate tool tip&lt;br /&gt;
						&#039;&amp;quot;&amp;gt;&#039;,													-- close the opening span tag&lt;br /&gt;
						item,&lt;br /&gt;
						&#039;&amp;lt;/span&amp;gt;&#039;,												-- and close the span&lt;br /&gt;
					});&lt;br /&gt;
				end	&lt;br /&gt;
			else&lt;br /&gt;
				item = table.concat ({											-- create an unlinked item&lt;br /&gt;
					item_prefix,												-- label prefix&lt;br /&gt;
					item,														-- item as label&lt;br /&gt;
					item_suffix,												-- item suffix&lt;br /&gt;
				});&lt;br /&gt;
			end&lt;br /&gt;
	&lt;br /&gt;
			table.insert (result, item);										-- add the item to the result list&lt;br /&gt;
		end&lt;br /&gt;
	&lt;br /&gt;
		if is_set (args[&#039;list-leadout&#039;]) then&lt;br /&gt;
			out_text = table.concat ({label, mw.text.listToText (result, list_separator, list_leadout)});&lt;br /&gt;
		else&lt;br /&gt;
			out_text = table.concat ({label, table.concat (result, list_separator)});&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
	end	--is_set (args[1])&lt;br /&gt;
&lt;br /&gt;
	return out_text&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return {main = main};&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Module:Authority_control&amp;diff=193</id>
		<title>Module:Authority control</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Module:Authority_control&amp;diff=193"/>
		<updated>2020-08-22T20:23:46Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;require(&#039;Module:No globals&#039;)&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
local title = mw.title.getCurrentTitle()&lt;br /&gt;
local namespace = title.namespace&lt;br /&gt;
local testcases = (string.sub(title.subpageText,1,9) == &#039;testcases&#039;)&lt;br /&gt;
&lt;br /&gt;
--[[==========================================================================]]&lt;br /&gt;
--[[                            Category functions                            ]]&lt;br /&gt;
--[[==========================================================================]]&lt;br /&gt;
&lt;br /&gt;
function p.getCatForId( id )&lt;br /&gt;
	local catName = &#039;&#039;&lt;br /&gt;
	if namespace == 0 then&lt;br /&gt;
		catName = &#039;Wikipedia articles with &#039;..id..&#039; identifiers&#039;&lt;br /&gt;
	elseif namespace == 2 and not title.isSubpage then&lt;br /&gt;
		catName = &#039;User pages with &#039;..id..&#039; identifiers&#039;&lt;br /&gt;
	else&lt;br /&gt;
		catName = &#039;Miscellaneous pages with &#039;..id..&#039; identifiers&#039;&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[[Category:&#039;..catName..&#039;]]&#039;..p.redCatLink(catName)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.redCatLink( catName ) --catName == &#039;Blah&#039;, not &#039;Category:Blah&#039;, not &#039;[[Category:Blah]]&#039;&lt;br /&gt;
	if catName and catName ~= &#039;&#039; and&lt;br /&gt;
	   testcases == false and&lt;br /&gt;
	   mw.title.new(catName, 14).exists == false&lt;br /&gt;
	then&lt;br /&gt;
		return &#039;[[Category:Pages with red-linked authority control categories]]&#039;&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;&#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[==========================================================================]]&lt;br /&gt;
--[[                      Property formatting functions                       ]]&lt;br /&gt;
--[[==========================================================================]]&lt;br /&gt;
&lt;br /&gt;
function p.aagLink( id )&lt;br /&gt;
	--P3372&#039;s format regex: \d+ (e.g. 1)&lt;br /&gt;
	if not id:match( &#039;^%d+$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://www.aucklandartgallery.com/explore-art-and-ideas/artist/&#039;..id..&#039;/ &#039;..id..&#039;]&#039;..p.getCatForId( &#039;AAG&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.acmLink( id )&lt;br /&gt;
	--P864&#039;s format regex: \d{11} (e.g. 12345678901)&lt;br /&gt;
	if not id:match( &#039;^%d%d%d%d%d%d%d%d%d%d%d$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://dl.acm.org/profile/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;ACM-DL&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.adbLink( id )&lt;br /&gt;
	--P1907&#039;s format regex: [a-z][-a-z]+-([1-2]\d|[1-9])\d{0,3} (e.g. barton-sir-edmund-toby-71)&lt;br /&gt;
	if not id:match( &#039;^[a-z][-a-z]+-[1-2]%d%d?%d?%d?$&#039; ) and&lt;br /&gt;
	   not id:match( &#039;^[a-z][-a-z]+-[1-9]%d?%d?%d?$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[http://adb.anu.edu.au/biography/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;ADB&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.agsaLink( id )&lt;br /&gt;
	--P6804&#039;s format regex: [1-9]\d* (e.g. 3625)&lt;br /&gt;
	if not id:match( &#039;^[1-9]%d*$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://www.agsa.sa.gov.au/collection-publications/collection/creators/_/&#039;..id..&#039;/ &#039;..id..&#039;]&#039;..p.getCatForId( &#039;AGSA&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.autoresuyLink( id )&lt;br /&gt;
	--P2558&#039;s format regex: [1-9]\d{0,4} (e.g. 12345)&lt;br /&gt;
	if not id:match( &#039;^[1-9]%d?%d?%d?%d?$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://autores.uy/autor/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;autores.uy&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.awrLink( id )&lt;br /&gt;
	--P4186&#039;s format regex: (([A-Z]{3}\d{4})|([A-Z]{2}\d{5}))[a-z] (e.g. PR00768b)&lt;br /&gt;
	if not id:match( &#039;^[A-Z][A-Z][A-Z]%d%d%d%d[a-z]$&#039; ) and&lt;br /&gt;
	   not id:match( &#039;^[A-Z][A-Z]%d%d%d%d%d[a-z]$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[http://www.womenaustralia.info/biogs/&#039;..id..&#039;.htm &#039;..id..&#039;]&#039;..p.getCatForId( &#039;AWR&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.balatLink( id )&lt;br /&gt;
	--P3293&#039;s format regex: \d+ (e.g. 1)&lt;br /&gt;
	if not id:match( &#039;^%d+$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[http://balat.kikirpa.be/object/104257&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;BALaT&#039; ) --no https as of 9/2019&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.bibsysLink( id )&lt;br /&gt;
	--P1015&#039;s format regex: [1-9]\d* or [1-9](\d{0,8}|\d{12}) (e.g. 1234567890123)&lt;br /&gt;
	--TODO: follow up @ [[d:Property talk:P1015#Discrepancy between the 2 regex constraints]] or escalate/investigate&lt;br /&gt;
	if not id:match( &#039;^[1-9]%d?%d?%d?%d?%d?%d?%d?%d?$&#039; ) and&lt;br /&gt;
	   not id:match( &#039;^[1-9]%d%d%d%d%d%d%d%d%d%d%d%d$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://authority.bibsys.no/authority/rest/authorities/html/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;BIBSYS&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.bildLink( id )&lt;br /&gt;
	--P2092&#039;s format regex: \d+ (e.g. 1)&lt;br /&gt;
	if not id:match( &#039;^%d+$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://www.bildindex.de/document/obj&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;Bildindex&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.bncLink( id )&lt;br /&gt;
	--P1890&#039;s format regex: \d{9} (e.g. 123456789)&lt;br /&gt;
	if not id:match( &#039;^%d%d%d%d%d%d%d%d%d$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[http://www.bncatalogo.cl/F?func=direct&amp;amp;local_base=red10&amp;amp;doc_number=&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;BNC&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.bneLink( id )&lt;br /&gt;
	--P950&#039;s format regex: (XX|FF|a)\d{4,7}|(bima|bimo|bica|bis[eo]|bivi|Mise|Mimo|Mima)\d{10} (e.g. XX1234567)&lt;br /&gt;
	if not id:match( &#039;^[XF][XF]%d%d%d%d%d?%d?%d?$&#039; ) and&lt;br /&gt;
	   not id:match( &#039;^a%d%d%d%d%d?%d?%d?$&#039; ) and&lt;br /&gt;
	   not id:match( &#039;^bi[mcsv][aoei]%d%d%d%d%d%d%d%d%d%d$&#039; ) and&lt;br /&gt;
	   not id:match( &#039;^Mi[sm][eoa]%d%d%d%d%d%d%d%d%d%d$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[http://catalogo.bne.es/uhtbin/authoritybrowse.cgi?action=display&amp;amp;authority_id=&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;BNE&#039; ) --no https as of 9/2019&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.bnfLink( id )&lt;br /&gt;
	--P268&#039;s format regex: \d{8}[0-9bcdfghjkmnpqrstvwxz] (e.g. 123456789)&lt;br /&gt;
	if not id:match( &#039;^c?b?%d%d%d%d%d%d%d%d[0-9bcdfghjkmnpqrstvwxz]$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	--Add cb prefix if it has been removed&lt;br /&gt;
	if not id:match( &#039;^cb.+$&#039; ) then&lt;br /&gt;
		id = &#039;cb&#039;..id&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://catalogue.bnf.fr/ark:/12148/&#039;..id..&#039; &#039;..id..&#039;] [https://data.bnf.fr/ark:/12148/&#039;..id..&#039; (data)]&#039;..p.getCatForId( &#039;BNF&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.botanistLink( id )&lt;br /&gt;
	--P428&#039;s format regex: (&#039;t )?(d&#039;)?(de )?(la )?(van (der )?)?(Ma?c)?(De)?(Di)?\p{Lu}?C?[&#039;\p{Ll}]*([-&#039;. ]*(van )?(y )?(d[ae][nr]?[- ])?(Ma?c)?[\p{Lu}bht]?C?[&#039;\p{Ll}]*)*\.? ?f?\.? (e.g. L.)&lt;br /&gt;
	--not easily/meaningfully implementable in Lua&#039;s regex since &amp;quot;(this)?&amp;quot; is not allowed...&lt;br /&gt;
	if not mw.ustring.match( id, &amp;quot;^[%u%l%d%. &#039;-]+$&amp;quot; ) then --better than nothing&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	local id2 = id:gsub(&#039; +&#039;, &#039;%%20&#039;)&lt;br /&gt;
	return &#039;[https://www.ipni.org/ipni/advAuthorSearch.do?find_abbreviation=&#039;..id2..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;Botanist&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.bpnLink( id )&lt;br /&gt;
	--P651&#039;s format regex: \d{6,8} (e.g. 00123456)&lt;br /&gt;
	if not id:match( &#039;^%d%d%d%d%d%d%d%d$&#039; ) and --original format regex, changed 8/2019 to&lt;br /&gt;
	   not id:match( &#039;^0?%d%d%d%d%d%d%d$&#039; ) and --allow 1-2 leading 0s, allowed by the website&lt;br /&gt;
	   not id:match( &#039;^0?0?%d%d%d%d%d%d$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[http://www.biografischportaal.nl/en/persoon/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;BPN&#039; ) --no https as of 9/2019&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.canticLink( id )&lt;br /&gt;
	--P1273&#039;s format regex: a\d{7}[0-9x] (e.g. a10640745)&lt;br /&gt;
	if not id:match( &#039;^a%d%d%d%d%d%d%d[%dx]$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[http://cantic.bnc.cat/registres/CUCId/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;CANTIC&#039; ) --no https as of 10/2019&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.ciniiLink( id )&lt;br /&gt;
	--P271&#039;s format regex: DA\d{7}[\dX] (e.g. DA12345678)&lt;br /&gt;
	if not id:match( &#039;^DA%d%d%d%d%d%d%d[%dX]$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://ci.nii.ac.jp/author/&#039;..id..&#039;?l=en &#039;..id..&#039;]&#039;..p.getCatForId( &#039;CINII&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.daaoLink( id )&lt;br /&gt;
	--P1707&#039;s format regex: [a-z\-]+\d* (e.g. rolf-harris)&lt;br /&gt;
	if not id:match( &#039;^[a-z%-]+%d*$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://www.daao.org.au/bio/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;DAAO&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.dblpLink( id )&lt;br /&gt;
	--P2456&#039;s format regex: \d{2,3} /\d+(-\d+)?|[a-z] /[a-zA-Z][0-9A-Za-z]*(-\d+)? (e.g. 123/123)&lt;br /&gt;
	if not id:match( &#039;^%d%d%d?/%d+$&#039; ) and&lt;br /&gt;
	   not id:match( &#039;^%d%d%d?/%d+%-%d+$&#039; ) and&lt;br /&gt;
	   not id:match( &#039;^[a-z]/[a-zA-Z][0-9A-Za-z]*$&#039; ) and&lt;br /&gt;
	   not id:match( &#039;^[a-z]/[a-zA-Z][0-9A-Za-z]*%-%d+$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://dblp.org/pid/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;DBLP&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.dsiLink( id )&lt;br /&gt;
	--P2349&#039;s format regex: [1-9]\d* (e.g. 1538)&lt;br /&gt;
	if not id:match( &#039;^[1-9]%d*$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[http://www.uni-stuttgart.de/hi/gnt/dsi2/index.php?table_name=dsi&amp;amp;function=details&amp;amp;where_field=id&amp;amp;where_value=&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;DSI&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.fnzaLink( id )&lt;br /&gt;
	--P6792&#039;s format regex: [1-9]\d* (e.g. 9785)&lt;br /&gt;
	if not id:match( &#039;^[1-9]%d*$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://findnzartists.org.nz/artist/&#039;..id..&#039;/ &#039;..id..&#039;]&#039;..p.getCatForId( &#039;FNZA&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.gndLink( id )&lt;br /&gt;
	--P227&#039;s format regex: 1[012]?\d{7}[0-9X]|[47]\d{6}-\d|[1-9]\d{0,7}-[0-9X]|3\d{7}[0-9X] (e.g. 4079154-3)&lt;br /&gt;
	if not id:match( &#039;^1[012]?%d%d%d%d%d%d%d[0-9X]$&#039; ) and&lt;br /&gt;
	   not id:match( &#039;^[47]%d%d%d%d%d%d%-%d$&#039; ) and&lt;br /&gt;
	   not id:match( &#039;^[1-9]%d?%d?%d?%d?%d?%d?%d?%-[0-9X]$&#039; ) and&lt;br /&gt;
	   not id:match( &#039;^3%d%d%d%d%d%d%d[0-9X]$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://d-nb.info/gnd/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;GND&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.hdsLink( id )&lt;br /&gt;
	--P902&#039;s format regex: \d{6} (e.g. 050123)&lt;br /&gt;
	if not id:match( &#039;^%d%d%d%d%d%d$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://hls-dhs-dss.ch/fr/articles/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;HDS&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.iaafLink( id )&lt;br /&gt;
	--P1146&#039;s format regex: [0-9][0-9]* (e.g. 012)&lt;br /&gt;
	if not id:match( &#039;^%d+$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://www.iaaf.org/athletes/_/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;IAAF&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.iciaLink( id )&lt;br /&gt;
	--P1736&#039;s format regex: \d+ (e.g. 1)&lt;br /&gt;
	if not id:match( &#039;^%d+$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://www.imj.org.il/artcenter/newsite/en/?artist=&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;ICIA&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.isniLink( id )&lt;br /&gt;
	id = p.validateIsni( id ) --e.g. 0000-0000-6653-4145&lt;br /&gt;
	if not id then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[http://isni.org/isni/&#039;..id..&#039; &#039;..id:sub( 1, 4 )..&#039; &#039;..id:sub( 5, 8 )..&#039; &#039;..id:sub( 9, 12 )..&#039; &#039;..id:sub( 13, 16 )..&#039;]&#039;..p.getCatForId( &#039;ISNI&#039; ) --no https as of 9/2019&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.jocondeLink( id )&lt;br /&gt;
	--P347&#039;s format regex: [\-0-9A-Za-z]{11} (e.g. 12345678901)&lt;br /&gt;
	local regex = &#039;^&#039;..string.rep(&#039;[%-0-9A-Za-z]&#039;, 11)..&#039;$&#039;&lt;br /&gt;
	if not id:match( regex ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://www.pop.culture.gouv.fr/notice/joconde/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;Joconde&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.kulturnavLink( id )&lt;br /&gt;
	--P1248&#039;s format regex: [0-9a-f]{8}\-[0-9a-f]{4}\-[0-9a-f]{4}\-[0-9a-f]{4}\-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB)&lt;br /&gt;
	if not id:match( &#039;^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[http://kulturnav.org/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;KULTURNAV&#039; ) --no https as of 9/2019&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.lccnLink( id )&lt;br /&gt;
	local parts = p.splitLccn( id ) --e.g. n78039510&lt;br /&gt;
	if not parts then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	local lccnType = parts[1] ~= &#039;sh&#039; and &#039;names&#039; or &#039;subjects&#039;&lt;br /&gt;
	id = parts[1] .. parts[2] .. p.append( parts[3], &#039;0&#039;, 6 )&lt;br /&gt;
	return &#039;[https://id.loc.gov/authorities/&#039;..lccnType..&#039;/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;LCCN&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.lirLink( id )&lt;br /&gt;
	--P886&#039;s format regex: \d+ (e.g. 1)&lt;br /&gt;
	if not id:match( &#039;^%d+$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[http://www.e-lir.ch/e-LIR___Lexicon.&#039;..id..&#039;.450.0.html &#039;..id..&#039;]&#039;..p.getCatForId( &#039;LIR&#039; ) --no https as of 9/2019&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.lnbLink( id )&lt;br /&gt;
	--P1368&#039;s format regex: \d{9} (e.g. 123456789)&lt;br /&gt;
	if not id:match( &#039;^%d%d%d%d%d%d%d%d%d$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://kopkatalogs.lv/F?func=direct&amp;amp;local_base=lnc10&amp;amp;doc_number=&#039;..id..&#039;&amp;amp;P_CON_LNG=ENG &#039;..id..&#039;]&#039;..p.getCatForId( &#039;LNB&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.leonoreLink( id )&lt;br /&gt;
	--P640&#039;s format regex: LH/\d{1,4}/\d{1,3}|19800035/\d{1,4}/\d{1,5}(Bis)?|C/0/\d{1,2} (e.g. LH/2064/18)&lt;br /&gt;
	if not id:match( &#039;^LH/%d%d?%d?%d?/%d%d?%d?$&#039; ) and             --IDs from       LH/1/1 to         LH/2794/54 (legionaries)&lt;br /&gt;
	   not id:match( &#039;^19800035/%d%d?%d?%d?/%d%d?%d?%d?%d?$&#039; ) and --IDs from 19800035/1/1 to 19800035/385/51670 (legionnaires who died 1954-1977 &amp;amp; some who died &amp;lt; 1954)&lt;br /&gt;
	   not id:match( &#039;^C/0/%d%d?$&#039; ) then                          --IDs from        C/0/1 to             C/0/84 (84 famous legionaries)&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[http://www.culture.gouv.fr/public/mistral/leonore_fr?ACTION=CHERCHER&amp;amp;FIELD_1=COTE&amp;amp;VALUE_1=&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;Léonore&#039; ) --no https as of 9/2019&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.mbaLink( id )&lt;br /&gt;
	--P434&#039;s format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB)&lt;br /&gt;
	if not id:match( &#039;^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://musicbrainz.org/artist/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;MusicBrainz&#039; ) --special category name&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.mbareaLink( id )&lt;br /&gt;
	--P982&#039;s format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB)&lt;br /&gt;
	if not id:match( &#039;^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://musicbrainz.org/area/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;MusicBrainz area&#039; ) --special category name&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.mbiLink( id )&lt;br /&gt;
	--P1330&#039;s format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB)&lt;br /&gt;
	if not id:match( &#039;^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://musicbrainz.org/instrument/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;MusicBrainz instrument&#039; ) --special category name&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.mblLink( id )&lt;br /&gt;
	--P966&#039;s format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB)&lt;br /&gt;
	if not id:match( &#039;^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://musicbrainz.org/label/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;MusicBrainz label&#039; ) --special category name&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.mbpLink( id )&lt;br /&gt;
	--P1004&#039;s format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB)&lt;br /&gt;
	if not id:match( &#039;^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://musicbrainz.org/place/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;MusicBrainz place&#039; ) --special category name&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.mbrgLink( id )&lt;br /&gt;
	--P436&#039;s format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB)&lt;br /&gt;
	if not id:match( &#039;^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://musicbrainz.org/release-group/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;MusicBrainz release group&#039; ) --special category name&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.mbsLink( id )&lt;br /&gt;
	--P1407&#039;s format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB)&lt;br /&gt;
	if not id:match( &#039;^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://musicbrainz.org/series/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;MusicBrainz series&#039; ) --special category name&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.mbwLink( id )&lt;br /&gt;
	--P435&#039;s format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB)&lt;br /&gt;
	if not id:match( &#039;^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://musicbrainz.org/work/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;MusicBrainz work&#039; ) --special category name&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.mgpLink( id )&lt;br /&gt;
	--P549&#039;s format regex: \d{1,6} (e.g. 123456)&lt;br /&gt;
	if not id:match( &#039;^%d%d?%d?%d?%d?%d?$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://genealogy.math.ndsu.nodak.edu/id.php?id=&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;MGP&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.naraLink( id )&lt;br /&gt;
	--P1225&#039;s format regex: ^([1-9]\d{0,8})$ (e.g. 123456789)&lt;br /&gt;
	if not id:match( &#039;^[1-9]%d?%d?%d?%d?%d?%d?%d?%d?$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://catalog.archives.gov/id/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;NARA&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.nclLink( id )&lt;br /&gt;
	--P1048&#039;s format regex: \d+ (e.g. 1081436)&lt;br /&gt;
	if not id:match( &#039;^%d+$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[http://aleweb.ncl.edu.tw/F/?func=accref&amp;amp;acc_sequence=&#039;..id..&#039;&amp;amp;CON_LNG=ENG &#039;..id..&#039;]&#039;..p.getCatForId( &#039;NCL&#039; ) --no https as of 9/2019&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.ndlLink( id )&lt;br /&gt;
	--P349&#039;s format regex: 0?\d{8} (e.g. 012345678)&lt;br /&gt;
	if not id:match( &#039;^0?%d%d%d%d%d%d%d%d$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://id.ndl.go.jp/auth/ndlna/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;NDL&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.ngvLink( id )&lt;br /&gt;
	--P2041&#039;s format regex: \d+ (e.g. 12354)&lt;br /&gt;
	if not id:match( &#039;^%d+$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://www.ngv.vic.gov.au/explore/collection/artist/&#039;..id..&#039;/ &#039;..id..&#039;]&#039;..p.getCatForId( &#039;NGV&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.nkcLink( id )&lt;br /&gt;
	--P691&#039;s format regex: [a-z]{2,4}[0-9]{2,14} (e.g. abcd12345678901234)&lt;br /&gt;
	if not id:match( &#039;^[a-z][a-z][a-z]?[a-z]?%d%d%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://aleph.nkp.cz/F/?func=find-c&amp;amp;local_base=aut&amp;amp;ccl_term=ica=&#039;..id..&#039;&amp;amp;CON_LNG=ENG &#039;..id..&#039;]&#039;..p.getCatForId( &#039;NKC&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.nlaLink( id )&lt;br /&gt;
	--P409&#039;s format regex: [1-9][0-9]{0,11} (e.g. 123456789012)&lt;br /&gt;
	if not id:match( &#039;^[1-9]%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://nla.gov.au/anbd.aut-an&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;NLA&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.nlgLink( id )&lt;br /&gt;
	--P3348&#039;s format regex: [1-9]\d* (e.g. 1)&lt;br /&gt;
	if not id:match( &#039;^[1-9]%d*$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://data.nlg.gr/resource/authority/record&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;NLG&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.nliLink( id )&lt;br /&gt;
	--P949&#039;s format regex: \d{9} (e.g. 123456789)&lt;br /&gt;
	if not id:match( &#039;^%d%d%d%d%d%d%d%d%d$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[http://uli.nli.org.il/F/?func=direct&amp;amp;doc_number=&#039;..id..&#039;&amp;amp;local_base=nlx10&#039;..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;NLI&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.nlkLink( id )&lt;br /&gt;
	--P5034&#039;s format regex: KA.(19|20).{7} (e.g. KAC201501465)&lt;br /&gt;
	if not id:match( &#039;^KA.19.......$&#039; ) and&lt;br /&gt;
	   not id:match( &#039;^KA.20.......$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://nl.go.kr/authorities/resource/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;NLK&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.nlpLink( id )&lt;br /&gt;
	--P1695&#039;s format regex: 9810[0-9]\d* or A[0-9]{7}[0-9X] (e.g. 9810123456789012345 or A10414836)&lt;br /&gt;
	if not id:match( &#039;^9810%d+$&#039; ) and&lt;br /&gt;
	   not id:match( &#039;^A%d%d%d%d%d%d%d[%dX]$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://tools.wmflabs.org/wikidata-externalid-url?p=1695&amp;amp;id=&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;NLP&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.nlrLink( id )&lt;br /&gt;
	--P1003&#039;s format regex: \d{9} (e.g. 123456789)&lt;br /&gt;
	if not id:match( &#039;^%d%d%d%d%d%d%d%d%d$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[http://alephnew.bibnat.ro:8991/F?func=find-b&amp;amp;request=&#039;..id..&#039;&amp;amp;find_code=SYS&amp;amp;adjacent=Y&amp;amp;local_base=NLR10 &#039;..id..&#039;]&#039;..p.getCatForId( &#039;NLR&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.nskLink( id )&lt;br /&gt;
	--P1375&#039;s format regex: \d{9} (e.g. 123456789)&lt;br /&gt;
	if not id:match( &#039;^%d%d%d%d%d%d%d%d%d$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[http://katalog.nsk.hr/F/?func=direct&amp;amp;doc_number=&#039;..id..&#039;&amp;amp;local_base=nsk10 &#039;..id..&#039;]&#039;..p.getCatForId( &#039;NSK&#039; ) --no https as of 9/2019&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.ntaLink( id )&lt;br /&gt;
	--P1006&#039;s format regex: \d{8}[\dX] (e.g. 12345678X)&lt;br /&gt;
	if not id:match( &#039;^%d%d%d%d%d%d%d%d[%dX]$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[http://data.bibliotheken.nl/id/thes/p&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;NTA&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.orcidLink( id )&lt;br /&gt;
	id = p.validateIsni( id ) --e.g. 0000-0002-7398-5483&lt;br /&gt;
	if not id then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	id = id:sub( 1, 4 )..&#039;-&#039;..id:sub( 5, 8 )..&#039;-&#039;..id:sub( 9, 12 )..&#039;-&#039;..id:sub( 13, 16 )&lt;br /&gt;
	return &#039;[https://orcid.org/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;ORCID&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.picLink( id )&lt;br /&gt;
	--P2750&#039;s format regex: [1-9]\d* (e.g. 1)&lt;br /&gt;
	if not id:match( &#039;^[1-9]%d*$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://pic.nypl.org/constituents/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;PIC&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.ridLink( id )&lt;br /&gt;
	--P1053&#039;s format regex: [A-Z]{1,3}-\d{4}-20[0-2]\d   (e.g. AAS-5150-2020)&lt;br /&gt;
	if not id:match( &#039;^[A-Z][A-Z]?[A-Z]?%-%d%d%d%d%-20[0-2]%d$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://www.researcherid.com/rid/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;RID&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.reroLink( id )&lt;br /&gt;
	--P3065&#039;s format regex: 0[1-2]-[A-Z0-9]{1,10} (e.g. 02-A012345678)&lt;br /&gt;
	if not id:match( &#039;^0[1-2]%-[A-Z%d][A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[http://data.rero.ch/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;RERO&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.rkdartistsLink( id )&lt;br /&gt;
	--P650&#039;s format regex: [1-9]\d{0,5} (e.g. 123456)&lt;br /&gt;
	if not id:match( &#039;^[1-9]%d?%d?%d?%d?%d?$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://rkd.nl/en/explore/artists/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;RKDartists&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.rkdidLink( id )&lt;br /&gt;
	--P350&#039;s format regex: [1-9]\d{0,5} (e.g. 123456)&lt;br /&gt;
	if not id:match( &#039;^[1-9]%d?%d?%d?%d?%d?$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://rkd.nl/nl/explore/images/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;RKDID&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.rslLink( id )&lt;br /&gt;
	--P947&#039;s format regex: \d{1,9} (e.g. 123456789)&lt;br /&gt;
	if not id:match( &#039;^%d%d?%d?%d?%d?%d?%d?%d?%d?$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[http://aleph.rsl.ru/F?func=find-b&amp;amp;find_code=SYS&amp;amp;adjacent=Y&amp;amp;local_base=RSL11&amp;amp;request=&#039;..id..&#039;&amp;amp;CON_LNG=ENG &#039;..id..&#039;]&#039;..p.getCatForId( &#039;RSL&#039; ) --no https as of 9/2019&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.sbnLink( id )&lt;br /&gt;
	--P396&#039;s format regex: IT\\ICCU\\(\d{10}|\D\D[\D\d]\D\\\d{6}) (e.g. IT\ICCU\CFIV\000163)&lt;br /&gt;
	if not id:match( &#039;^IT\\ICCU\\%d%d%d%d%d%d%d%d%d%d$&#039; ) and&lt;br /&gt;
	   not id:match( &#039;^IT\\ICCU\\%u%u[%u%d]%u\\%d%d%d%d%d%d$&#039; ) then --legacy: %u used here instead of %D (but the faulty ID cat is empty, out of ~12k uses)&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://opac.sbn.it/opacsbn/opac/iccu/scheda_authority.jsp?bid=&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;SBN&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.selibrLink( id )&lt;br /&gt;
	--P906&#039;s format regex: [1-9]\d{4,5} (e.g. 123456)&lt;br /&gt;
	if not id:match( &#039;^[1-9]%d%d%d%d%d?$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://libris.kb.se/auth/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;SELIBR&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.sikartLink( id )&lt;br /&gt;
	--P781&#039;s format regex: \d{7,9} (e.g. 123456789)&lt;br /&gt;
	if not id:match( &#039;^%d%d%d%d%d%d%d%d?%d?$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[http://www.sikart.ch/KuenstlerInnen.aspx?id=&#039;..id..&#039;&amp;amp;lng=en &#039;..id..&#039;]&#039;..p.getCatForId( &#039;SIKART&#039; ) --no https as of 9/2019&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.snacLink( id )&lt;br /&gt;
	--P3430&#039;s format regex: \d*[A-Za-z][0-9A-Za-z]* (e.g. A)&lt;br /&gt;
	if not id:match( &#039;^%d*[A-Za-z][0-9A-Za-z]*$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://snaccooperative.org/ark:/99166/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;SNAC-ID&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.sudocLink( id )&lt;br /&gt;
	--P269&#039;s format regex: (\d{8}[\dX]|) (e.g. 026927608)&lt;br /&gt;
	if not id:match( &#039;^%d%d%d%d%d%d%d%d[%dxX]$&#039; ) then --legacy: allow lowercase &#039;x&#039;&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://www.idref.fr/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;SUDOC&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.s2authoridLink( id )&lt;br /&gt;
	--P4012&#039;s format regex: [1-9]\d* (e.g. 1796130)&lt;br /&gt;
	if not id:match( &#039;^[1-9]%d*$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://www.semanticscholar.org/author/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;Semantic Scholar author&#039; ) --special category name&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.ta98Link( id )&lt;br /&gt;
	--P1323&#039;s format regex: A\d{2}\.\d\.\d{2}\.\d{3}[FM]? (e.g. A12.3.45.678)&lt;br /&gt;
	if not id:match( &#039;^A%d%d%.%d%.%d%d%.%d%d%d[FM]?$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[http://tools.wmflabs.org/wikidata-externalid-url/?p=1323&amp;amp;url_prefix=https:%2F%2Fwww.unifr.ch%2Fifaa%2FPublic%2FEntryPage%2FTA98%20Tree%2FEntity%20TA98%20EN%2F&amp;amp;url_suffix=%20Entity%20TA98%20EN.htm&amp;amp;id=&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;TA98&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.tdviaLink( id )&lt;br /&gt;
	--P7314&#039;s format regex: [a-z/-]+] (e.g. barkan-omer-lutfi)&lt;br /&gt;
	if not id:match( &#039;^[a-z/-]+$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://islamansiklopedisi.org.tr/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;TDVİA&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.teLink( id )&lt;br /&gt;
	--P1693&#039;s format regex: E[1-8]\.\d{1,2}\.\d{1,2}\.\d{1,2}\.\d{1}\.\d{1}\.\d{1,3} (e.g. E1.23.45.67.8.9.0)&lt;br /&gt;
	local e1, e2 = id:match( &#039;^E([1-8])%.(%d%d?)%.%d%d?%.%d%d?%.%d%.%d%.%d%d?%d?$&#039; )&lt;br /&gt;
	if not e1 then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	local TEnum = &#039;TEe0&#039;..e1 --no formatter URL in WD, probably due to this complexity&lt;br /&gt;
	if e1 == &#039;5&#039; or e1 == &#039;7&#039; then&lt;br /&gt;
		if #e2 == 1 then e2 = &#039;0&#039;..e2 end&lt;br /&gt;
		TEnum = TEnum..e2&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[http://www.unifr.ch/ifaa/Public/EntryPage/ViewTE/&#039;..TEnum..&#039;.html &#039;..id..&#039;]&#039;..p.getCatForId( &#039;TE&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.tepapaLink( id )&lt;br /&gt;
	--P3544&#039;s format regex: \d+ (e.g. 1)&lt;br /&gt;
	if not id:match( &#039;^%d+$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://collections.tepapa.govt.nz/agent/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;TePapa&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.thLink( id )&lt;br /&gt;
	--P1694&#039;s format regex: H\d\.\d{2}\.\d{2}\.\d\.\d{5} (e.g. H1.23.45.6.78901)&lt;br /&gt;
	local h1, h2 = id:match( &#039;^H(%d)%.(%d%d)%.%d%d%.%d%.%d%d%d%d%d$&#039; )&lt;br /&gt;
	if not h1 then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	local THnum = &#039;THh&#039;..h1..h2 --no formatter URL in WD, probably due to this complexity&lt;br /&gt;
	return &#039;[http://www.unifr.ch/ifaa/Public/EntryPage/ViewTH/&#039;..THnum..&#039;.html &#039;..id..&#039;]&#039;..p.getCatForId( &#039;TH&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.tlsLink( id )&lt;br /&gt;
	local id2 = id:gsub(&#039; +&#039;, &#039;_&#039;)&lt;br /&gt;
	--P1362&#039;s format regex: \p{Lu}[\p{L}\d_&#039;,\.\-\(\)\*/–]{3,59} (e.g. Abcd)&lt;br /&gt;
	local class = &amp;quot;[%a%d_&#039;,%.%-%(%)%*/–]&amp;quot;&lt;br /&gt;
	local regex = &amp;quot;^%u&amp;quot;..string.rep(class, 3)..string.rep(class..&amp;quot;?&amp;quot;, 56)..&amp;quot;$&amp;quot;&lt;br /&gt;
	if not mw.ustring.match( id2, regex ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[http://tls.theaterwissenschaft.ch/wiki/&#039;..id2..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;TLS&#039; ) --no https as of 9/2019&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.troveLink( id )&lt;br /&gt;
	--P1315&#039;s format regex: [1-9]\d{5,7} (e.g. 12345678)&lt;br /&gt;
	if not id:match( &#039;^[1-9]%d%d%d%d%d%d?%d?$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://trove.nla.gov.au/people/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;Trove&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.ulanLink( id )&lt;br /&gt;
	--P245&#039;s format regex: 500\d{6} (e.g. 500123456)&lt;br /&gt;
	if not id:match( &#039;^500%d%d%d%d%d%d$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://www.getty.edu/vow/ULANFullDisplay?find=&amp;amp;role=&amp;amp;nation=&amp;amp;subjectid=&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;ULAN&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.uscongressLink( id )&lt;br /&gt;
	--P1157&#039;s format regex: [A-Z]00[01]\d{3} (e.g. A000123)&lt;br /&gt;
	if not id:match( &#039;^[A-Z]00[01]%d%d%d$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[http://bioguide.congress.gov/scripts/biodisplay.pl?index=&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;USCongress&#039; ) --no https as of 9/2019&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.viafLink( id )&lt;br /&gt;
	--P214&#039;s format regex: [1-9]\d(\d{0,7}|\d{17,20}) (e.g. 123456789, 1234567890123456789012)&lt;br /&gt;
	if not id:match( &#039;^[1-9]%d%d?%d?%d?%d?%d?%d?%d?$&#039; ) and&lt;br /&gt;
	   not id:match( &#039;^[1-9]%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d?%d?%d?$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;[https://viaf.org/viaf/&#039;..id..&#039; &#039;..id..&#039;]&#039;..p.getCatForId( &#039;VIAF&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[=========================== Helper functions =============================]]&lt;br /&gt;
&lt;br /&gt;
function p.append(str, c, length)&lt;br /&gt;
	while str:len() &amp;lt; length do&lt;br /&gt;
		str = c .. str&lt;br /&gt;
	end&lt;br /&gt;
	return str&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--Returns the ISNI check digit isni must be a string where the 15 first elements are digits, e.g. 0000000066534145&lt;br /&gt;
function p.getIsniCheckDigit( isni )&lt;br /&gt;
	local total = 0&lt;br /&gt;
	for i = 1, 15 do&lt;br /&gt;
		local digit = isni:byte( i ) - 48 --Get integer value&lt;br /&gt;
		total = (total + digit) * 2&lt;br /&gt;
	end&lt;br /&gt;
	local remainder = total % 11&lt;br /&gt;
	local result = (12 - remainder) % 11&lt;br /&gt;
	if result == 10 then&lt;br /&gt;
		return &amp;quot;X&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	return tostring( result )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--Validate ISNI (and ORCID) and retuns it as a 16 characters string or returns false if it&#039;s invalid&lt;br /&gt;
--See http://support.orcid.org/knowledgebase/articles/116780-structure-of-the-orcid-identifier&lt;br /&gt;
function p.validateIsni( id )&lt;br /&gt;
	--P213 (ISNI) format regex: [0-9]{4} [0-9]{4} [0-9]{4} [0-9]{3}[0-9X] (e.g. 0000-0000-6653-4145)&lt;br /&gt;
	--P496 (ORCID) format regex: 0000-000(1-[5-9]|2-[0-9]|3-[0-4])\d{3}-\d{3}[\dX] (e.g. 0000-0002-7398-5483)&lt;br /&gt;
	id = id:gsub( &#039;[ %-]&#039;, &#039;&#039; ):upper()&lt;br /&gt;
	if not id:match( &#039;^%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d[%dX]$&#039; ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	if p.getIsniCheckDigit( id ) ~= string.char( id:byte( 16 ) ) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return id&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.splitLccn( id )&lt;br /&gt;
	--P244&#039;s format regex: (n|nb|nr|no|ns|sh)([4-9][0-9]|00|20[0-1][0-9])[0-9]{6} (e.g. n78039510)&lt;br /&gt;
	if id:match( &#039;^%l%l?%l?%d%d%d%d%d%d%d%d%d?%d?$&#039; ) then&lt;br /&gt;
		id = id:gsub( &#039;^(%l+)(%d+)(%d%d%d%d%d%d)$&#039;, &#039;%1/%2/%3&#039; )&lt;br /&gt;
	end&lt;br /&gt;
	if id:match( &#039;^%l%l?%l?/%d%d%d?%d?/%d+$&#039; ) then&lt;br /&gt;
		return mw.text.split( id, &#039;/&#039; )&lt;br /&gt;
	end&lt;br /&gt;
	return false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[==========================================================================]]&lt;br /&gt;
--[[          Wikidata, navigation bar, and documentation functions           ]]&lt;br /&gt;
--[[==========================================================================]]&lt;br /&gt;
&lt;br /&gt;
function p.getIdsFromWikidata( itemId, property )&lt;br /&gt;
	local ids = {}&lt;br /&gt;
	local statements = mw.wikibase.getBestStatements( itemId, property )&lt;br /&gt;
	if statements then&lt;br /&gt;
		for _, statement in ipairs( statements ) do&lt;br /&gt;
			if statement.mainsnak.datavalue then&lt;br /&gt;
				table.insert( ids, statement.mainsnak.datavalue.value )&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return ids&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.matchesWikidataRequirements( itemId, reqs )&lt;br /&gt;
	for _, group in ipairs( reqs ) do&lt;br /&gt;
		local property = &#039;P&#039;..group[1]&lt;br /&gt;
		local qid = group[2]&lt;br /&gt;
		local statements = mw.wikibase.getBestStatements( itemId, property )&lt;br /&gt;
		if statements then&lt;br /&gt;
			for _, statement in ipairs( statements ) do&lt;br /&gt;
				if statement.mainsnak.datavalue then&lt;br /&gt;
					if statement.mainsnak.datavalue.value[&#039;numeric-id&#039;] == qid then&lt;br /&gt;
						return true&lt;br /&gt;
	end	end	end	end	end&lt;br /&gt;
	return false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.createRow( id, label, rawValue, link, withUid, specialCat )&lt;br /&gt;
	if link then&lt;br /&gt;
		if withUid then&lt;br /&gt;
			return &#039;*&amp;lt;span class=&amp;quot;nowrap&amp;quot;&amp;gt;&#039;..label..&#039; &amp;lt;span class=&amp;quot;uid&amp;quot;&amp;gt;&#039;..link..&#039;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;\n&#039;&lt;br /&gt;
		end&lt;br /&gt;
		return &#039;*&amp;lt;span class=&amp;quot;nowrap&amp;quot;&amp;gt;&#039;..label..&#039; &#039;..link..&#039;&amp;lt;/span&amp;gt;\n&#039;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local catName = &#039;Wikipedia articles with faulty &#039;..(specialCat or id)..&#039; identifiers&#039;&lt;br /&gt;
	return &#039;* &amp;lt;span class=&amp;quot;error&amp;quot;&amp;gt;The &#039;..id..&#039; id &#039;..rawValue..&#039; is not valid.&amp;lt;/span&amp;gt;[[Category:&#039;..catName..&#039;]]&#039;..p.redCatLink(catName)..&#039;\n&#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Creates a human-readable standalone wikitable version of p.conf, and tracking categories with page counts, for use in the documentation&lt;br /&gt;
function p.docConfTable( frame )&lt;br /&gt;
	local wikiTable = &#039;{| class=&amp;quot;wikitable sortable&amp;quot;\n&#039;..&lt;br /&gt;
					  &#039;! rowspan=2 | Parameter\n&#039;..&lt;br /&gt;
					  &#039;! rowspan=2 | Label\n&#039;..&lt;br /&gt;
					  &#039;! rowspan=2; data-sort-type=number | Wikidata property\n&#039;..&lt;br /&gt;
					  &#039;! colspan=4 | Tracking categories and page counts\n&#039;..&lt;br /&gt;
					  &#039;|-\n&#039;..&lt;br /&gt;
					  &#039;! [[:Category:Wikipedia articles with authority control information|&#039;..       &#039;Articles]]\n&#039;..&lt;br /&gt;
					  &#039;! [[:Category:User pages with authority control information|&#039;..               &#039;User pages]]\n&#039;..&lt;br /&gt;
					  &#039;! [[:Category:Miscellaneous pages with authority control information|&#039;..      &#039;Misc. pages]]\n&#039;..&lt;br /&gt;
					  &#039;! [[:Category:Wikipedia articles with faulty authority control information|&#039;..&#039;Faulty IDs]]\n&#039;..&lt;br /&gt;
					  &#039;|-\n&#039;&lt;br /&gt;
	&lt;br /&gt;
	local lang = mw.getContentLanguage()&lt;br /&gt;
	for _, conf in pairs( p.conf ) do&lt;br /&gt;
		local param, link, pid = conf[1], conf[2], conf[3]&lt;br /&gt;
		local category = conf.category or param&lt;br /&gt;
		local args = { id = &#039;f&#039;, pid }&lt;br /&gt;
		local wpl = frame:expandTemplate{ title = &#039;Wikidata property link&#039;, args = args }&lt;br /&gt;
		--cats&lt;br /&gt;
		local articleCat = &#039;Wikipedia articles with &#039;..category..&#039; identifiers&#039;&lt;br /&gt;
		local userCat =    &#039;User pages with &#039;..category..&#039; identifiers&#039;&lt;br /&gt;
		local miscCat =    &#039;Miscellaneous pages with &#039;..category..&#039; identifiers&#039;&lt;br /&gt;
		local faultyCat =  &#039;Wikipedia articles with faulty &#039;..category..&#039; identifiers&#039;&lt;br /&gt;
		--counts&lt;br /&gt;
		local articleCount = lang:formatNum( mw.site.stats.pagesInCategory(articleCat, &#039;pages&#039;) )&lt;br /&gt;
		local userCount =    lang:formatNum( mw.site.stats.pagesInCategory(userCat, &#039;pages&#039;) )&lt;br /&gt;
		local miscCount =    lang:formatNum( mw.site.stats.pagesInCategory(miscCat, &#039;pages&#039;) )&lt;br /&gt;
		local faultyCount =  lang:formatNum( mw.site.stats.pagesInCategory(faultyCat, &#039;pages&#039;) )&lt;br /&gt;
		--concat&lt;br /&gt;
		wikiTable = wikiTable..&#039;\n&#039;..&lt;br /&gt;
					&#039;|-\n&#039;..&lt;br /&gt;
					&#039;||&#039;..param..&lt;br /&gt;
					&#039;||&#039;..link..&lt;br /&gt;
					&#039;||data-sort-value=&#039;..pid..&#039;|&#039;..wpl..&lt;br /&gt;
					&#039;||style=&amp;quot;text-align: right;&amp;quot;|[[:Category:&#039;..articleCat..&#039;|&#039;..articleCount..&#039;]]&#039;..&lt;br /&gt;
					&#039;||style=&amp;quot;text-align: right;&amp;quot;|[[:Category:&#039;..   userCat..&#039;|&#039;..   userCount..&#039;]]&#039;..&lt;br /&gt;
					&#039;||style=&amp;quot;text-align: right;&amp;quot;|[[:Category:&#039;..   miscCat..&#039;|&#039;..   miscCount..&#039;]]&#039;..&lt;br /&gt;
					&#039;||style=&amp;quot;text-align: right;&amp;quot;|[[:Category:&#039;.. faultyCat..&#039;|&#039;.. faultyCount..&#039;]]&#039;&lt;br /&gt;
	end&lt;br /&gt;
	return wikiTable..&#039;\n|}&#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[==========================================================================]]&lt;br /&gt;
--[[                              Configuration                               ]]&lt;br /&gt;
--[[==========================================================================]]&lt;br /&gt;
&lt;br /&gt;
-- If a specific &amp;quot;(identifier) redirect&amp;quot; exists for an identifier, please route through this particular redirect rather than linking directly to the target page. This reduces clutter in &amp;quot;What links here&amp;quot; and improves reverse lookup of articles where a manifestation of this particular identifier is used.&lt;br /&gt;
&lt;br /&gt;
-- Check that the Wikidata item has this property--&amp;gt;value before adding it&lt;br /&gt;
local reqs = {}&lt;br /&gt;
&lt;br /&gt;
-- Parameter format: { &#039;parameter name&#039;, &#039;label&#039;, propertyId # in Wikidata, formatting/validation function }&lt;br /&gt;
p.conf = {&lt;br /&gt;
	{ &#039;AAG&#039;, &#039;[[Auckland Art Gallery Toi o Tāmaki|AAG]]&#039;, 3372, p.aagLink },&lt;br /&gt;
	{ &#039;ACM-DL&#039;, &#039;[[Association for Computing Machinery#Portal and Digital Library|ACM DL]]&#039;, 864, p.acmLink },&lt;br /&gt;
	{ &#039;ADB&#039;, &#039;[[Australian Dictionary of Biography|ADB]]&#039;, 1907, p.adbLink },&lt;br /&gt;
	{ &#039;AGSA&#039;, &#039;[[Art Gallery of South Australia|AGSA]]&#039;, 6804, p.agsaLink },&lt;br /&gt;
	{ &#039;autores.uy&#039;, &#039;[[autores.uy]]&#039;, 2558, p.autoresuyLink },&lt;br /&gt;
	{ &#039;AWR&#039;, &#039;[[Australian Women\&#039;s Register|AWR]]&#039;, 4186, p.awrLink },&lt;br /&gt;
	{ &#039;BALaT&#039;, &#039;[[Royal Institute for Cultural Heritage#Online artworks pages|BALaT]]&#039;, 3293, p.balatLink },&lt;br /&gt;
	{ &#039;BIBSYS&#039;, &#039;[[Bibsys|BIBSYS]]&#039;, 1015, p.bibsysLink },&lt;br /&gt;
	{ &#039;Bildindex&#039;, &#039;[[Marburg Picture Index|Bildindex]]&#039;, 2092, p.bildLink },&lt;br /&gt;
	{ &#039;BNC&#039;, &#039;[[National Library of Chile|BNC]]&#039;, 1890, p.bncLink },&lt;br /&gt;
	{ &#039;BNE&#039;, &#039;[[Biblioteca Nacional de España|BNE]]&#039;, 950, p.bneLink },&lt;br /&gt;
	{ &#039;BNF&#039;, &#039;[[BNF (identifier)|BNF]]&#039;, 268, p.bnfLink },&lt;br /&gt;
	{ &#039;Botanist&#039;, &#039;[[Author citation (botany)|Botanist]]&#039;, 428, p.botanistLink },&lt;br /&gt;
	{ &#039;BPN&#039;, &#039;[[Biografisch Portaal|BPN]]&#039;, 651, p.bpnLink },&lt;br /&gt;
	{ &#039;CANTIC&#039;, &#039;[[Name and Title Authority File of Catalonia|CANTIC]]&#039;, 1273, p.canticLink },&lt;br /&gt;
	{ &#039;CINII&#039;, &#039;[[CiNii (identifier)|CiNii]]&#039;, 271, p.ciniiLink },&lt;br /&gt;
	{ &#039;DAAO&#039;, &#039;[[Dictionary of Australian Artists|DAAO]]&#039;, 1707, p.daaoLink },&lt;br /&gt;
	{ &#039;DBLP&#039;, &#039;[[DBLP]]&#039;, 2456, p.dblpLink },&lt;br /&gt;
	{ &#039;DSI&#039;, &#039;[[Stuttgart Database of Scientific Illustrators 1450–1950|DSI]]&#039;, 2349, p.dsiLink },&lt;br /&gt;
	{ &#039;FNZA&#039;, &#039;[[:d:Property:P6792|FNZA]]&#039;, 6792, p.fnzaLink },&lt;br /&gt;
	{ &#039;GND&#039;, &#039;[[GND (identifier)|GND]]&#039;, 227, p.gndLink },&lt;br /&gt;
	{ &#039;HDS&#039;, &#039;[[Historical Dictionary of Switzerland|HDS]]&#039;, 902, p.hdsLink },&lt;br /&gt;
	{ &#039;IAAF&#039;, &#039;[[World Athletics]]&#039;, 1146, p.iaafLink },&lt;br /&gt;
	{ &#039;ICIA&#039;, &#039;[[Information Center for Israeli Art|ICIA]]&#039;, 1736, p.iciaLink },&lt;br /&gt;
	{ &#039;ISNI&#039;, &#039;[[ISNI (identifier)|ISNI]]&#039;, 213, p.isniLink },&lt;br /&gt;
	{ &#039;Joconde&#039;, &#039;[[Joconde]]&#039; , 347, p.jocondeLink },&lt;br /&gt;
	{ &#039;KULTURNAV&#039;, &#039;[[KulturNav]]&#039;, 1248, p.kulturnavLink },&lt;br /&gt;
	{ &#039;LCCN&#039;, &#039;[[LCCN (identifier)|LCCN]]&#039;, 244, p.lccnLink },&lt;br /&gt;
	{ &#039;LIR&#039;, &#039;[[Historical Dictionary of Switzerland#Lexicon_Istoric_Retic|LIR]]&#039;, 886, p.lirLink },&lt;br /&gt;
	{ &#039;LNB&#039;, &#039;[[National Library of Latvia|LNB]]&#039;, 1368, p.lnbLink },&lt;br /&gt;
	{ &#039;Léonore&#039;, &#039;[[Base Léonore|Léonore]]&#039;, 640, p.leonoreLink },&lt;br /&gt;
	{ &#039;MBA&#039;, &#039;[[MusicBrainz]]&#039;, 434, p.mbaLink, category = &#039;MusicBrainz&#039; }, --special category name&lt;br /&gt;
	{ &#039;MBAREA&#039;, &#039;[[MusicBrainz]]&#039;, 982, p.mbareaLink, category = &#039;MusicBrainz area&#039; }, --special category name&lt;br /&gt;
	{ &#039;MBI&#039;, &#039;[[MusicBrainz]]&#039;, 1330, p.mbiLink, category = &#039;MusicBrainz instrument&#039; }, --special category name&lt;br /&gt;
	{ &#039;MBL&#039;, &#039;[[MusicBrainz]]&#039;, 966, p.mblLink, category = &#039;MusicBrainz label&#039; }, --special category name&lt;br /&gt;
	{ &#039;MBP&#039;, &#039;[[MusicBrainz]]&#039;, 1004, p.mbpLink, category = &#039;MusicBrainz place&#039; }, --special category name&lt;br /&gt;
	{ &#039;MBRG&#039;, &#039;[[MusicBrainz]] release group&#039;, 436, p.mbrgLink, category = &#039;MusicBrainz release group&#039; }, --special category name&lt;br /&gt;
	{ &#039;MBS&#039;, &#039;[[MusicBrainz]]&#039;, 1407, p.mbsLink, category = &#039;MusicBrainz series&#039; }, --special category name&lt;br /&gt;
	{ &#039;MBW&#039;, &#039;[[MusicBrainz]] work&#039;, 435, p.mbwLink, category = &#039;MusicBrainz work&#039; }, --special category name&lt;br /&gt;
	{ &#039;MGP&#039;, &#039;[[Mathematics Genealogy Project|MGP]]&#039;, 549, p.mgpLink },&lt;br /&gt;
	{ &#039;NARA&#039;, &#039;[[National Archives and Records Administration|NARA]]&#039;, 1225, p.naraLink },&lt;br /&gt;
	{ &#039;NCL&#039;, &#039;[[National Central Library|NCL]]&#039;, 1048, p.nclLink },&lt;br /&gt;
	{ &#039;NDL&#039;, &#039;[[National Diet Library|NDL]]&#039;, 349, p.ndlLink },&lt;br /&gt;
	{ &#039;NGV&#039;, &#039;[[National Gallery of Victoria|NGV]]&#039;, 2041, p.ngvLink },&lt;br /&gt;
	{ &#039;NKC&#039;, &#039;[[National Library of the Czech Republic|NKC]]&#039;, 691, p.nkcLink },&lt;br /&gt;
	{ &#039;NLA&#039;, &#039;[[National Library of Australia|NLA]]&#039;, 409, p.nlaLink },&lt;br /&gt;
	{ &#039;NLG&#039;, &#039;[[National Library of Greece|NLG]]&#039;, 3348, p.nlgLink },&lt;br /&gt;
	{ &#039;NLI&#039;, &#039;[[National Library of Israel|NLI]]&#039;, 949, p.nliLink },&lt;br /&gt;
	{ &#039;NLK&#039;, &#039;[[National Library of Korea|NLK]]&#039;, 5034, p.nlkLink },&lt;br /&gt;
	{ &#039;NLP&#039;, &#039;[[National Library of Poland|NLP]]&#039;, 1695, p.nlpLink },&lt;br /&gt;
	{ &#039;NLR&#039;, &#039;[[National Library of Romania|NLR]]&#039;, 1003, p.nlrLink },&lt;br /&gt;
	{ &#039;NSK&#039;, &#039;[[National and University Library in Zagreb|NSK]]&#039;, 1375, p.nskLink },&lt;br /&gt;
	{ &#039;NTA&#039;, &#039;[[Royal Library of the Netherlands|NTA]]&#039;, 1006, p.ntaLink },&lt;br /&gt;
	{ &#039;ORCID&#039;, &#039;[[ORCID (identifier)|ORCID]]&#039;, 496, p.orcidLink },&lt;br /&gt;
	{ &#039;PIC&#039;, &#039;[[:d:Q23892012|PIC]]&#039;, 2750, p.picLink },&lt;br /&gt;
	{ &#039;RID&#039;, &#039;[[ResearcherID]]&#039;, 1053, p.ridLink },&lt;br /&gt;
	{ &#039;RERO&#039;, &#039;[[RERO (Library Network of Western Switzerland)|RERO]]&#039;, 3065, p.reroLink },&lt;br /&gt;
	{ &#039;RKDartists&#039;, &#039;[[Netherlands Institute for Art History#Online artist pages|RKD]]&#039;, 650, p.rkdartistsLink },&lt;br /&gt;
	{ &#039;RKDID&#039;, &#039;[[Netherlands Institute for Art History#Online artworks pages|RKDimages ID]]&#039;, 350, p.rkdidLink },&lt;br /&gt;
	{ &#039;RSL&#039;, &#039;[[Russian State Library|RSL]]&#039;, 947, p.rslLink },&lt;br /&gt;
	{ &#039;SBN&#039;, &#039;[[ICCU (identifier)|ICCU]]&#039;, 396, p.sbnLink },&lt;br /&gt;
	{ &#039;SELIBR&#039;, &#039;[[SELIBR (identifier)|SELIBR]]&#039;, 906, p.selibrLink },&lt;br /&gt;
	{ &#039;SIKART&#039;, &#039;[[SIKART]]&#039;, 781, p.sikartLink },&lt;br /&gt;
	{ &#039;SNAC-ID&#039;, &#039;[[SNAC]]&#039;, 3430, p.snacLink },&lt;br /&gt;
	{ &#039;SUDOC&#039;, &#039;[[SUDOC (identifier)|SUDOC]]&#039;, 269, p.sudocLink },&lt;br /&gt;
	{ &#039;S2AuthorId&#039;, &#039;[[Semantic Scholar|S2AuthorId]]&#039;, 4012, p.s2authoridLink, category = &#039;Semantic Scholar author&#039; }, --special category name&lt;br /&gt;
	{ &#039;TA98&#039;, &#039;[[Terminologia Anatomica|TA98]]&#039;, 1323, p.ta98Link },&lt;br /&gt;
	{ &#039;TDVİA&#039;, &#039;[[İslâm Ansiklopedisi|TDVİA]]&#039;, 7314, p.tdviaLink },&lt;br /&gt;
	{ &#039;TE&#039;, &#039;[[Terminologia Embryologica|TE]]&#039;, 1693, p.teLink },&lt;br /&gt;
	{ &#039;TePapa&#039;, &#039;[[Museum of New Zealand Te Papa Tongarewa|TePapa]]&#039;, 3544, p.tepapaLink },&lt;br /&gt;
	{ &#039;TH&#039;, &#039;[[Terminologia Histologica|TH]]&#039;, 1694, p.thLink },&lt;br /&gt;
	{ &#039;TLS&#039;, &#039;[[Theaterlexikon der Schweiz|TLS]]&#039;, 1362, p.tlsLink },&lt;br /&gt;
	{ &#039;Trove&#039;, &#039;[[Trove]]&#039;, 1315, p.troveLink }, --formerly NLA-person&lt;br /&gt;
	{ &#039;ULAN&#039;, &#039;[[Union List of Artist Names|ULAN]]&#039;, 245, p.ulanLink },&lt;br /&gt;
	{ &#039;USCongress&#039;, &#039;[[Biographical Directory of the United States Congress|US Congress]]&#039;, 1157, p.uscongressLink },&lt;br /&gt;
	{ &#039;VIAF&#039;, &#039;[[VIAF (identifier)|VIAF]]&#039;, 214, p.viafLink },&lt;br /&gt;
	{ &#039;WORLDCATID&#039;, &#039;[[WorldCat|WorldCat Identities]]&#039;, 7859, nil },&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- Legitimate aliases to p.conf, for convenience&lt;br /&gt;
-- Format: { &#039;alias&#039;, &#039;parameter name in p.conf&#039; }&lt;br /&gt;
p.aliases = {&lt;br /&gt;
	{ &#039;RLS&#039;, &#039;RSL&#039; },&lt;br /&gt;
	{ &#039;MusicBrainz&#039;, &#039;MBA&#039; },&lt;br /&gt;
	{ &#039;MusicBrainz artist&#039;, &#039;MBA&#039; },&lt;br /&gt;
	{ &#039;MusicBrainz label&#039;, &#039;MBL&#039; },&lt;br /&gt;
	{ &#039;MusicBrainz release group&#039;, &#039;MBRG&#039; },&lt;br /&gt;
	{ &#039;MusicBrainz work&#039;, &#039;MBW&#039; },&lt;br /&gt;
	{ &#039;Leonore&#039;, &#039;Léonore&#039; },&lt;br /&gt;
	{ &#039;TDVIA&#039;, &#039;TDVİA&#039; },&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- Deprecated aliases to p.conf; tracked in [[Category:Wikipedia articles with deprecated authority control identifiers]]&lt;br /&gt;
-- Format: { &#039;deprecated parameter name&#039;, &#039;replacement parameter name in p.conf&#039; }&lt;br /&gt;
p.deprecated = {&lt;br /&gt;
	{ &#039;GKD&#039;, &#039;GND&#039; },&lt;br /&gt;
	{ &#039;PND&#039;, &#039;GND&#039; },&lt;br /&gt;
	{ &#039;SWD&#039;, &#039;GND&#039; },&lt;br /&gt;
	{ &#039;NARA-organization&#039;, &#039;NARA&#039; },&lt;br /&gt;
	{ &#039;NARA-person&#039;, &#039;NARA&#039; },&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
--[[==========================================================================]]&lt;br /&gt;
--[[                                   Main                                   ]]&lt;br /&gt;
--[[==========================================================================]]&lt;br /&gt;
&lt;br /&gt;
function p.authorityControl( frame )&lt;br /&gt;
	local resolveEntity = require( &amp;quot;Module:ResolveEntityId&amp;quot; )&lt;br /&gt;
	local parentArgs = frame:getParent().args&lt;br /&gt;
	local elements = {} --create/insert rows later&lt;br /&gt;
	local worldcatCat = &#039;&#039;&lt;br /&gt;
	local suppressedIdCat = &#039;&#039;&lt;br /&gt;
	local deprecatedIdCat = &#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
	--Redirect aliases to proper parameter names&lt;br /&gt;
	for _, a in pairs( p.aliases ) do&lt;br /&gt;
		local alias, param = a[1], a[2]&lt;br /&gt;
		if (parentArgs[param] == nil or parentArgs[param] == &#039;&#039;) and parentArgs[alias] then&lt;br /&gt;
			parentArgs[param] = parentArgs[alias]&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	--Redirect deprecated parameters to proper parameter names, and assign tracking cat&lt;br /&gt;
	for _, d in pairs( p.deprecated ) do&lt;br /&gt;
		local dep, param = d[1], d[2]&lt;br /&gt;
		if (parentArgs[param] == nil or parentArgs[param] == &#039;&#039;) and parentArgs[dep] then&lt;br /&gt;
			parentArgs[param] = parentArgs[dep]&lt;br /&gt;
			if namespace == 0 then&lt;br /&gt;
				deprecatedIdCat = &#039;[[Category:Wikipedia articles with deprecated authority control identifiers|&#039;..dep..&#039;]]&#039;&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	--Use QID= parameter for testing/example purposes only&lt;br /&gt;
	local itemId = nil&lt;br /&gt;
	if namespace ~= 0 then&lt;br /&gt;
		local qid = parentArgs[&#039;qid&#039;] or parentArgs[&#039;QID&#039;]&lt;br /&gt;
		if qid then&lt;br /&gt;
			itemId = &#039;Q&#039;..mw.ustring.gsub(qid, &#039;^[Qq]&#039;, &#039;&#039;)&lt;br /&gt;
			itemId = resolveEntity._id(itemId) --nil if unresolvable&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		itemId = mw.wikibase.getEntityIdForCurrentPage()&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	--Wikidata fallback if requested&lt;br /&gt;
	if itemId then&lt;br /&gt;
		for _, params in ipairs( p.conf ) do&lt;br /&gt;
			if params[3] &amp;gt; 0 then&lt;br /&gt;
				local val = parentArgs[params[1]]&lt;br /&gt;
				if val == nil or val == &#039;&#039; then&lt;br /&gt;
					local canUseWikidata = nil&lt;br /&gt;
					if reqs[params[1]] then&lt;br /&gt;
						canUseWikidata = p.matchesWikidataRequirements( itemId, reqs[params[1]] )&lt;br /&gt;
					else&lt;br /&gt;
						canUseWikidata = true&lt;br /&gt;
					end&lt;br /&gt;
					if canUseWikidata then&lt;br /&gt;
						local wikidataIds = p.getIdsFromWikidata( itemId, &#039;P&#039;..params[3] )&lt;br /&gt;
						if wikidataIds[1] then&lt;br /&gt;
							if val == &#039;&#039; and (namespace == 0 or testcases) then&lt;br /&gt;
								suppressedIdCat = &#039;[[Category:Wikipedia articles with suppressed authority control identifiers|&#039;..params[1]..&#039;]]&#039;&lt;br /&gt;
							else&lt;br /&gt;
								parentArgs[params[1]] = wikidataIds[1]&lt;br /&gt;
	end	end	end	end	end	end	end&lt;br /&gt;
	&lt;br /&gt;
	--Configured rows&lt;br /&gt;
	local rct = 0&lt;br /&gt;
	for _, params in ipairs( p.conf ) do&lt;br /&gt;
		local val = parentArgs[params[1]]&lt;br /&gt;
		if val and val ~= &#039;&#039; and type(params[4]) == &#039;function&#039; then&lt;br /&gt;
			table.insert( elements, p.createRow( params[1], params[2]..&#039;:&#039;, val, params[4]( val ), true, params.category ) )&lt;br /&gt;
			rct = rct + 1&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	--WorldCat&lt;br /&gt;
	local worldcatId = parentArgs[&#039;WORLDCATID&#039;]&lt;br /&gt;
	if worldcatId and worldcatId ~= &#039;&#039; then --if WORLDCATID present &amp;amp; unsuppressed&lt;br /&gt;
		table.insert( elements, p.createRow( &#039;WORLDCATID&#039;, &#039;&#039;, worldcatId, &#039;[[WorldCat Identities]]: [https://www.worldcat.org/identities/&#039;..mw.uri.encode(worldcatId, &#039;PATH&#039;)..&#039; &#039;..worldcatId..&#039;]&#039;, false ) ) --Validation?&lt;br /&gt;
		worldcatCat = &#039;[[Category:Wikipedia articles with WorldCat identifiers]]&#039;&lt;br /&gt;
	elseif worldcatId == nil then --if WORLDCATID absent but unsuppressed&lt;br /&gt;
		local viafId = parentArgs[&#039;VIAF&#039;]&lt;br /&gt;
		local lccnId = parentArgs[&#039;LCCN&#039;]&lt;br /&gt;
		if viafId and viafId ~= &#039;&#039; and p.viafLink( viafId ) then --VIAF must be present, unsuppressed, &amp;amp; validated&lt;br /&gt;
			table.insert( elements, p.createRow( &#039;VIAF&#039;, &#039;&#039;, viafId, &#039;[[WorldCat Identities]] (via VIAF): [https://www.worldcat.org/identities/containsVIAFID/&#039;..viafId..&#039; &#039;..viafId..&#039;]&#039;, false ) )&lt;br /&gt;
			if namespace == 0 then &lt;br /&gt;
				worldcatCat = &#039;[[Category:Wikipedia articles with WorldCat-VIAF identifiers]]&#039;&lt;br /&gt;
			end&lt;br /&gt;
		elseif lccnId and lccnId ~= &#039;&#039; and p.lccnLink( lccnId ) then --LCCN must be present, unsuppressed, &amp;amp; validated&lt;br /&gt;
			local lccnParts = p.splitLccn( lccnId )&lt;br /&gt;
			if lccnParts and lccnParts[1] ~= &#039;sh&#039; then&lt;br /&gt;
				local lccnIdFmtd = lccnParts[1]..lccnParts[2]..&#039;-&#039;..lccnParts[3]&lt;br /&gt;
				table.insert( elements, p.createRow( &#039;LCCN&#039;, &#039;&#039;, lccnId, &#039;[[WorldCat Identities]] (via LCCN): [https://www.worldcat.org/identities/lccn-&#039;..lccnIdFmtd..&#039; &#039;..lccnIdFmtd..&#039;]&#039;, false ) )&lt;br /&gt;
				if namespace == 0 then&lt;br /&gt;
					worldcatCat = &#039;[[Category:Wikipedia articles with WorldCat-LCCN identifiers]]&#039;&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	elseif worldcatId == &#039;&#039; then --if WORLDCATID suppressed&lt;br /&gt;
		suppressedIdCat = &#039;[[Category:Wikipedia articles with suppressed authority control identifiers|WORLDCATID]]&#039;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local Navbox = require(&#039;Module:Navbox&#039;)&lt;br /&gt;
	local elementsCat = &#039;&#039;&lt;br /&gt;
	if rct &amp;gt;= 25 then&lt;br /&gt;
		local eCat = &#039;AC with &#039;..rct..&#039; elements&#039;&lt;br /&gt;
		elementsCat  = &#039;[[Category:&#039;..eCat..&#039;]]&#039;..p.redCatLink(eCat)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local outString = &#039;&#039;&lt;br /&gt;
	if #elements &amp;gt; 0 then&lt;br /&gt;
		local args = {}&lt;br /&gt;
		if testcases and itemId then args = { qid = itemId } end --expensive&lt;br /&gt;
		local pencil = frame:expandTemplate{ title = &#039;EditAtWikidata&#039;, args = args}&lt;br /&gt;
		outString = Navbox._navbox( {&lt;br /&gt;
			name  = &#039;Authority control&#039;,&lt;br /&gt;
			navboxclass = &#039;authority-control&#039;,&lt;br /&gt;
			bodyclass = &#039;hlist&#039;,&lt;br /&gt;
			group1 = &#039;[[Help:Authority control|Authority control]]&#039;..pencil,&lt;br /&gt;
			list1 = table.concat( elements )&lt;br /&gt;
			} )&lt;br /&gt;
		local auxCats = worldcatCat .. elementsCat .. suppressedIdCat .. deprecatedIdCat&lt;br /&gt;
		if testcases then&lt;br /&gt;
			auxCats = mw.ustring.gsub(auxCats, &#039;(%[%[)(Category)&#039;, &#039;%1:%2&#039;) --for easier checking&lt;br /&gt;
		end&lt;br /&gt;
		outString = outString .. auxCats&lt;br /&gt;
		if namespace ~= 0 then&lt;br /&gt;
			outString = mw.ustring.gsub(outString, &#039;(%[%[)(Category:Wikipedia articles)&#039;, &#039;%1:%2&#039;) --by definition&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return outString&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Module:Arguments&amp;diff=191</id>
		<title>Module:Arguments</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Module:Arguments&amp;diff=191"/>
		<updated>2020-08-22T20:23:46Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module provides easy processing of arguments passed to Scribunto from&lt;br /&gt;
-- #invoke. It is intended for use by other Lua modules, and should not be&lt;br /&gt;
-- called from #invoke directly.&lt;br /&gt;
&lt;br /&gt;
local libraryUtil = require(&#039;libraryUtil&#039;)&lt;br /&gt;
local checkType = libraryUtil.checkType&lt;br /&gt;
&lt;br /&gt;
local arguments = {}&lt;br /&gt;
&lt;br /&gt;
-- Generate four different tidyVal functions, so that we don&#039;t have to check the&lt;br /&gt;
-- options every time we call it.&lt;br /&gt;
&lt;br /&gt;
local function tidyValDefault(key, val)&lt;br /&gt;
	if type(val) == &#039;string&#039; then&lt;br /&gt;
		val = val:match(&#039;^%s*(.-)%s*$&#039;)&lt;br /&gt;
		if val == &#039;&#039; then&lt;br /&gt;
			return nil&lt;br /&gt;
		else&lt;br /&gt;
			return val&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		return val&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function tidyValTrimOnly(key, val)&lt;br /&gt;
	if type(val) == &#039;string&#039; then&lt;br /&gt;
		return val:match(&#039;^%s*(.-)%s*$&#039;)&lt;br /&gt;
	else&lt;br /&gt;
		return val&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function tidyValRemoveBlanksOnly(key, val)&lt;br /&gt;
	if type(val) == &#039;string&#039; then&lt;br /&gt;
		if val:find(&#039;%S&#039;) then&lt;br /&gt;
			return val&lt;br /&gt;
		else&lt;br /&gt;
			return nil&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		return val&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function tidyValNoChange(key, val)&lt;br /&gt;
	return val&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function matchesTitle(given, title)&lt;br /&gt;
	local tp = type( given )&lt;br /&gt;
	return (tp == &#039;string&#039; or tp == &#039;number&#039;) and mw.title.new( given ).prefixedText == title&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local translate_mt = { __index = function(t, k) return k end }&lt;br /&gt;
&lt;br /&gt;
function arguments.getArgs(frame, options)&lt;br /&gt;
	checkType(&#039;getArgs&#039;, 1, frame, &#039;table&#039;, true)&lt;br /&gt;
	checkType(&#039;getArgs&#039;, 2, options, &#039;table&#039;, true)&lt;br /&gt;
	frame = frame or {}&lt;br /&gt;
	options = options or {}&lt;br /&gt;
&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Set up argument translation.&lt;br /&gt;
	--]]&lt;br /&gt;
	options.translate = options.translate or {}&lt;br /&gt;
	if getmetatable(options.translate) == nil then&lt;br /&gt;
		setmetatable(options.translate, translate_mt)&lt;br /&gt;
	end&lt;br /&gt;
	if options.backtranslate == nil then&lt;br /&gt;
		options.backtranslate = {}&lt;br /&gt;
		for k,v in pairs(options.translate) do&lt;br /&gt;
			options.backtranslate[v] = k&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if options.backtranslate and getmetatable(options.backtranslate) == nil then&lt;br /&gt;
		setmetatable(options.backtranslate, {&lt;br /&gt;
			__index = function(t, k)&lt;br /&gt;
				if options.translate[k] ~= k then&lt;br /&gt;
					return nil&lt;br /&gt;
				else&lt;br /&gt;
					return k&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		})&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Get the argument tables. If we were passed a valid frame object, get the&lt;br /&gt;
	-- frame arguments (fargs) and the parent frame arguments (pargs), depending&lt;br /&gt;
	-- on the options set and on the parent frame&#039;s availability. If we weren&#039;t&lt;br /&gt;
	-- passed a valid frame object, we are being called from another Lua module&lt;br /&gt;
	-- or from the debug console, so assume that we were passed a table of args&lt;br /&gt;
	-- directly, and assign it to a new variable (luaArgs).&lt;br /&gt;
	--]]&lt;br /&gt;
	local fargs, pargs, luaArgs&lt;br /&gt;
	if type(frame.args) == &#039;table&#039; and type(frame.getParent) == &#039;function&#039; then&lt;br /&gt;
		if options.wrappers then&lt;br /&gt;
			--[[&lt;br /&gt;
			-- The wrappers option makes Module:Arguments look up arguments in&lt;br /&gt;
			-- either the frame argument table or the parent argument table, but&lt;br /&gt;
			-- not both. This means that users can use either the #invoke syntax&lt;br /&gt;
			-- or a wrapper template without the loss of performance associated&lt;br /&gt;
			-- with looking arguments up in both the frame and the parent frame.&lt;br /&gt;
			-- Module:Arguments will look up arguments in the parent frame&lt;br /&gt;
			-- if it finds the parent frame&#039;s title in options.wrapper;&lt;br /&gt;
			-- otherwise it will look up arguments in the frame object passed&lt;br /&gt;
			-- to getArgs.&lt;br /&gt;
			--]]&lt;br /&gt;
			local parent = frame:getParent()&lt;br /&gt;
			if not parent then&lt;br /&gt;
				fargs = frame.args&lt;br /&gt;
			else&lt;br /&gt;
				local title = parent:getTitle():gsub(&#039;/sandbox$&#039;, &#039;&#039;)&lt;br /&gt;
				local found = false&lt;br /&gt;
				if matchesTitle(options.wrappers, title) then&lt;br /&gt;
					found = true&lt;br /&gt;
				elseif type(options.wrappers) == &#039;table&#039; then&lt;br /&gt;
					for _,v in pairs(options.wrappers) do&lt;br /&gt;
						if matchesTitle(v, title) then&lt;br /&gt;
							found = true&lt;br /&gt;
							break&lt;br /&gt;
						end&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
&lt;br /&gt;
				-- We test for false specifically here so that nil (the default) acts like true.&lt;br /&gt;
				if found or options.frameOnly == false then&lt;br /&gt;
					pargs = parent.args&lt;br /&gt;
				end&lt;br /&gt;
				if not found or options.parentOnly == false then&lt;br /&gt;
					fargs = frame.args&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			-- options.wrapper isn&#039;t set, so check the other options.&lt;br /&gt;
			if not options.parentOnly then&lt;br /&gt;
				fargs = frame.args&lt;br /&gt;
			end&lt;br /&gt;
			if not options.frameOnly then&lt;br /&gt;
				local parent = frame:getParent()&lt;br /&gt;
				pargs = parent and parent.args or nil&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		if options.parentFirst then&lt;br /&gt;
			fargs, pargs = pargs, fargs&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		luaArgs = frame&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Set the order of precedence of the argument tables. If the variables are&lt;br /&gt;
	-- nil, nothing will be added to the table, which is how we avoid clashes&lt;br /&gt;
	-- between the frame/parent args and the Lua args.&lt;br /&gt;
	local argTables = {fargs}&lt;br /&gt;
	argTables[#argTables + 1] = pargs&lt;br /&gt;
	argTables[#argTables + 1] = luaArgs&lt;br /&gt;
&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Generate the tidyVal function. If it has been specified by the user, we&lt;br /&gt;
	-- use that; if not, we choose one of four functions depending on the&lt;br /&gt;
	-- options chosen. This is so that we don&#039;t have to call the options table&lt;br /&gt;
	-- every time the function is called.&lt;br /&gt;
	--]]&lt;br /&gt;
	local tidyVal = options.valueFunc&lt;br /&gt;
	if tidyVal then&lt;br /&gt;
		if type(tidyVal) ~= &#039;function&#039; then&lt;br /&gt;
			error(&lt;br /&gt;
				&amp;quot;bad value assigned to option &#039;valueFunc&#039;&amp;quot;&lt;br /&gt;
					.. &#039;(function expected, got &#039;&lt;br /&gt;
					.. type(tidyVal)&lt;br /&gt;
					.. &#039;)&#039;,&lt;br /&gt;
				2&lt;br /&gt;
			)&lt;br /&gt;
		end&lt;br /&gt;
	elseif options.trim ~= false then&lt;br /&gt;
		if options.removeBlanks ~= false then&lt;br /&gt;
			tidyVal = tidyValDefault&lt;br /&gt;
		else&lt;br /&gt;
			tidyVal = tidyValTrimOnly&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		if options.removeBlanks ~= false then&lt;br /&gt;
			tidyVal = tidyValRemoveBlanksOnly&lt;br /&gt;
		else&lt;br /&gt;
			tidyVal = tidyValNoChange&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Set up the args, metaArgs and nilArgs tables. args will be the one&lt;br /&gt;
	-- accessed from functions, and metaArgs will hold the actual arguments. Nil&lt;br /&gt;
	-- arguments are memoized in nilArgs, and the metatable connects all of them&lt;br /&gt;
	-- together.&lt;br /&gt;
	--]]&lt;br /&gt;
	local args, metaArgs, nilArgs, metatable = {}, {}, {}, {}&lt;br /&gt;
	setmetatable(args, metatable)&lt;br /&gt;
&lt;br /&gt;
	local function mergeArgs(tables)&lt;br /&gt;
		--[[&lt;br /&gt;
		-- Accepts multiple tables as input and merges their keys and values&lt;br /&gt;
		-- into one table. If a value is already present it is not overwritten;&lt;br /&gt;
		-- tables listed earlier have precedence. We are also memoizing nil&lt;br /&gt;
		-- values, which can be overwritten if they are &#039;s&#039; (soft).&lt;br /&gt;
		--]]&lt;br /&gt;
		for _, t in ipairs(tables) do&lt;br /&gt;
			for key, val in pairs(t) do&lt;br /&gt;
				if metaArgs[key] == nil and nilArgs[key] ~= &#039;h&#039; then&lt;br /&gt;
					local tidiedVal = tidyVal(key, val)&lt;br /&gt;
					if tidiedVal == nil then&lt;br /&gt;
						nilArgs[key] = &#039;s&#039;&lt;br /&gt;
					else&lt;br /&gt;
						metaArgs[key] = tidiedVal&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;
	-- Define metatable behaviour. Arguments are memoized in the metaArgs table,&lt;br /&gt;
	-- and are only fetched from the argument tables once. Fetching arguments&lt;br /&gt;
	-- from the argument tables is the most resource-intensive step in this&lt;br /&gt;
	-- module, so we try and avoid it where possible. For this reason, nil&lt;br /&gt;
	-- arguments are also memoized, in the nilArgs table. Also, we keep a record&lt;br /&gt;
	-- in the metatable of when pairs and ipairs have been called, so we do not&lt;br /&gt;
	-- run pairs and ipairs on the argument tables more than once. We also do&lt;br /&gt;
	-- not run ipairs on fargs and pargs if pairs has already been run, as all&lt;br /&gt;
	-- the arguments will already have been copied over.&lt;br /&gt;
	--]]&lt;br /&gt;
&lt;br /&gt;
	metatable.__index = function (t, key)&lt;br /&gt;
		--[[&lt;br /&gt;
		-- Fetches an argument when the args table is indexed. First we check&lt;br /&gt;
		-- to see if the value is memoized, and if not we try and fetch it from&lt;br /&gt;
		-- the argument tables. When we check memoization, we need to check&lt;br /&gt;
		-- metaArgs before nilArgs, as both can be non-nil at the same time.&lt;br /&gt;
		-- If the argument is not present in metaArgs, we also check whether&lt;br /&gt;
		-- pairs has been run yet. If pairs has already been run, we return nil.&lt;br /&gt;
		-- This is because all the arguments will have already been copied into&lt;br /&gt;
		-- metaArgs by the mergeArgs function, meaning that any other arguments&lt;br /&gt;
		-- must be nil.&lt;br /&gt;
		--]]&lt;br /&gt;
		if type(key) == &#039;string&#039; then&lt;br /&gt;
			key = options.translate[key]&lt;br /&gt;
		end&lt;br /&gt;
		local val = metaArgs[key]&lt;br /&gt;
		if val ~= nil then&lt;br /&gt;
			return val&lt;br /&gt;
		elseif metatable.donePairs or nilArgs[key] then&lt;br /&gt;
			return nil&lt;br /&gt;
		end&lt;br /&gt;
		for _, argTable in ipairs(argTables) do&lt;br /&gt;
			local argTableVal = tidyVal(key, argTable[key])&lt;br /&gt;
			if argTableVal ~= nil then&lt;br /&gt;
				metaArgs[key] = argTableVal&lt;br /&gt;
				return argTableVal&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		nilArgs[key] = &#039;h&#039;&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	metatable.__newindex = function (t, key, val)&lt;br /&gt;
		-- This function is called when a module tries to add a new value to the&lt;br /&gt;
		-- args table, or tries to change an existing value.&lt;br /&gt;
		if type(key) == &#039;string&#039; then&lt;br /&gt;
			key = options.translate[key]&lt;br /&gt;
		end&lt;br /&gt;
		if options.readOnly then&lt;br /&gt;
			error(&lt;br /&gt;
				&#039;could not write to argument table key &amp;quot;&#039;&lt;br /&gt;
					.. tostring(key)&lt;br /&gt;
					.. &#039;&amp;quot;; the table is read-only&#039;,&lt;br /&gt;
				2&lt;br /&gt;
			)&lt;br /&gt;
		elseif options.noOverwrite and args[key] ~= nil then&lt;br /&gt;
			error(&lt;br /&gt;
				&#039;could not write to argument table key &amp;quot;&#039;&lt;br /&gt;
					.. tostring(key)&lt;br /&gt;
					.. &#039;&amp;quot;; overwriting existing arguments is not permitted&#039;,&lt;br /&gt;
				2&lt;br /&gt;
			)&lt;br /&gt;
		elseif val == nil then&lt;br /&gt;
			--[[&lt;br /&gt;
			-- If the argument is to be overwritten with nil, we need to erase&lt;br /&gt;
			-- the value in metaArgs, so that __index, __pairs and __ipairs do&lt;br /&gt;
			-- not use a previous existing value, if present; and we also need&lt;br /&gt;
			-- to memoize the nil in nilArgs, so that the value isn&#039;t looked&lt;br /&gt;
			-- up in the argument tables if it is accessed again.&lt;br /&gt;
			--]]&lt;br /&gt;
			metaArgs[key] = nil&lt;br /&gt;
			nilArgs[key] = &#039;h&#039;&lt;br /&gt;
		else&lt;br /&gt;
			metaArgs[key] = val&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local function translatenext(invariant)&lt;br /&gt;
		local k, v = next(invariant.t, invariant.k)&lt;br /&gt;
		invariant.k = k&lt;br /&gt;
		if k == nil then&lt;br /&gt;
			return nil&lt;br /&gt;
		elseif type(k) ~= &#039;string&#039; or not options.backtranslate then&lt;br /&gt;
			return k, v&lt;br /&gt;
		else&lt;br /&gt;
			local backtranslate = options.backtranslate[k]&lt;br /&gt;
			if backtranslate == nil then&lt;br /&gt;
				-- Skip this one. This is a tail call, so this won&#039;t cause stack overflow&lt;br /&gt;
				return translatenext(invariant)&lt;br /&gt;
			else&lt;br /&gt;
				return backtranslate, v&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	metatable.__pairs = function ()&lt;br /&gt;
		-- Called when pairs is run on the args table.&lt;br /&gt;
		if not metatable.donePairs then&lt;br /&gt;
			mergeArgs(argTables)&lt;br /&gt;
			metatable.donePairs = true&lt;br /&gt;
		end&lt;br /&gt;
		return translatenext, { t = metaArgs }&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local function inext(t, i)&lt;br /&gt;
		-- This uses our __index metamethod&lt;br /&gt;
		local v = t[i + 1]&lt;br /&gt;
		if v ~= nil then&lt;br /&gt;
			return i + 1, v&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	metatable.__ipairs = function (t)&lt;br /&gt;
		-- Called when ipairs is run on the args table.&lt;br /&gt;
		return inext, t, 0&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return args&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return arguments&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Module:Anchor&amp;diff=189</id>
		<title>Module:Anchor</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Module:Anchor&amp;diff=189"/>
		<updated>2020-08-22T20:23:46Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module implements {{anchor}}.&lt;br /&gt;
&lt;br /&gt;
local getArgs = require(&#039;Module:Arguments&#039;).getArgs&lt;br /&gt;
local tableTools = require(&#039;Module:TableTools&#039;)&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
function p.main(frame)&lt;br /&gt;
	-- Get the positional arguments from #invoke, remove any nil values,&lt;br /&gt;
	-- and pass them to p._main.&lt;br /&gt;
	local args = getArgs(frame)&lt;br /&gt;
	local argArray = tableTools.compressSparseArray(args)&lt;br /&gt;
	return p._main(unpack(argArray))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._main(...)&lt;br /&gt;
	-- Generate the list of anchors.&lt;br /&gt;
	local anchors = {...}&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	for _, anchor in ipairs(anchors) do&lt;br /&gt;
		ret[#ret + 1] = &#039;&amp;lt;span id=&amp;quot;&#039; .. anchor .. &#039;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
	end&lt;br /&gt;
	return table.concat(ret)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:Redirect_template&amp;diff=187</id>
		<title>Template:Redirect template</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:Redirect_template&amp;diff=187"/>
		<updated>2020-08-22T18:04:15Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#invoke:Redirect template|main}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{Documentation}}&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:Redirect_category_shell&amp;diff=185</id>
		<title>Template:Redirect category shell</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:Redirect_category_shell&amp;diff=185"/>
		<updated>2020-08-22T18:04:15Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Mbox&lt;br /&gt;
| name  = Redirect category shell&lt;br /&gt;
| type  = move &lt;br /&gt;
| image = none&lt;br /&gt;
| style = margin-top: 1.1em; border: solid 1px darkblue; border-left-width: 0.5em;&lt;br /&gt;
| textstyle = padding-top: 0.9em; padding-bottom: 0.9em;&lt;br /&gt;
| text  = [[File:Symbol redirect arrow with gradient.svg|25px|link=]] &#039;&#039;&#039;This page is a [[Wikipedia:Redirect|redirect]]:&#039;&#039;&#039;{{#if:{{{h|}}}&lt;br /&gt;
 |:: &#039;&#039;{{{h}}}&#039;&#039;&lt;br /&gt;
 }}&amp;lt;!--&lt;br /&gt;
  Automatically detect protected redirects:&lt;br /&gt;
--&amp;gt;&amp;lt;includeonly&amp;gt;{{#switch: {{PROTECTIONLEVEL:move}}&lt;br /&gt;
   |sysop|templateeditor|extendedconfirmed={{pp-move|small=yes}}&lt;br /&gt;
 }}{{#switch: {{PROTECTIONLEVEL:edit}}&lt;br /&gt;
   |sysop={{pp-protected|small=yes}}{{R protected|embed=yes}}&lt;br /&gt;
   |templateeditor={{pp-protected|small=yes}}{{R template protected|embed=yes}}&lt;br /&gt;
   |extendedconfirmed={{pp-protected|small=yes}}{{R extended-protected|embed=yes}}&lt;br /&gt;
   |autoconfirmed={{pp-protected|small=yes}}{{R semi-protected|embed=yes}}&lt;br /&gt;
   | &amp;lt;!--Not protected, or only semi-move-protected--&amp;gt;&lt;br /&gt;
 }}&amp;lt;/includeonly&amp;gt;{{#if: {{{1|}}}||&amp;lt;includeonly&amp;gt;&lt;br /&gt;
* {{red|&#039;&#039;&#039;Important – Please Read! {{maroon|This template should {{em|not}} be applied without parameters by bot nor by any automated or semi-automated process. It should {{em|not}} be used without parameters {{em|unless you want to learn how to categorize redirects}}. For editors who want to learn how to categorize redirects, this template is a {{em|learning tool}}. {{em|Only}} those editors who intend to return to the redirect to learn which rcats to use should apply this template without parameters, or with an empty first parameter!}}&#039;&#039;&#039;}}&amp;lt;/includeonly&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Manifold sort&#039;&#039;&#039;:  If help is needed to determine appropriate categories, then this redirect populates &#039;&#039;&#039;{{Cat|Miscellaneous redirects}}&#039;&#039;&#039;.  Monitors of that category will check this redirect and add or remove [[WP:RCAT|rcat]]s as needed.{{#ifeq: {{lc:{{{nocat|false}}}}} | false |{{{category|&amp;lt;includeonly&amp;gt;[[Category:Miscellaneous redirects]]&amp;lt;/includeonly&amp;gt;}}}}}&lt;br /&gt;
}}&lt;br /&gt;
{{#if: {{{2|}}}|{{{2}}}|{{{1|}}}}}&lt;br /&gt;
&#039;&#039;&amp;lt;small&amp;gt;When appropriate, [[Wikipedia:Protection policy|protection levels]] are automatically sensed, described and categorized.&amp;lt;/small&amp;gt;&#039;&#039;&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>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:R_from_move/except&amp;diff=183</id>
		<title>Template:R from move/except</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:R_from_move/except&amp;diff=183"/>
		<updated>2020-08-22T18:04:15Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;This is the exception page for {{tl|R from move}}.  This page makes exceptions that include certain pages that should not inhabit either {{cat|Unsynchronized talk page redirects}} or {{cat|Redirects from moves}}.  If necessary, new exceptions may be added with no need to edit the main template, {{tl|R from move}}.&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;{{#switch: {{FULLPAGENAME}}&lt;br /&gt;
|MediaWiki:Move-redirect-text=&lt;br /&gt;
|Template:R from move/except=&lt;br /&gt;
|#default=[[Category:Redirects from moves]]&lt;br /&gt;
}}{{#ifeq: {{NAMESPACENUMBER}}|1|&lt;br /&gt;
    {{#ifeq: {{#invoke:redirect|isRedirect|{{FULLPAGENAME}}}}|yes|&lt;br /&gt;
      {{#ifeq: {{#invoke:redirect|isRedirect|{{SUBJECTPAGENAME}}}}|yes|&lt;br /&gt;
        {{#ifeq: {{PAGENAME:{{#invoke:redirect|main|{{TALKPAGENAME}}}}}}|{{PAGENAME:{{#invoke:redirect|main|{{SUBJECTPAGENAME}}}}}}||&lt;br /&gt;
          {{#ifeq: {{FULLPAGENAME}}|{{SUBJECTPAGENAME}}||&lt;br /&gt;
            {{#ifeq: {{Str left|{{PAGENAME}}|16}}|List of ships of||[[Category:Unsynchronized talk page redirects]]&lt;br /&gt;
            }}&lt;br /&gt;
          }}&lt;br /&gt;
        }}&lt;br /&gt;
      |{{#ifexist:{{SUBJECTPAGENAME}}|&lt;br /&gt;
        {{#ifeq: {{SUBJECTPAGENAME}}|{{Target of|{{SUBJECTPAGENAME:{{Target of|{{FULLPAGENAME}}}}}}}}|[[Category:Articles with unsynchronized talk page redirects]]|[[Category:Articles with talk page redirects]]}}&lt;br /&gt;
        }}&lt;br /&gt;
      }}&lt;br /&gt;
    |{{error|Page is not a redirect, misplaced [[Template:R from move]]}}&lt;br /&gt;
    }}&lt;br /&gt;
  }}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{Documentation|Template:R from move/doc}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:R_from_move&amp;diff=181</id>
		<title>Template:R from move</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:R_from_move&amp;diff=181"/>
		<updated>2020-08-22T18:04:15Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{hatnote|This rcat template is automatically added to all new redirects that result from page moves; it must be added manually to older redirects when appropriate.}}{{This is a redirect/rcat}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;{{Redirect template&lt;br /&gt;
  |name=From a page move&lt;br /&gt;
  |from=a page that has been moved (renamed)&lt;br /&gt;
  |info=This page was kept as a redirect to avoid breaking links, both internal and external, that may have been made to the old page name.&lt;br /&gt;
  |all category=Redirects from moves&lt;br /&gt;
}}&amp;lt;includeonly&amp;gt;{{R from move/except}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
&amp;lt;!-- Place categories on /doc subpage; interwikis go to Wikidata. --&amp;gt;&lt;br /&gt;
{{Documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:Mbox&amp;diff=179</id>
		<title>Template:Mbox</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:Mbox&amp;diff=179"/>
		<updated>2020-08-22T18:04:15Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#invoke:Message box|mbox}}&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>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Zoophilia_and_the_law&amp;diff=177</id>
		<title>Zoophilia and the law</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Zoophilia_and_the_law&amp;diff=177"/>
		<updated>2020-08-22T18:04:14Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Legality of bestiality by country or territory]]&lt;br /&gt;
&lt;br /&gt;
{{Redirect category shell|&lt;br /&gt;
{{R from move}}&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:Quote&amp;diff=175</id>
		<title>Template:Quote</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:Quote&amp;diff=175"/>
		<updated>2020-08-22T18:01:20Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;templatestyles src=&amp;quot;Template:Quote/styles.css&amp;quot; /&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;blockquote class=&amp;quot;templatequote&amp;quot; {{#if:{{{style|}}}|style=&amp;quot;{{{style}}}&amp;quot;}}&amp;gt;{{{text|{{{content|{{{quotetext|{{{quote|{{{1|&amp;lt;includeonly&amp;gt;{{error|Error: No text given for quotation (or equals sign used in the actual argument to an unnamed parameter)}}[[Category:Pages incorrectly using the quote template]]&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;{{lorem ipsum}}&amp;lt;/noinclude&amp;gt;}}}}}}}}}}}}}}}{{#if:{{{sign|}}}{{{cite|}}}{{{author|}}}{{{by|}}}{{{personquoted|}}}{{{source|}}}{{{ts|}}}{{{title|}}}{{{publication|}}}{{{quotesource|}}}{{{char|}}}{{{character|}}}{{{2|}}}{{{3|}}}{{{4|}}}{{{5|}}}|{{#if:{{{multiline|}}}|&amp;lt;nowiki /&amp;gt;}}&lt;br /&gt;
&amp;lt;div class=&amp;quot;templatequotecite&amp;quot;&amp;gt;—&amp;amp;thinsp;&amp;lt;cite&amp;gt;{{#if:{{{char|{{{character|{{{5|}}}}}}}}}|{{{char|{{{character|{{{5|}}}}}}}}}, in&amp;amp;#32;}}{{Comma separated entries&lt;br /&gt;
 | {{if empty|{{{sign|}}}|{{{cite|}}}|{{{author|}}}|{{{by|}}}|{{{personquoted|}}}|{{{2|}}}}}&lt;br /&gt;
 | {{if empty|{{{title|}}}|{{{publication|}}}|{{{ts|}}}|{{{quotesource|}}}|{{{3|}}}}}&lt;br /&gt;
 | {{if empty|{{{source|}}}|{{{4|}}}}}&lt;br /&gt;
 }}&amp;lt;/cite&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
}}&amp;lt;/blockquote&amp;gt;{{#if:{{{class|}}}{{{id|}}}{{{diff|}}}{{{4|}}}{{{5|}}}|[[Category:Pages incorrectly using the quote template]]}}{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using quote template with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Quote]] with unknown parameter &amp;quot;_VALUE_&amp;quot;|ignoreblank=y| 1 | 2 | 3 | 4 | 5 | author | by | char | character | cite | class | content | diff | id | multiline | personquoted | publication | quote | quotesource | quotetext | sign | source | style | text | title | ts }}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&amp;lt;!-- Add categories to the /doc subpage, not here! --&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:Pp-semi-indef&amp;diff=173</id>
		<title>Template:Pp-semi-indef</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:Pp-semi-indef&amp;diff=173"/>
		<updated>2020-08-22T18:01:20Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 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>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:Pp-move-indef&amp;diff=171</id>
		<title>Template:Pp-move-indef</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:Pp-move-indef&amp;diff=171"/>
		<updated>2020-08-22T18:01:20Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{{#invoke:Pp-move-indef|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>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:Portal-inline&amp;diff=169</id>
		<title>Template:Portal-inline</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:Portal-inline&amp;diff=169"/>
		<updated>2020-08-22T18:01:20Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;{{#invoke:portal-inline|main}}&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;/includeonly&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;noinclude&amp;gt;{{documentation}}&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:Paraphilias&amp;diff=167</id>
		<title>Template:Paraphilias</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:Paraphilias&amp;diff=167"/>
		<updated>2020-08-22T18:01:20Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Navbox&lt;br /&gt;
|name  = Paraphilias&lt;br /&gt;
|title = [[Paraphilia]]s&lt;br /&gt;
|bodyclass = hlist&lt;br /&gt;
|above = [[List of paraphilias|List]]&lt;br /&gt;
|list1 =&lt;br /&gt;
*[[Abasiophilia]]&lt;br /&gt;
*[[Acrotomophilia]]&lt;br /&gt;
*[[Agalmatophilia]]&lt;br /&gt;
*[[Algolagnia]]&lt;br /&gt;
*[[Apotemnophilia]]&lt;br /&gt;
*[[Autassassinophilia]]&lt;br /&gt;
*[[Biastophilia]]&lt;br /&gt;
*[[Smoking fetishism|Capnolagnia]]&lt;br /&gt;
*[[Chremastistophilia]]&lt;br /&gt;
*[[Chronophilia]]&lt;br /&gt;
*[[Coprophagia]]&lt;br /&gt;
*[[Coprophilia]]&lt;br /&gt;
*[[Leg fetishism|Crurophilia]]&lt;br /&gt;
*[[Crush fetish]]&lt;br /&gt;
*[[Dacryphilia]]&lt;br /&gt;
*[[Dendrophilia (paraphilia)|Dendrophilia]]&lt;br /&gt;
*[[Emetophilia]]&lt;br /&gt;
*[[Flatulence fetishism|Eproctophilia]]&lt;br /&gt;
*[[Erotic asphyxiation]]&lt;br /&gt;
*[[Erotic hypnosis]]&lt;br /&gt;
&amp;lt;!-- NOTE: Ephebophilia is not a paraphilia; refer to the Ephebophilia article. --&amp;gt;&lt;br /&gt;
*[[Lust murder|Erotophonophilia]]&lt;br /&gt;
*[[Exhibitionism]]&lt;br /&gt;
*[[Formicophilia]]&lt;br /&gt;
*[[Frotteurism]]&lt;br /&gt;
*[[Gerontophilia]]&lt;br /&gt;
&amp;lt;!-- NOTE: Hebephilia is hotly contested as both a paraphilia and mental disorder; refer to the Hebephilia article. --&amp;gt;&lt;br /&gt;
*[[Homeovestism]]&lt;br /&gt;
*[[Hybristophilia]]&lt;br /&gt;
*[[Infantophilia]]&lt;br /&gt;
*[[Kleptolagnia]]&lt;br /&gt;
*[[Klismaphilia]]&lt;br /&gt;
*[[Erotic lactation|Lactaphilia]]&lt;br /&gt;
*[[Macrophilia]]&lt;br /&gt;
*[[Sexual masochism disorder|Masochism]]&lt;br /&gt;
*[[Mechanophilia]]&lt;br /&gt;
*[[Microphilia]]&lt;br /&gt;
*[[Narratophilia]]&lt;br /&gt;
*[[Nose fetishism|Nasophilia]]&lt;br /&gt;
*[[Necrophilia]]&lt;br /&gt;
*[[Object sexuality]]&lt;br /&gt;
*[[Odaxelagnia]]&lt;br /&gt;
*[[Olfactophilia]]&lt;br /&gt;
*[[Omorashi]]&lt;br /&gt;
*[[Paraphilic infantilism]]&lt;br /&gt;
*[[Partialism]]&lt;br /&gt;
*[[Pecattiphilia]]&lt;br /&gt;
*[[Pedophilia]]&lt;br /&gt;
*[[Foot fetishism|Podophilia]]&lt;br /&gt;
*[[Plushophilia]]&lt;br /&gt;
*[[Pyrophilia]]&lt;br /&gt;
*[[Sexual sadism disorder|Sadism]]&lt;br /&gt;
*[[Salirophilia]]&lt;br /&gt;
*[[Scopophilia]]&lt;br /&gt;
*[[Somnophilia]]&lt;br /&gt;
*[[Muscle worship|Sthenolagnia]]&lt;br /&gt;
*[[Symphorophilia]]&lt;br /&gt;
*[[Tamakeri]]&lt;br /&gt;
*[[Obscene phone call|Telephone scatologia]]&lt;br /&gt;
*[[Transvestic fetishism]]&lt;br /&gt;
*[[Hair fetishism|Trichophilia]]&lt;br /&gt;
*[[Troilism]]&lt;br /&gt;
*[[Urolagnia]]&lt;br /&gt;
*[[Urophagia]]&lt;br /&gt;
*[[Vorarephilia]]&lt;br /&gt;
*[[Voyeurism]]&lt;br /&gt;
*[[Zoophilia]]&lt;br /&gt;
*[[Zoosadism]]&lt;br /&gt;
&lt;br /&gt;
|state3 = plain&lt;br /&gt;
|list3  = {{Navbox|subgroup&lt;br /&gt;
|above  = &#039;&#039;&#039;See also&#039;&#039;&#039;&lt;br /&gt;
|list1  =&lt;br /&gt;
*[[Other specified paraphilic disorder]]&lt;br /&gt;
*[[Erotic target location error]]&lt;br /&gt;
*[[Courtship disorder]]&lt;br /&gt;
*[[Polymorphous perversity]]&lt;br /&gt;
*[[Sexual fetishism]]&lt;br /&gt;
*[[Human sexual activity]]&lt;br /&gt;
*[[Perversion]]&lt;br /&gt;
*[[Sexology]]&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
| below = &lt;br /&gt;
* {{Icon|Book}} &#039;&#039;&#039;[[Book:Paraphilias|Book]]&#039;&#039;&#039;&lt;br /&gt;
* {{icon|Category}} &#039;&#039;&#039;[[:Category:Paraphilias|Category]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{Warning|Only put this template on pages about paraphilias - it includes pages it is on in [[:Category:Paraphilias]].}}&lt;br /&gt;
{{collapsible option}}&lt;br /&gt;
[[Category:Psychology navigational boxes]]&lt;br /&gt;
[[Category:Sex and sexuality templates]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:Paraphilia&amp;diff=165</id>
		<title>Template:Paraphilia</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:Paraphilia&amp;diff=165"/>
		<updated>2020-08-22T18:01:20Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Template:Paraphilias]]&lt;br /&gt;
&lt;br /&gt;
{{R from move}}&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:Pagetype&amp;diff=163</id>
		<title>Template:Pagetype</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:Pagetype&amp;diff=163"/>
		<updated>2020-08-22T18:01:20Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 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>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:Ns_has_subpages&amp;diff=161</id>
		<title>Template:Ns has subpages</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:Ns_has_subpages&amp;diff=161"/>
		<updated>2020-08-22T18:01:20Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 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>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:Navbox&amp;diff=159</id>
		<title>Template:Navbox</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:Navbox&amp;diff=159"/>
		<updated>2020-08-22T18:01:20Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{{#invoke:Navbox|navbox}}&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>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:Main_other&amp;diff=157</id>
		<title>Template:Main other</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:Main_other&amp;diff=157"/>
		<updated>2020-08-22T18:01:20Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 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 and interwikis to the /doc subpage, not here! --&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:Main&amp;diff=155</id>
		<title>Template:Main</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:Main&amp;diff=155"/>
		<updated>2020-08-22T18:01:20Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#invoke:main|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>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:Icon&amp;diff=153</id>
		<title>Template:Icon</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:Icon&amp;diff=153"/>
		<updated>2020-08-22T18:01:20Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#invoke:Icon|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>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:ISBN&amp;diff=151</id>
		<title>Template:ISBN</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:ISBN&amp;diff=151"/>
		<updated>2020-08-22T18:01:20Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#if:{{{1|&amp;lt;noinclude&amp;gt;$&amp;lt;/noinclude&amp;gt;}}}|{{Catalog lookup link|{{{1|}}}|{{{2|}}}|{{{3|}}}|{{{4|}}}|{{{5|}}}|{{{6|}}}|{{{7|}}}|{{{8|}}}|{{{9|}}}|article-link={{#ifeq:{{yesno-no|{{{plainlink|}}}}}|yes||{{#ifeq:{{yesno-yes|{{{link|}}}}}|no||ISBN (identifier)}}}}|article-name={{#ifeq:{{yesno-no|{{{plainlink|}}}}}|yes||ISBN}}|link-prefix=[Special:BookSources/|item-prefix={{!}}|item-postfix=]|list-leadout={{{leadout|}}}}}{{#if:{{trim|{{{1|}}}}}|{{#ifeq:{{yesno-no|{{{invalid1|}}}}}|yes|{{main other|[[Category:Pages with listed invalid ISBNs]]}}|{{#invoke:check isxn|check_isbn|{{{1|}}}|error={{error-small|&amp;amp;nbsp;Parameter error in {{tl|ISBN}}: Invalid [[ISBN]].}}{{main other|[[Category:Pages with ISBN errors]]}}}}}}{{#if:{{trim|{{{2|}}}}}|{{#ifeq:{{yesno-no|{{{invalid2|}}}}}|yes|{{main other|[[Category:Pages with listed invalid ISBNs]]}}|{{#invoke:check isxn|check_isbn|{{{2|}}}|error={{error-small|&amp;amp;nbsp;Parameter error in {{tl|ISBN}}: Invalid [[ISBN]].}}{{main other|[[Category:Pages with ISBN errors]]}}}}}}{{#if:{{trim|{{{3|}}}}}|{{#ifeq:{{yesno-no|{{{invalid3|}}}}}|yes|{{main other|[[Category:Pages with listed invalid ISBNs]]}}|{{#invoke:check isxn|check_isbn|{{{3|}}}|error={{error-small|&amp;amp;nbsp;Parameter error in {{tl|ISBN}}: Invalid [[ISBN]].}}{{main other|[[Category:Pages with ISBN errors]]}}}}}}{{#if:{{trim|{{{4|}}}}}|{{#ifeq:{{yesno-no|{{{invalid4|}}}}}|yes|{{main other|[[Category:Pages with listed invalid ISBNs]]}}|{{#invoke:check isxn|check_isbn|{{{4|}}}|error={{error-small|&amp;amp;nbsp;Parameter error in {{tl|ISBN}}: Invalid [[ISBN]].}}{{main other|[[Category:Pages with ISBN errors]]}}}}}}{{#if:{{trim|{{{5|}}}}}|{{#ifeq:{{yesno-no|{{{invalid5|}}}}}|yes|{{main other|[[Category:Pages with listed invalid ISBNs]]}}|{{#invoke:check isxn|check_isbn|{{{5|}}}|error={{error-small|&amp;amp;nbsp;Parameter error in {{tl|ISBN}}: Invalid [[ISBN]].}}{{main other|[[Category:Pages with ISBN errors]]}}}}}}{{#if:{{trim|{{{6|}}}}}|{{#ifeq:{{yesno-no|{{{invalid6|}}}}}|yes|{{main other|[[Category:Pages with listed invalid ISBNs]]}}|{{#invoke:check isxn|check_isbn|{{{6|}}}|error={{error-small|&amp;amp;nbsp;Parameter error in {{tl|ISBN}}: Invalid [[ISBN]].}}{{main other|[[Category:Pages with ISBN errors]]}}}}}}{{#if:{{trim|{{{7|}}}}}|{{#ifeq:{{yesno-no|{{{invalid7|}}}}}|yes|{{main other|[[Category:Pages with listed invalid ISBNs]]}}|{{#invoke:check isxn|check_isbn|{{{7|}}}|error={{error-small|&amp;amp;nbsp;Parameter error in {{tl|ISBN}}: Invalid [[ISBN]].}}{{main other|[[Category:Pages with ISBN errors]]}}}}}}{{#if:{{trim|{{{8|}}}}}|{{#ifeq:{{yesno-no|{{{invalid8|}}}}}|yes|{{main other|[[Category:Pages with listed invalid ISBNs]]}}|{{#invoke:check isxn|check_isbn|{{{8|}}}|error={{error-small|&amp;amp;nbsp;Parameter error in {{tl|ISBN}}: Invalid [[ISBN]].}}{{main other|[[Category:Pages with ISBN errors]]}}}}}}{{#if:{{trim|{{{9|}}}}}|{{#ifeq:{{yesno-no|{{{invalid9|}}}}}|yes|{{main other|[[Category:Pages with listed invalid ISBNs]]}}|{{#invoke:check isxn|check_isbn|{{{9|}}}|error={{error-small|&amp;amp;nbsp;Parameter error in {{tl|ISBN}}: Invalid [[ISBN]].}}{{main other|[[Category:Pages with ISBN errors]]}}}}}}}}}}}}}}}}}}}}}}}}|{{error-small|Parameter error in {{tl|ISBN}}: Missing [[ISBN]].}}}}{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using ISBN template with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:ISBN]] with unknown parameter &amp;quot;_VALUE_&amp;quot;|ignoreblank=y| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | invalid1 | invalid2 | invalid3 | invalid4 | invalid5 | invalid6 | invalid7 | invalid8 | invalid9 | leadout | link | plainlink }}&amp;lt;noinclude&amp;gt;{{documentation}}&amp;lt;!-- Add categories and interwiki lines to the /doc subpage, not here! --&amp;gt;&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:IPA&amp;diff=149</id>
		<title>Template:IPA</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:IPA&amp;diff=149"/>
		<updated>2020-08-22T18:01:20Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;span title=&amp;quot;Representation in the International Phonetic Alphabet (IPA)&amp;quot; class=&amp;quot;IPA&amp;quot;&amp;gt;{{{1}}}&amp;lt;/span&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>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:For&amp;diff=147</id>
		<title>Template:For</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:For&amp;diff=147"/>
		<updated>2020-08-22T18:01:20Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{{#invoke:For|For}}&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>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:Fix/category&amp;diff=145</id>
		<title>Template:Fix/category</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:Fix/category&amp;diff=145"/>
		<updated>2020-08-22T18:01:20Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{pp-template|small=yes}}&amp;lt;/noinclude&amp;gt;{{{cat|[[Category:All pages needing cleanup]]}}}{{#if:{{{cat-date|}}}&lt;br /&gt;
  |[[{{{cat-date}}} {{#if:{{{date|}}}&lt;br /&gt;
   |from {{{date}}}&lt;br /&gt;
  }}]]{{#if:{{{date|}}}&lt;br /&gt;
   |{{#ifexist:{{{cat-date}}} from {{{date}}}|&lt;br /&gt;
    |[[Category:Articles with invalid date parameter in template]]&lt;br /&gt;
   }}&lt;br /&gt;
  }}&lt;br /&gt;
 }}{{#if:{{{cat2|}}}|{{{cat2}}}}}{{#if:{{{cat-date2|}}}&lt;br /&gt;
  |[[{{{cat-date2}}} {{#if:{{{date|}}}&lt;br /&gt;
   |from {{{date}}}&lt;br /&gt;
  }}]]{{#if:{{{date|}}}&lt;br /&gt;
   |{{#ifexist:{{{cat-date2}}} from {{{date}}}|&lt;br /&gt;
    |[[Category:Articles with invalid date parameter in template]]&lt;br /&gt;
   }}&lt;br /&gt;
  }}&lt;br /&gt;
 }}{{#if:{{{cat3|}}}|{{{cat3}}}}}{{#if:{{{cat-date3|}}}&lt;br /&gt;
  |[[{{{cat-date3}}} {{#if:{{{date|}}}&lt;br /&gt;
   |from {{{date}}}&lt;br /&gt;
  }}]]{{#if:{{{date|}}}&lt;br /&gt;
   |{{#ifexist:{{{cat-date3}}} from {{{date}}}|&lt;br /&gt;
    |[[Category:Articles with invalid date parameter in template]]&lt;br /&gt;
   }}&lt;br /&gt;
  }}&lt;br /&gt;
 }}&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:Fix-span&amp;diff=143</id>
		<title>Template:Fix-span</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:Fix-span&amp;diff=143"/>
		<updated>2020-08-22T18:01:20Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#if:{{{content|}}}|&amp;lt;span class=&amp;quot;{{{span-class|cleanup-needed-content}}}&amp;quot; style=&amp;quot;padding-left:0.1em; padding-right:0.1em; color:#595959; border:1px solid #DDD;&amp;quot;&amp;gt;{{{content|}}}&amp;lt;/span&amp;gt;}}{{#switch:{{{subst|¬}}}&lt;br /&gt;
 |¬={{category handler&lt;br /&gt;
  |template=[[Category:Templates needing substitution checking]]&lt;br /&gt;
  |nocat={{{nocat|&amp;lt;noinclude&amp;gt;true&amp;lt;/noinclude&amp;gt;}}}&lt;br /&gt;
 }}&lt;br /&gt;
 |SUBST=[[Category:Pages with incorrectly substituted templates]]&lt;br /&gt;
}}{{Category handler&lt;br /&gt;
 |main={{Fix/category&lt;br /&gt;
  |cat-date={{{cat-date|}}} &lt;br /&gt;
  |cat={{{cat|}}} &lt;br /&gt;
  |cat-date2={{{cat-date2|}}} &lt;br /&gt;
  |cat2={{{cat2|}}} &lt;br /&gt;
  |cat-date3={{{cat-date3|}}} &lt;br /&gt;
  |cat3={{{cat3|}}} &lt;br /&gt;
  |date={{{date|}}}&lt;br /&gt;
 }}&lt;br /&gt;
 |template={{#if:{{{name|}}}|{{#ifeq:{{{name}}}|{{ROOTPAGENAME}}||{{#if:{{{date|}}}||[[Category:Templates including undated clean-up tags]]}}}}}} &lt;br /&gt;
 |subpage=no&lt;br /&gt;
}}{{#if:{{{special|}}}&lt;br /&gt;
 |{{{special|}}}&lt;br /&gt;
 |&amp;lt;sup class=&amp;quot;noprint Inline-Template {{{class|}}}&amp;quot; style=&amp;quot;margin-left:0.1em; white-space:nowrap;&amp;quot;&amp;gt;&amp;amp;#91;&amp;lt;i&amp;gt;{{#if:{{{pre-text|}}}&lt;br /&gt;
  |{{{pre-text}}}&amp;amp;#32;&lt;br /&gt;
 }}[[{{{link|Wikipedia:Cleanup}}}|&amp;lt;span title=&amp;quot;{{replace|{{{title|{{{link|Wikipedia:Cleanup}}}}}}|&amp;quot;|&amp;amp;quot;}}{{#if:{{{date|}}}|&amp;lt;nowiki/&amp;gt; ({{{date}}})}}&amp;quot;&amp;gt;{{{text|}}}&amp;lt;/span&amp;gt;]]{{#if:{{{post-text|}}}&lt;br /&gt;
  |&amp;amp;#32;{{{post-text}}}&lt;br /&gt;
 }}&amp;lt;/i&amp;gt;&amp;amp;#93;&amp;lt;/sup&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>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:Fix&amp;diff=141</id>
		<title>Template:Fix</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:Fix&amp;diff=141"/>
		<updated>2020-08-22T18:01:20Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#switch:{{{subst|¬}}}&lt;br /&gt;
 |¬={{category handler&lt;br /&gt;
  |template=[[Category:Templates needing substitution checking]]&lt;br /&gt;
  |nocat={{{nocat|&amp;lt;noinclude&amp;gt;true&amp;lt;/noinclude&amp;gt;}}}&lt;br /&gt;
 }}&lt;br /&gt;
 |SUBST=[[Category:Pages with incorrectly substituted templates]]&lt;br /&gt;
}}{{Category handler&lt;br /&gt;
 |main={{Fix/category&lt;br /&gt;
  |cat-date={{{cat-date|}}} &lt;br /&gt;
  |cat={{{cat|}}} &lt;br /&gt;
  |cat-date2={{{cat-date2|}}} &lt;br /&gt;
  |cat2={{{cat2|}}} &lt;br /&gt;
  |cat-date3={{{cat-date3|}}} &lt;br /&gt;
  |cat3={{{cat3|}}} &lt;br /&gt;
  |date={{{date|}}}&lt;br /&gt;
 }}&lt;br /&gt;
 |template={{#if:{{{name|}}}|{{#ifeq:{{{name}}}|{{ROOTPAGENAME}}||{{#if:{{{date|}}}||[[Category:Templates including undated clean-up tags]]}}}}}} &lt;br /&gt;
 |subpage=no&lt;br /&gt;
}}{{#if:{{{text|}}}&lt;br /&gt;
 |&amp;lt;sup class=&amp;quot;noprint Inline-Template {{{class|}}}&amp;quot; style=&amp;quot;white-space:nowrap;&amp;quot;&amp;gt;&amp;amp;#91;&amp;lt;i&amp;gt;{{#if:{{{pre-text|}}}&lt;br /&gt;
  |{{{pre-text}}}&amp;amp;#32;&lt;br /&gt;
 }}[[{{{link|Wikipedia:Cleanup}}}|&amp;lt;span title=&amp;quot;{{delink|1={{{title|{{{link|Wikipedia:Cleanup}}}}}}{{#if:{{{date|}}}|&amp;amp;#32;({{{date}}})}}}}&amp;quot;&amp;gt;{{{text|}}}&amp;lt;/span&amp;gt;]]{{#if:{{{post-text|}}}&lt;br /&gt;
  |&amp;amp;#32;{{{post-text}}}&lt;br /&gt;
 }}&amp;lt;/i&amp;gt;&amp;amp;#93;&amp;lt;/sup&amp;gt;|{{{special|}}}&lt;br /&gt;
}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{Documentation}}&lt;br /&gt;
&amp;lt;!-- Add cats and interwikis to the /doc subpage, not here! --&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:Failed_verification&amp;diff=139</id>
		<title>Template:Failed verification</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:Failed_verification&amp;diff=139"/>
		<updated>2020-08-22T18:01:20Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ {{{|safesubst:}}}#invoke:Unsubst||date=__DATE__ |$B=&lt;br /&gt;
&amp;lt;!--{{Failed verification}} begin--&amp;gt;{{Fix&lt;br /&gt;
| subst = &amp;lt;includeonly&amp;gt;{{subst:&amp;lt;/includeonly&amp;gt;&amp;lt;includeonly&amp;gt;substcheck}}&amp;lt;/includeonly&amp;gt;&lt;br /&gt;
| link  = Wikipedia:Verifiability&lt;br /&gt;
| text  = failed verification&lt;br /&gt;
| title = {{{reason|The material near this tag failed verification of its source citation(s).}}}&lt;br /&gt;
| date  = {{{date|}}}&lt;br /&gt;
| cat   = [[Category:All articles with failed verification]]&lt;br /&gt;
| cat-date = Category:Articles with failed verification&lt;br /&gt;
| post-text = {{#if:{{{talk|}}}|– [[{{TALKPAGENAME}}#{{{talk}}}|see discussion]]|{{#if:{{{talkpage|{{{talk page|}}}}}}|– [[{{{talkpage|{{{talk page}}}}}}|see discussion]]}}}}&lt;br /&gt;
}}&amp;lt;!--{{Failed verification}} end--&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>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:FULLROOTPAGENAME&amp;diff=137</id>
		<title>Template:FULLROOTPAGENAME</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:FULLROOTPAGENAME&amp;diff=137"/>
		<updated>2020-08-22T18:01:20Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ {{{|safesubst:}}}#if: {{ {{{|safesubst:}}}Ns has subpages | {{ {{{|safesubst:}}}#if:{{{1|}}}|{{ {{{|safesubst:}}}NAMESPACE:{{{1}}}}}|{{ {{{|safesubst:}}}NAMESPACE}}}} }} &lt;br /&gt;
  | {{ {{{|safesubst:}}}#titleparts:{{ {{{|safesubst:}}}#if:{{{1|}}}|{{{1}}}|{{ {{{|safesubst:}}}FULLPAGENAME}}}}|1}}&lt;br /&gt;
  | {{ {{{|safesubst:}}}#if:{{{1|}}}|{{{1}}}|{{ {{{|safesubst:}}}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>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:Error-small&amp;diff=135</id>
		<title>Template:Error-small</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:Error-small&amp;diff=135"/>
		<updated>2020-08-22T18:01:20Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{small|{{#invoke:Error|error|{{{message|{{{1}}}}}}|tag=span}}}}&amp;lt;noinclude&amp;gt;{{documentation}}&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:EditAtWikidata&amp;diff=133</id>
		<title>Template:EditAtWikidata</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:EditAtWikidata&amp;diff=133"/>
		<updated>2020-08-22T18:01:20Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#invoke:EditAtWikidata |showMessage |qid={{{qid|}}} |pid={{{pid|}}} |nbsp={{{nbsp|}}} |{{{1|}}} }}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:Div_col_end&amp;diff=131</id>
		<title>Template:Div col end</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:Div_col_end&amp;diff=131"/>
		<updated>2020-08-22T18:01:20Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{Documentation|Template:Div col/doc}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:Div_col&amp;diff=129</id>
		<title>Template:Div col</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:Div_col&amp;diff=129"/>
		<updated>2020-08-22T18:01:20Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&amp;lt;div class=&amp;quot;div-col columns column-width&amp;quot; style=&amp;quot;{{column-width|{{{colwidth|30em}}}}} &amp;lt;!--&lt;br /&gt;
 --&amp;gt;{{#if: {{{gap|}}}&lt;br /&gt;
    | {{column-gap|{{{gap}}}}} }}&amp;lt;!--&lt;br /&gt;
 --&amp;gt;{{#switch: {{{rules|}}}&lt;br /&gt;
    | = &amp;lt;!--empty--&amp;gt;&lt;br /&gt;
    | yes = {{column-rule}}&lt;br /&gt;
    | {{Column-rule|{{{rules}}}}} }} &amp;lt;!--&lt;br /&gt;
 --&amp;gt;{{#ifeq: {{{small|}}}|yes&lt;br /&gt;
    | font-size:90%; }} &amp;lt;!--&lt;br /&gt;
 --&amp;gt;{{#if: {{{style|}}}&lt;br /&gt;
    | {{{style}}} }}&amp;quot;&amp;gt;&amp;lt;!--&lt;br /&gt;
 --&amp;gt;{{#if: {{{content|}}}&lt;br /&gt;
    |{{{content}}}&lt;br /&gt;
&amp;lt;/div&amp;gt;}}&amp;lt;!-- Inventory how many pages use small=yes &lt;br /&gt;
 --&amp;gt;{{#ifeq: {{{small|}}}|yes&lt;br /&gt;
    |[[Category:Pages using div col with small parameter]]}}&amp;lt;/includeonly&amp;gt;{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using div col with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Div col]] with unknown parameter &amp;quot;_VALUE_&amp;quot;; use colwidth= to specify column size |ignoreblank=y | colwidth | content | gap | rules | small | style }}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{Documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Adam52</name></author>
	</entry>
	<entry>
		<id>https://zoophilia.wiki/index.php?title=Template:Delink&amp;diff=127</id>
		<title>Template:Delink</title>
		<link rel="alternate" type="text/html" href="https://zoophilia.wiki/index.php?title=Template:Delink&amp;diff=127"/>
		<updated>2020-08-22T18:01:20Z</updated>

		<summary type="html">&lt;p&gt;Adam52: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{&amp;lt;includeonly&amp;gt;safesubst:&amp;lt;/includeonly&amp;gt;#invoke:delink|delink}}&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>Adam52</name></author>
	</entry>
</feed>