<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://sureshjoshi.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jayprakash12345</id>
	<title>Suresh Joshi - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://sureshjoshi.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jayprakash12345"/>
	<link rel="alternate" type="text/html" href="https://sureshjoshi.org/wiki/Special:Contributions/Jayprakash12345"/>
	<updated>2026-06-03T20:17:25Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.36.1</generator>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=MediaWiki:Common.css&amp;diff=220</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=MediaWiki:Common.css&amp;diff=220"/>
		<updated>2021-10-13T16:48:46Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;@font-face {&lt;br /&gt;
    font-family: &amp;quot;Ekatra&amp;quot;;&lt;br /&gt;
    src: url(&amp;quot;https://sureshjoshi.org/fonts/Ekatra-Normal.ttf&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &amp;quot;Ekatra&amp;quot;;&lt;br /&gt;
    src: url(&amp;quot;https://sureshjoshi.org/fonts/Ekatra-Bold.ttf&amp;quot;);&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &amp;quot;Ekatra&amp;quot;;&lt;br /&gt;
    src: url(&amp;quot;https://sureshjoshi.org/fonts/Ekatra-Italic.ttf&amp;quot;);&lt;br /&gt;
    font-style: italic;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
body {&lt;br /&gt;
  font-family: Ekatra;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#bodyContent{&lt;br /&gt;
  font-size: 20px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#p-logo-text {&lt;br /&gt;
	display: flex;&lt;br /&gt;
	align-items: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#footer-places, #ca-viewsource, #ca-talk {&lt;br /&gt;
	display: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#p-banner {&lt;br /&gt;
	overflow: hidden;&lt;br /&gt;
	white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#mw-content-container {&lt;br /&gt;
	background-image: none;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=MediaWiki:Common.css&amp;diff=219</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=MediaWiki:Common.css&amp;diff=219"/>
		<updated>2021-10-13T16:47:51Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: Undo revision 218 by Jayprakash12345 (talk)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;@font-face {&lt;br /&gt;
    font-family: &amp;quot;Ekatra&amp;quot;;&lt;br /&gt;
    src: url(&amp;quot;https://sureshjoshi.org/fonts/Ekatra-Normal.ttf&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &amp;quot;Ekatra&amp;quot;;&lt;br /&gt;
    src: url(&amp;quot;https://sureshjoshi.org/fonts/Ekatra-Bold.ttf&amp;quot;);&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &amp;quot;Ekatra&amp;quot;;&lt;br /&gt;
    src: url(&amp;quot;https://sureshjoshi.org/fonts/Ekatra-Italic.ttf&amp;quot;);&lt;br /&gt;
    font-style: italic;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
body {&lt;br /&gt;
  font-family: Ekatra;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#bodyContent{&lt;br /&gt;
  font-size: 18px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#p-logo-text {&lt;br /&gt;
	display: flex;&lt;br /&gt;
	align-items: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#footer-places, #ca-viewsource, #ca-talk {&lt;br /&gt;
	display: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#p-banner {&lt;br /&gt;
	overflow: hidden;&lt;br /&gt;
	white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#mw-content-container {&lt;br /&gt;
	background-image: none;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=MediaWiki:Common.css&amp;diff=218</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=MediaWiki:Common.css&amp;diff=218"/>
		<updated>2021-10-13T16:46:53Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;@font-face {&lt;br /&gt;
    font-family: &amp;quot;Ekatra&amp;quot;;&lt;br /&gt;
    src: url(&amp;quot;https://sureshjoshi.org/fonts/Ekatra-Normal.ttf&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &amp;quot;Ekatra&amp;quot;;&lt;br /&gt;
    src: url(&amp;quot;https://sureshjoshi.org/fonts/Ekatra-Bold.ttf&amp;quot;);&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &amp;quot;Ekatra&amp;quot;;&lt;br /&gt;
    src: url(&amp;quot;https://sureshjoshi.org/fonts/Ekatra-Italic.ttf&amp;quot;);&lt;br /&gt;
    font-style: italic;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
body {&lt;br /&gt;
  font-family: Ekatra;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#bodyContent{&lt;br /&gt;
  font-size: 20px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#p-logo-text {&lt;br /&gt;
	display: flex;&lt;br /&gt;
	align-items: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#footer-places, #ca-viewsource, #ca-talk {&lt;br /&gt;
	display: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#p-banner {&lt;br /&gt;
	overflow: hidden;&lt;br /&gt;
	white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#mw-content-container {&lt;br /&gt;
	background-image: none;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=User:Jayprakash12345/Sandbox&amp;diff=180</id>
		<title>User:Jayprakash12345/Sandbox</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=User:Jayprakash12345/Sandbox&amp;diff=180"/>
		<updated>2021-09-27T14:29:15Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{|&lt;br /&gt;
|+ Caption text&lt;br /&gt;
|-&lt;br /&gt;
! Header text !! Header text !! Header text&lt;br /&gt;
|-&lt;br /&gt;
| Example || Example || Example&lt;br /&gt;
|-&lt;br /&gt;
| Example || Example || Example&lt;br /&gt;
|-&lt;br /&gt;
| Example || Example || Example&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=User:Jayprakash12345/Sandbox&amp;diff=179</id>
		<title>User:Jayprakash12345/Sandbox</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=User:Jayprakash12345/Sandbox&amp;diff=179"/>
		<updated>2021-09-27T14:29:04Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: Created page with &amp;quot;{| class=&amp;quot;wikitable&amp;quot; |+ Caption text |- ! Header text !! Header text !! Header text |- | Example || Example || Example |- | Example || Example || Example |- | Example || Examp...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Caption text&lt;br /&gt;
|-&lt;br /&gt;
! Header text !! Header text !! Header text&lt;br /&gt;
|-&lt;br /&gt;
| Example || Example || Example&lt;br /&gt;
|-&lt;br /&gt;
| Example || Example || Example&lt;br /&gt;
|-&lt;br /&gt;
| Example || Example || Example&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=MediaWiki:Common.css&amp;diff=174</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=MediaWiki:Common.css&amp;diff=174"/>
		<updated>2021-09-27T13:31:06Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;@font-face {&lt;br /&gt;
    font-family: &amp;quot;Ekatra&amp;quot;;&lt;br /&gt;
    src: url(&amp;quot;https://sureshjoshi.org/fonts/Ekatra-Normal.ttf&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &amp;quot;Ekatra&amp;quot;;&lt;br /&gt;
    src: url(&amp;quot;https://sureshjoshi.org/fonts/Ekatra-Bold.ttf&amp;quot;);&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &amp;quot;Ekatra&amp;quot;;&lt;br /&gt;
    src: url(&amp;quot;https://sureshjoshi.org/fonts/Ekatra-Italic.ttf&amp;quot;);&lt;br /&gt;
    font-style: italic;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
body {&lt;br /&gt;
  font-family: Ekatra;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#bodyContent{&lt;br /&gt;
  font-size: 18px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#p-logo-text {&lt;br /&gt;
	display: flex;&lt;br /&gt;
	align-items: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#footer-places, #ca-viewsource, #ca-talk {&lt;br /&gt;
	display: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#p-banner {&lt;br /&gt;
	overflow: hidden;&lt;br /&gt;
	white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#mw-content-container {&lt;br /&gt;
	background-image: none;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=MediaWiki:Common.css&amp;diff=173</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=MediaWiki:Common.css&amp;diff=173"/>
		<updated>2021-09-27T13:30:23Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;@font-face {&lt;br /&gt;
    font-family: &amp;quot;Ekatra&amp;quot;;&lt;br /&gt;
    src: url(&amp;quot;https://sureshjoshi.org/fonts/Ekatra-Normal.ttf&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &amp;quot;Ekatra&amp;quot;;&lt;br /&gt;
    src: url(&amp;quot;https://sureshjoshi.org/fonts/Ekatra-Bold.ttf&amp;quot;);&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &amp;quot;Ekatra&amp;quot;;&lt;br /&gt;
    src: url(&amp;quot;https://sureshjoshi.org/fonts/Ekatra-Italic.ttf&amp;quot;);&lt;br /&gt;
    font-style: italic;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
body {&lt;br /&gt;
  font-family: Ekatra;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#bodyContent{&lt;br /&gt;
  font-size: 20px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#p-logo-text {&lt;br /&gt;
	display: flex;&lt;br /&gt;
	align-items: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#footer-places, #ca-viewsource, #ca-talk {&lt;br /&gt;
	display: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#p-banner {&lt;br /&gt;
	overflow: hidden;&lt;br /&gt;
	white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#mw-content-container {&lt;br /&gt;
	background-image: none;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=MediaWiki:Common.css&amp;diff=172</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=MediaWiki:Common.css&amp;diff=172"/>
		<updated>2021-09-27T13:27:42Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;@font-face {&lt;br /&gt;
    font-family: &amp;quot;Ekatra&amp;quot;;&lt;br /&gt;
    src: url(&amp;quot;https://sureshjoshi.org/fonts/Ekatra-Normal.ttf&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &amp;quot;Ekatra&amp;quot;;&lt;br /&gt;
    src: url(&amp;quot;https://sureshjoshi.org/fonts/Ekatra-Bold.ttf&amp;quot;);&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &amp;quot;Ekatra&amp;quot;;&lt;br /&gt;
    src: url(&amp;quot;https://sureshjoshi.org/fonts/Ekatra-Italic.ttf&amp;quot;);&lt;br /&gt;
    font-style: italic;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
body {&lt;br /&gt;
  font-family: Ekatra;&lt;br /&gt;
  font-size: 17px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#p-logo-text {&lt;br /&gt;
	display: flex;&lt;br /&gt;
	align-items: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#footer-places, #ca-viewsource, #ca-talk {&lt;br /&gt;
	display: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#p-banner {&lt;br /&gt;
	overflow: hidden;&lt;br /&gt;
	white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#mw-content-container {&lt;br /&gt;
	background-image: none;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=MediaWiki:Common.css&amp;diff=171</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=MediaWiki:Common.css&amp;diff=171"/>
		<updated>2021-09-27T13:25:31Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;@font-face {&lt;br /&gt;
    font-family: &amp;quot;Ekatra&amp;quot;;&lt;br /&gt;
    src: url(&amp;quot;https://sureshjoshi.org/fonts/Ekatra-Normal.ttf&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &amp;quot;Ekatra&amp;quot;;&lt;br /&gt;
    src: url(&amp;quot;https://sureshjoshi.org/fonts/Ekatra-Bold.ttf&amp;quot;);&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &amp;quot;Ekatra&amp;quot;;&lt;br /&gt;
    src: url(&amp;quot;https://sureshjoshi.org/fonts/Ekatra-Italic.ttf&amp;quot;);&lt;br /&gt;
    font-style: italic;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
body {&lt;br /&gt;
  font-family: Ekatra;&lt;br /&gt;
  font-size: 18px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#p-logo-text {&lt;br /&gt;
	display: flex;&lt;br /&gt;
	align-items: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#footer-places, #ca-viewsource, #ca-talk {&lt;br /&gt;
	display: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#p-banner {&lt;br /&gt;
	overflow: hidden;&lt;br /&gt;
	white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#mw-content-container {&lt;br /&gt;
	background-image: none;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=MediaWiki:Common.js&amp;diff=170</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=MediaWiki:Common.js&amp;diff=170"/>
		<updated>2021-09-27T13:24:32Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
$( function(){&lt;br /&gt;
	&lt;br /&gt;
	if( mw.config.get('wgIsMainPage') ){&lt;br /&gt;
		$('#firstHeading').remove();&lt;br /&gt;
		$('#ca-nstab-main').hide();&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	if( mw.config.get('wgUserName') === null  ){&lt;br /&gt;
		$('body').bind('cut copy', function(e) {&lt;br /&gt;
			e.preventDefault();&lt;br /&gt;
		});&lt;br /&gt;
	} else {&lt;br /&gt;
		$(&amp;quot;#content&amp;quot;).removeAttr(&amp;quot;onmousedown&amp;quot;);&lt;br /&gt;
		$(&amp;quot;#content&amp;quot;).removeAttr(&amp;quot;onselectstart&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
$( function(){&lt;br /&gt;
	&lt;br /&gt;
	var countPoem2 = $(&amp;quot;.Poem2-Ekatra&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	if( countPoem2.length &amp;gt; 0 ){&lt;br /&gt;
	&lt;br /&gt;
	var Poem2lenghtArray = [];&lt;br /&gt;
	for (var k = 0; k &amp;lt;= countPoem2.length; k++) {&lt;br /&gt;
	   Poem2lenghtArray.push(k);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
		Poem2lenghtArray.forEach(function(j) {&lt;br /&gt;
			&lt;br /&gt;
			var poemElement = $(&amp;quot;.Poem2-Ekatra&amp;quot;).eq(j);&lt;br /&gt;
						&lt;br /&gt;
			if( poemElement.length ){&lt;br /&gt;
				var poemText = poemElement.html();&lt;br /&gt;
&lt;br /&gt;
				var poemArray = poemText.split(&amp;quot;\n&amp;quot;);&lt;br /&gt;
				&lt;br /&gt;
				poemElement.text(&amp;quot;&amp;quot;);&lt;br /&gt;
			&lt;br /&gt;
				// First measure&lt;br /&gt;
				poemArray.forEach( function(i) {&lt;br /&gt;
					poemElement.append( '&amp;lt;p style=&amp;quot;text-indent: 2em;&amp;quot;&amp;gt;' + i + '&amp;lt;/p&amp;gt;' );&lt;br /&gt;
				});&lt;br /&gt;
				&lt;br /&gt;
				// Second measure&lt;br /&gt;
				poemElement.children('p').each(function () {&lt;br /&gt;
					$(this).css('text-indent', '2em');&lt;br /&gt;
				});&lt;br /&gt;
			}&lt;br /&gt;
		&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
});&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=MediaWiki:Common.css&amp;diff=169</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=MediaWiki:Common.css&amp;diff=169"/>
		<updated>2021-09-27T13:00:17Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;@font-face {&lt;br /&gt;
    font-family: &amp;quot;Ekatra&amp;quot;;&lt;br /&gt;
    src: url(&amp;quot;https://sureshjoshi.org/fonts/Ekatra-Normal.ttf&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &amp;quot;Ekatra&amp;quot;;&lt;br /&gt;
    src: url(&amp;quot;https://sureshjoshi.org/fonts/Ekatra-Bold.ttf&amp;quot;);&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
    font-family: &amp;quot;Ekatra&amp;quot;;&lt;br /&gt;
    src: url(&amp;quot;https://sureshjoshi.org/fonts/Ekatra-Italic.ttf&amp;quot;);&lt;br /&gt;
    font-style: italic;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
body {&lt;br /&gt;
  font-family: Ekatra;&lt;br /&gt;
  font-size: 20px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#p-logo-text {&lt;br /&gt;
	display: flex;&lt;br /&gt;
	align-items: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#footer-places, #ca-viewsource, #ca-talk {&lt;br /&gt;
	display: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#p-banner {&lt;br /&gt;
	overflow: hidden;&lt;br /&gt;
	white-space: nowrap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#mw-content-container {&lt;br /&gt;
	background-image: none;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Widget:Vimeo&amp;diff=166</id>
		<title>Widget:Vimeo</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Widget:Vimeo&amp;diff=166"/>
		<updated>2021-09-26T16:33:30Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&amp;lt;iframe allowfullscreen=&amp;quot;&amp;quot; height=&amp;quot;&amp;lt;!--{$height|default:300|escape:'html'}--&amp;gt;&amp;quot; src=&amp;quot;//player.vimeo.com/video/&amp;lt;!--{$id|escape:'urlpathinfo'}--&amp;gt;?title=0&amp;amp;amp;byline=0&amp;amp;amp;portrait=0&amp;quot; webkitallowfullscreen=&amp;quot;&amp;quot; width=&amp;quot;&amp;lt;!--{$width|default:400|escape:'html'}--&amp;gt;&amp;quot; style=&amp;quot;border: none&amp;quot;&amp;gt;&amp;lt;/iframe&amp;gt;&amp;lt;/includeonly&amp;gt;&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Usage ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{{#widget:Vimeo|id=8758454}}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:-&lt;br /&gt;
{{#widget:Vimeo|id=8758454}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Widget:Vimeo&amp;diff=165</id>
		<title>Widget:Vimeo</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Widget:Vimeo&amp;diff=165"/>
		<updated>2021-09-26T16:32:30Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&amp;lt;iframe allowfullscreen=&amp;quot;&amp;quot; height=&amp;quot;&amp;lt;!--{$height|default:300|escape:'html'}--&amp;gt;&amp;quot; src=&amp;quot;//player.vimeo.com/video/&amp;lt;!--{$id|escape:'urlpathinfo'}--&amp;gt;?title=0&amp;amp;amp;byline=0&amp;amp;amp;portrait=0&amp;quot; webkitallowfullscreen=&amp;quot;&amp;quot; width=&amp;quot;&amp;lt;!--{$width|default:400|escape:'html'}--&amp;gt;&amp;quot; style=&amp;quot;border: none&amp;quot;&amp;gt;&amp;lt;/iframe&amp;gt;&amp;lt;/includeonly&amp;gt;&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Usage ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{{#widget:Vimeo|id=8758454}}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:-&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Widget:Vimeo&amp;diff=164</id>
		<title>Widget:Vimeo</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Widget:Vimeo&amp;diff=164"/>
		<updated>2021-09-26T16:31:27Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: Created page with &amp;quot;&amp;lt;includeonly&amp;gt;&amp;lt;iframe allowfullscreen=&amp;quot;&amp;quot; height=&amp;quot;&amp;lt;!--{$height|default:300|escape:'html'}--&amp;gt;&amp;quot; src=&amp;quot;//player.vimeo.com/video/&amp;lt;!--{$id|escape:'urlpathinfo'}--&amp;gt;?title=0&amp;amp;amp;byline=...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&amp;lt;iframe allowfullscreen=&amp;quot;&amp;quot; height=&amp;quot;&amp;lt;!--{$height|default:300|escape:'html'}--&amp;gt;&amp;quot; src=&amp;quot;//player.vimeo.com/video/&amp;lt;!--{$id|escape:'urlpathinfo'}--&amp;gt;?title=0&amp;amp;amp;byline=0&amp;amp;amp;portrait=0&amp;quot; webkitallowfullscreen=&amp;quot;&amp;quot; width=&amp;quot;&amp;lt;!--{$width|default:400|escape:'html'}--&amp;gt;&amp;quot; style=&amp;quot;border: none&amp;quot;&amp;gt;&amp;lt;/iframe&amp;gt;&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Module:String&amp;diff=163</id>
		<title>Module:String</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Module:String&amp;diff=163"/>
		<updated>2021-09-26T15:44:22Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--[[&lt;br /&gt;
&lt;br /&gt;
This module is intended to provide access to basic string functions.&lt;br /&gt;
&lt;br /&gt;
Most of the functions provided here can be invoked with named parameters,&lt;br /&gt;
unnamed parameters, or a mixture.  If named parameters are used, Mediawiki will&lt;br /&gt;
automatically remove any leading or trailing whitespace from the parameter.&lt;br /&gt;
Depending on the intended use, it may be advantageous to either preserve or&lt;br /&gt;
remove such whitespace.&lt;br /&gt;
&lt;br /&gt;
Global options&lt;br /&gt;
    ignore_errors: If set to 'true' or 1, any error condition will result in&lt;br /&gt;
        an empty string being returned rather than an error message.&lt;br /&gt;
&lt;br /&gt;
    error_category: If an error occurs, specifies the name of a category to&lt;br /&gt;
        include with the error message.  The default category is&lt;br /&gt;
        [Category:Errors reported by Module String].&lt;br /&gt;
&lt;br /&gt;
    no_category: If set to 'true' or 1, no category will be added if an error&lt;br /&gt;
        is generated.&lt;br /&gt;
&lt;br /&gt;
Unit tests for this module are available at Module:String/tests.&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local str = {}&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
len&lt;br /&gt;
&lt;br /&gt;
This function returns the length of the target string.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|len|target_string|}}&lt;br /&gt;
OR&lt;br /&gt;
{{#invoke:String|len|s=target_string}}&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    s: The string whose length to report&lt;br /&gt;
&lt;br /&gt;
If invoked using named parameters, Mediawiki will automatically remove any leading or&lt;br /&gt;
trailing whitespace from the target string.&lt;br /&gt;
]]&lt;br /&gt;
function str.len( frame )&lt;br /&gt;
	local new_args = str._getParameters( frame.args, {'s'} )&lt;br /&gt;
	local s = new_args['s'] or ''&lt;br /&gt;
	return mw.ustring.len( s )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
sub&lt;br /&gt;
&lt;br /&gt;
This function returns a substring of the target string at specified indices.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|sub|target_string|start_index|end_index}}&lt;br /&gt;
OR&lt;br /&gt;
{{#invoke:String|sub|s=target_string|i=start_index|j=end_index}}&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    s: The string to return a subset of&lt;br /&gt;
    i: The fist index of the substring to return, defaults to 1.&lt;br /&gt;
    j: The last index of the string to return, defaults to the last character.&lt;br /&gt;
&lt;br /&gt;
The first character of the string is assigned an index of 1.  If either i or j&lt;br /&gt;
is a negative value, it is interpreted the same as selecting a character by&lt;br /&gt;
counting from the end of the string.  Hence, a value of -1 is the same as&lt;br /&gt;
selecting the last character of the string.&lt;br /&gt;
&lt;br /&gt;
If the requested indices are out of range for the given string, an error is&lt;br /&gt;
reported.&lt;br /&gt;
]]&lt;br /&gt;
function str.sub( frame )&lt;br /&gt;
	local new_args = str._getParameters( frame.args, { 's', 'i', 'j' } )&lt;br /&gt;
	local s = new_args['s'] or ''&lt;br /&gt;
	local i = tonumber( new_args['i'] ) or 1&lt;br /&gt;
	local j = tonumber( new_args['j'] ) or -1&lt;br /&gt;
&lt;br /&gt;
	local len = mw.ustring.len( s )&lt;br /&gt;
&lt;br /&gt;
	-- Convert negatives for range checking&lt;br /&gt;
	if i &amp;lt; 0 then&lt;br /&gt;
		i = len + i + 1&lt;br /&gt;
	end&lt;br /&gt;
	if j &amp;lt; 0 then&lt;br /&gt;
		j = len + j + 1&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if i &amp;gt; len or j &amp;gt; len or i &amp;lt; 1 or j &amp;lt; 1 then&lt;br /&gt;
		return str._error( 'String subset index out of range' )&lt;br /&gt;
	end&lt;br /&gt;
	if j &amp;lt; i then&lt;br /&gt;
		return str._error( 'String subset indices out of order' )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return mw.ustring.sub( s, i, j )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
This function implements that features of {{str sub old}} and is kept in order&lt;br /&gt;
to maintain these older templates.&lt;br /&gt;
]]&lt;br /&gt;
function str.sublength( frame )&lt;br /&gt;
	local i = tonumber( frame.args.i ) or 0&lt;br /&gt;
	local len = tonumber( frame.args.len )&lt;br /&gt;
	return mw.ustring.sub( frame.args.s, i + 1, len and ( i + len ) )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
_match&lt;br /&gt;
&lt;br /&gt;
This function returns a substring from the source string that matches a&lt;br /&gt;
specified pattern. It is exported for use in other modules&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
strmatch = require(&amp;quot;Module:String&amp;quot;)._match&lt;br /&gt;
sresult = strmatch( s, pattern, start, match, plain, nomatch )&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    s: The string to search&lt;br /&gt;
    pattern: The pattern or string to find within the string&lt;br /&gt;
    start: The index within the source string to start the search.  The first&lt;br /&gt;
        character of the string has index 1.  Defaults to 1.&lt;br /&gt;
    match: In some cases it may be possible to make multiple matches on a single&lt;br /&gt;
        string.  This specifies which match to return, where the first match is&lt;br /&gt;
        match= 1.  If a negative number is specified then a match is returned&lt;br /&gt;
        counting from the last match.  Hence match = -1 is the same as requesting&lt;br /&gt;
        the last match.  Defaults to 1.&lt;br /&gt;
    plain: A flag indicating that the pattern should be understood as plain&lt;br /&gt;
        text.  Defaults to false.&lt;br /&gt;
    nomatch: If no match is found, output the &amp;quot;nomatch&amp;quot; value rather than an error.&lt;br /&gt;
&lt;br /&gt;
For information on constructing Lua patterns, a form of [regular expression], see:&lt;br /&gt;
&lt;br /&gt;
* http://www.lua.org/manual/5.1/manual.html#5.4.1&lt;br /&gt;
* http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Patterns&lt;br /&gt;
* http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Ustring_patterns&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
-- This sub-routine is exported for use in other modules&lt;br /&gt;
function str._match( s, pattern, start, match_index, plain_flag, nomatch )&lt;br /&gt;
	if s == '' then&lt;br /&gt;
		return str._error( 'Target string is empty' )&lt;br /&gt;
	end&lt;br /&gt;
	if pattern == '' then&lt;br /&gt;
		return str._error( 'Pattern string is empty' )&lt;br /&gt;
	end&lt;br /&gt;
	start = tonumber(start) or 1&lt;br /&gt;
	if math.abs(start) &amp;lt; 1 or math.abs(start) &amp;gt; mw.ustring.len( s ) then&lt;br /&gt;
		return str._error( 'Requested start is out of range' )&lt;br /&gt;
	end&lt;br /&gt;
	if match_index == 0 then&lt;br /&gt;
		return str._error( 'Match index is out of range' )&lt;br /&gt;
	end&lt;br /&gt;
	if plain_flag then&lt;br /&gt;
		pattern = str._escapePattern( pattern )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local result&lt;br /&gt;
	if match_index == 1 then&lt;br /&gt;
		-- Find first match is simple case&lt;br /&gt;
		result = mw.ustring.match( s, pattern, start )&lt;br /&gt;
	else&lt;br /&gt;
		if start &amp;gt; 1 then&lt;br /&gt;
			s = mw.ustring.sub( s, start )&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		local iterator = mw.ustring.gmatch(s, pattern)&lt;br /&gt;
		if match_index &amp;gt; 0 then&lt;br /&gt;
			-- Forward search&lt;br /&gt;
			for w in iterator do&lt;br /&gt;
				match_index = match_index - 1&lt;br /&gt;
				if match_index == 0 then&lt;br /&gt;
					result = w&lt;br /&gt;
					break&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			-- Reverse search&lt;br /&gt;
			local result_table = {}&lt;br /&gt;
			local count = 1&lt;br /&gt;
			for w in iterator do&lt;br /&gt;
				result_table[count] = w&lt;br /&gt;
				count = count + 1&lt;br /&gt;
			end&lt;br /&gt;
&lt;br /&gt;
			result = result_table[ count + match_index ]&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if result == nil then&lt;br /&gt;
		if nomatch == nil then&lt;br /&gt;
			return str._error( 'Match not found' )&lt;br /&gt;
		else&lt;br /&gt;
			return nomatch&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		return result&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
match&lt;br /&gt;
&lt;br /&gt;
This function returns a substring from the source string that matches a&lt;br /&gt;
specified pattern.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|match|source_string|pattern_string|start_index|match_number|plain_flag|nomatch_output}}&lt;br /&gt;
OR&lt;br /&gt;
{{#invoke:String|match|s=source_string|pattern=pattern_string|start=start_index&lt;br /&gt;
    |match=match_number|plain=plain_flag|nomatch=nomatch_output}}&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    s: The string to search&lt;br /&gt;
    pattern: The pattern or string to find within the string&lt;br /&gt;
    start: The index within the source string to start the search.  The first&lt;br /&gt;
        character of the string has index 1.  Defaults to 1.&lt;br /&gt;
    match: In some cases it may be possible to make multiple matches on a single&lt;br /&gt;
        string.  This specifies which match to return, where the first match is&lt;br /&gt;
        match= 1.  If a negative number is specified then a match is returned&lt;br /&gt;
        counting from the last match.  Hence match = -1 is the same as requesting&lt;br /&gt;
        the last match.  Defaults to 1.&lt;br /&gt;
    plain: A flag indicating that the pattern should be understood as plain&lt;br /&gt;
        text.  Defaults to false.&lt;br /&gt;
    nomatch: If no match is found, output the &amp;quot;nomatch&amp;quot; value rather than an error.&lt;br /&gt;
&lt;br /&gt;
If invoked using named parameters, Mediawiki will automatically remove any leading or&lt;br /&gt;
trailing whitespace from each string.  In some circumstances this is desirable, in&lt;br /&gt;
other cases one may want to preserve the whitespace.&lt;br /&gt;
&lt;br /&gt;
If the match_number or start_index are out of range for the string being queried, then&lt;br /&gt;
this function generates an error.  An error is also generated if no match is found.&lt;br /&gt;
If one adds the parameter ignore_errors=true, then the error will be suppressed and&lt;br /&gt;
an empty string will be returned on any failure.&lt;br /&gt;
&lt;br /&gt;
For information on constructing Lua patterns, a form of [regular expression], see:&lt;br /&gt;
&lt;br /&gt;
* http://www.lua.org/manual/5.1/manual.html#5.4.1&lt;br /&gt;
* http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Patterns&lt;br /&gt;
* http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Ustring_patterns&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
-- This is the entry point for #invoke:String|match&lt;br /&gt;
function str.match( frame )&lt;br /&gt;
	local new_args = str._getParameters( frame.args, {'s', 'pattern', 'start', 'match', 'plain', 'nomatch'} )&lt;br /&gt;
	local s = new_args['s'] or ''&lt;br /&gt;
	local start = tonumber( new_args['start'] ) or 1&lt;br /&gt;
	local plain_flag = str._getBoolean( new_args['plain'] or false )&lt;br /&gt;
	local pattern = new_args['pattern'] or ''&lt;br /&gt;
	local match_index = math.floor( tonumber(new_args['match']) or 1 )&lt;br /&gt;
	local nomatch = new_args['nomatch']&lt;br /&gt;
&lt;br /&gt;
	return str._match( s, pattern, start, match_index, plain_flag, nomatch )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
pos&lt;br /&gt;
&lt;br /&gt;
This function returns a single character from the target string at position pos.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|pos|target_string|index_value}}&lt;br /&gt;
OR&lt;br /&gt;
{{#invoke:String|pos|target=target_string|pos=index_value}}&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    target: The string to search&lt;br /&gt;
    pos: The index for the character to return&lt;br /&gt;
&lt;br /&gt;
If invoked using named parameters, Mediawiki will automatically remove any leading or&lt;br /&gt;
trailing whitespace from the target string.  In some circumstances this is desirable, in&lt;br /&gt;
other cases one may want to preserve the whitespace.&lt;br /&gt;
&lt;br /&gt;
The first character has an index value of 1.&lt;br /&gt;
&lt;br /&gt;
If one requests a negative value, this function will select a character by counting backwards&lt;br /&gt;
from the end of the string.  In other words pos = -1 is the same as asking for the last character.&lt;br /&gt;
&lt;br /&gt;
A requested value of zero, or a value greater than the length of the string returns an error.&lt;br /&gt;
]]&lt;br /&gt;
function str.pos( frame )&lt;br /&gt;
	local new_args = str._getParameters( frame.args, {'target', 'pos'} )&lt;br /&gt;
	local target_str = new_args['target'] or ''&lt;br /&gt;
	local pos = tonumber( new_args['pos'] ) or 0&lt;br /&gt;
&lt;br /&gt;
	if pos == 0 or math.abs(pos) &amp;gt; mw.ustring.len( target_str ) then&lt;br /&gt;
		return str._error( 'String index out of range' )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return mw.ustring.sub( target_str, pos, pos )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
str_find&lt;br /&gt;
&lt;br /&gt;
This function duplicates the behavior of {{str_find}}, including all of its quirks.&lt;br /&gt;
This is provided in order to support existing templates, but is NOT RECOMMENDED for&lt;br /&gt;
new code and templates.  New code is recommended to use the &amp;quot;find&amp;quot; function instead.&lt;br /&gt;
&lt;br /&gt;
Returns the first index in &amp;quot;source&amp;quot; that is a match to &amp;quot;target&amp;quot;.  Indexing is 1-based,&lt;br /&gt;
and the function returns -1 if the &amp;quot;target&amp;quot; string is not present in &amp;quot;source&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Important Note: If the &amp;quot;target&amp;quot; string is empty / missing, this function returns a&lt;br /&gt;
value of &amp;quot;1&amp;quot;, which is generally unexpected behavior, and must be accounted for&lt;br /&gt;
separatetly.&lt;br /&gt;
]]&lt;br /&gt;
function str.str_find( frame )&lt;br /&gt;
	local new_args = str._getParameters( frame.args, {'source', 'target'} )&lt;br /&gt;
	local source_str = new_args['source'] or ''&lt;br /&gt;
	local target_str = new_args['target'] or ''&lt;br /&gt;
&lt;br /&gt;
	if target_str == '' then&lt;br /&gt;
		return 1&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local start = mw.ustring.find( source_str, target_str, 1, true )&lt;br /&gt;
	if start == nil then&lt;br /&gt;
		start = -1&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return start&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
find&lt;br /&gt;
&lt;br /&gt;
This function allows one to search for a target string or pattern within another&lt;br /&gt;
string.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|find|source_str|target_string|start_index|plain_flag}}&lt;br /&gt;
OR&lt;br /&gt;
{{#invoke:String|find|source=source_str|target=target_str|start=start_index|plain=plain_flag}}&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    source: The string to search&lt;br /&gt;
    target: The string or pattern to find within source&lt;br /&gt;
    start: The index within the source string to start the search, defaults to 1&lt;br /&gt;
    plain: Boolean flag indicating that target should be understood as plain&lt;br /&gt;
        text and not as a Lua style regular expression, defaults to true&lt;br /&gt;
&lt;br /&gt;
If invoked using named parameters, Mediawiki will automatically remove any leading or&lt;br /&gt;
trailing whitespace from the parameter.  In some circumstances this is desirable, in&lt;br /&gt;
other cases one may want to preserve the whitespace.&lt;br /&gt;
&lt;br /&gt;
This function returns the first index &amp;gt;= &amp;quot;start&amp;quot; where &amp;quot;target&amp;quot; can be found&lt;br /&gt;
within &amp;quot;source&amp;quot;.  Indices are 1-based.  If &amp;quot;target&amp;quot; is not found, then this&lt;br /&gt;
function returns 0.  If either &amp;quot;source&amp;quot; or &amp;quot;target&amp;quot; are missing / empty, this&lt;br /&gt;
function also returns 0.&lt;br /&gt;
&lt;br /&gt;
This function should be safe for UTF-8 strings.&lt;br /&gt;
]]&lt;br /&gt;
function str.find( frame )&lt;br /&gt;
	local new_args = str._getParameters( frame.args, {'source', 'target', 'start', 'plain' } )&lt;br /&gt;
	local source_str = new_args['source'] or ''&lt;br /&gt;
	local pattern = new_args['target'] or ''&lt;br /&gt;
	local start_pos = tonumber(new_args['start']) or 1&lt;br /&gt;
	local plain = new_args['plain'] or true&lt;br /&gt;
&lt;br /&gt;
	if source_str == '' or pattern == '' then&lt;br /&gt;
		return 0&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	plain = str._getBoolean( plain )&lt;br /&gt;
&lt;br /&gt;
	local start = mw.ustring.find( source_str, pattern, start_pos, plain )&lt;br /&gt;
	if start == nil then&lt;br /&gt;
		start = 0&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return start&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
replace&lt;br /&gt;
&lt;br /&gt;
This function allows one to replace a target string or pattern within another&lt;br /&gt;
string.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|replace|source_str|pattern_string|replace_string|replacement_count|plain_flag}}&lt;br /&gt;
OR&lt;br /&gt;
{{#invoke:String|replace|source=source_string|pattern=pattern_string|replace=replace_string|&lt;br /&gt;
   count=replacement_count|plain=plain_flag}}&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    source: The string to search&lt;br /&gt;
    pattern: The string or pattern to find within source&lt;br /&gt;
    replace: The replacement text&lt;br /&gt;
    count: The number of occurences to replace, defaults to all.&lt;br /&gt;
    plain: Boolean flag indicating that pattern should be understood as plain&lt;br /&gt;
        text and not as a Lua style regular expression, defaults to true&lt;br /&gt;
]]&lt;br /&gt;
function str.replace( frame )&lt;br /&gt;
	local new_args = str._getParameters( frame.args, {'source', 'pattern', 'replace', 'count', 'plain' } )&lt;br /&gt;
	local source_str = new_args['source'] or ''&lt;br /&gt;
	local pattern = new_args['pattern'] or ''&lt;br /&gt;
	local replace = new_args['replace'] or ''&lt;br /&gt;
	local count = tonumber( new_args['count'] )&lt;br /&gt;
	local plain = new_args['plain'] or true&lt;br /&gt;
&lt;br /&gt;
	if source_str == '' or pattern == '' then&lt;br /&gt;
		return source_str&lt;br /&gt;
	end&lt;br /&gt;
	plain = str._getBoolean( plain )&lt;br /&gt;
&lt;br /&gt;
	if plain then&lt;br /&gt;
		pattern = str._escapePattern( pattern )&lt;br /&gt;
		replace = mw.ustring.gsub( replace, &amp;quot;%%&amp;quot;, &amp;quot;%%%%&amp;quot; ) --Only need to escape replacement sequences.&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local result&lt;br /&gt;
&lt;br /&gt;
	if count ~= nil then&lt;br /&gt;
		result = mw.ustring.gsub( source_str, pattern, replace, count )&lt;br /&gt;
	else&lt;br /&gt;
		result = mw.ustring.gsub( source_str, pattern, replace )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
    simple function to pipe string.rep to templates.&lt;br /&gt;
]]&lt;br /&gt;
function str.rep( frame )&lt;br /&gt;
	local repetitions = tonumber( frame.args[2] )&lt;br /&gt;
	if not repetitions then&lt;br /&gt;
		return str._error( 'function rep expects a number as second parameter, received &amp;quot;' .. ( frame.args[2] or '' ) .. '&amp;quot;' )&lt;br /&gt;
	end&lt;br /&gt;
	return string.rep( frame.args[1] or '', repetitions )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
escapePattern&lt;br /&gt;
&lt;br /&gt;
This function escapes special characters from a Lua string pattern. See [1]&lt;br /&gt;
for details on how patterns work.&lt;br /&gt;
&lt;br /&gt;
[1] https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Patterns&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|escapePattern|pattern_string}}&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    pattern_string: The pattern string to escape.&lt;br /&gt;
]]&lt;br /&gt;
function str.escapePattern( frame )&lt;br /&gt;
	local pattern_str = frame.args[1]&lt;br /&gt;
	if not pattern_str then&lt;br /&gt;
		return str._error( 'No pattern string specified' )&lt;br /&gt;
	end&lt;br /&gt;
	local result = str._escapePattern( pattern_str )&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
count&lt;br /&gt;
This function counts the number of occurrences of one string in another.&lt;br /&gt;
]]&lt;br /&gt;
function str.count(frame)&lt;br /&gt;
	local args = str._getParameters(frame.args, {'source', 'pattern', 'plain'})&lt;br /&gt;
	local source = args.source or ''&lt;br /&gt;
	local pattern = args.pattern or ''&lt;br /&gt;
	local plain = str._getBoolean(args.plain or true)&lt;br /&gt;
	if plain then&lt;br /&gt;
		pattern = str._escapePattern(pattern)&lt;br /&gt;
	end&lt;br /&gt;
	local _, count = mw.ustring.gsub(source, pattern, '')&lt;br /&gt;
	return count&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
endswith&lt;br /&gt;
This function determines whether a string ends with another string.&lt;br /&gt;
]]&lt;br /&gt;
function str.endswith(frame)&lt;br /&gt;
	local args = str._getParameters(frame.args, {'source', 'pattern'})&lt;br /&gt;
	local source = args.source or ''&lt;br /&gt;
	local pattern = args.pattern or ''&lt;br /&gt;
	if pattern == '' then&lt;br /&gt;
		-- All strings end with the empty string.&lt;br /&gt;
		return &amp;quot;yes&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	if mw.ustring.sub(source, -mw.ustring.len(pattern), -1) == pattern then&lt;br /&gt;
		return &amp;quot;yes&amp;quot;&lt;br /&gt;
	else&lt;br /&gt;
		return &amp;quot;&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
join&lt;br /&gt;
&lt;br /&gt;
Join all non empty arguments together; the first argument is the separator.&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|join|sep|one|two|three}}&lt;br /&gt;
]]&lt;br /&gt;
function str.join(frame)&lt;br /&gt;
	local args = {}&lt;br /&gt;
	local sep&lt;br /&gt;
	for _, v in ipairs( frame.args ) do&lt;br /&gt;
		if sep then&lt;br /&gt;
			if v ~= '' then&lt;br /&gt;
				table.insert(args, v)&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			sep = v&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return table.concat( args, sep or '' )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Helper function that populates the argument list given that user may need to use a mix of&lt;br /&gt;
named and unnamed parameters.  This is relevant because named parameters are not&lt;br /&gt;
identical to unnamed parameters due to string trimming, and when dealing with strings&lt;br /&gt;
we sometimes want to either preserve or remove that whitespace depending on the application.&lt;br /&gt;
]]&lt;br /&gt;
function str._getParameters( frame_args, arg_list )&lt;br /&gt;
	local new_args = {}&lt;br /&gt;
	local index = 1&lt;br /&gt;
	local value&lt;br /&gt;
&lt;br /&gt;
	for _, arg in ipairs( arg_list ) do&lt;br /&gt;
		value = frame_args[arg]&lt;br /&gt;
		if value == nil then&lt;br /&gt;
			value = frame_args[index]&lt;br /&gt;
			index = index + 1&lt;br /&gt;
		end&lt;br /&gt;
		new_args[arg] = value&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return new_args&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Helper function to handle error messages.&lt;br /&gt;
]]&lt;br /&gt;
function str._error( error_str )&lt;br /&gt;
	local frame = mw.getCurrentFrame()&lt;br /&gt;
	local error_category = frame.args.error_category or 'Errors reported by Module String'&lt;br /&gt;
	local ignore_errors = frame.args.ignore_errors or false&lt;br /&gt;
	local no_category = frame.args.no_category or false&lt;br /&gt;
&lt;br /&gt;
	if str._getBoolean(ignore_errors) then&lt;br /&gt;
		return ''&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local error_str = '&amp;lt;strong class=&amp;quot;error&amp;quot;&amp;gt;String Module Error: ' .. error_str .. '&amp;lt;/strong&amp;gt;'&lt;br /&gt;
	if error_category ~= '' and not str._getBoolean( no_category ) then&lt;br /&gt;
		error_str = '[[Category:' .. error_category .. ']]' .. error_str&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return error_str&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Helper Function to interpret boolean strings&lt;br /&gt;
]]&lt;br /&gt;
function str._getBoolean( boolean_str )&lt;br /&gt;
	local boolean_value&lt;br /&gt;
&lt;br /&gt;
	if type( boolean_str ) == 'string' then&lt;br /&gt;
		boolean_str = boolean_str:lower()&lt;br /&gt;
		if boolean_str == 'false' or boolean_str == 'no' or boolean_str == '0'&lt;br /&gt;
				or boolean_str == '' then&lt;br /&gt;
			boolean_value = false&lt;br /&gt;
		else&lt;br /&gt;
			boolean_value = true&lt;br /&gt;
		end&lt;br /&gt;
	elseif type( boolean_str ) == 'boolean' then&lt;br /&gt;
		boolean_value = boolean_str&lt;br /&gt;
	else&lt;br /&gt;
		error( 'No boolean value found' )&lt;br /&gt;
	end&lt;br /&gt;
	return boolean_value&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Helper function that escapes all pattern characters so that they will be treated&lt;br /&gt;
as plain text.&lt;br /&gt;
]]&lt;br /&gt;
function str._escapePattern( pattern_str )&lt;br /&gt;
	return mw.ustring.gsub( pattern_str, &amp;quot;([%(%)%.%%%+%-%*%?%[%^%$%]])&amp;quot;, &amp;quot;%%%1&amp;quot; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return str&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Module:Row_numbers&amp;diff=161</id>
		<title>Module:Row numbers</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Module:Row_numbers&amp;diff=161"/>
		<updated>2021-09-26T15:44:22Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;require('Module:No globals');&lt;br /&gt;
&lt;br /&gt;
local count;&lt;br /&gt;
local hcount;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; G E T _ C O U N T &amp;gt;------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
returns a counter value according to the keyword extracted from the table; maintains count and hcount.  Inserts&lt;br /&gt;
a space character ahead of &amp;lt;count&amp;gt; or &amp;lt;hcount&amp;gt; so that, in the case of negative indexes, the negation operator &lt;br /&gt;
is not mistaken for part of the wikitable markup.  Returns:&lt;br /&gt;
	| -&amp;lt;count&amp;gt; – a cell value&lt;br /&gt;
instead of:&lt;br /&gt;
	|-&amp;lt;count&amp;gt; – row markup with extraneous text&lt;br /&gt;
&lt;br /&gt;
The keywords have the meanings:&lt;br /&gt;
	_row_count:			use row counter value (count); the hold counter (hcount) is same as count&lt;br /&gt;
	_row_count_hold:	use the value currently assigned to hcount; bump count but do not bump hcount&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function get_count (keyword)&lt;br /&gt;
	count = count + 1;															-- always bump the count&lt;br /&gt;
	if '_row_count' == keyword then												-- bump hcount, return new count value&lt;br /&gt;
		hcount = count;&lt;br /&gt;
		return ' ' .. count;													-- insert a leading space ahead of count&lt;br /&gt;
	elseif '_row_count_hold' == keyword then									-- current hcount value without increment&lt;br /&gt;
		return ' ' .. hcount;													-- insert a leading space ahead of hcount&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; R O W _ N U M B E R S &amp;gt;--------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
replaces keywords _row_count and _row_count_hold from the table in frame.args[1]&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function row_numbers (frame)&lt;br /&gt;
	if not frame.args[1]:match ('^%s*\127[^\127]*UNIQ%-%-nowiki%-%x%x%x%x%x%x%x%x%-QINU[^\127]*\127%s*$') then	-- make sure that what we get for input has been wrapped in &amp;lt;nowiki&amp;gt;...&amp;lt;/nowiki&amp;gt; tags&lt;br /&gt;
		return '&amp;lt;span style=\&amp;quot;font-size:100%; font-style:normal;\&amp;quot; class=\&amp;quot;error\&amp;quot;&amp;gt;error: missing nowiki tags&amp;lt;/span&amp;gt;';&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	count = (frame.args.index and frame.args.index:match ('^%d+$') or 1) - 1;	-- only if a number; |index= may be omitted (nil), or empty string, or non-digit; initial value is 0&lt;br /&gt;
&lt;br /&gt;
	local tbl_str = mw.text.unstripNoWiki (frame.args[1]);						-- get the table from the nowiki tags passed as arguments&lt;br /&gt;
&lt;br /&gt;
	tbl_str = tbl_str:gsub ('&amp;amp;lt;', '&amp;lt;');										-- undo &amp;lt;nowiki&amp;gt;'s escaping of the wikitext&lt;br /&gt;
	tbl_str = tbl_str:gsub ('&amp;amp;gt;', '&amp;gt;');										-- (mw.text.decode (tbl_str); is too aggressive)&lt;br /&gt;
&lt;br /&gt;
	return frame:preprocess (tbl_str:gsub('_row_count[_%w]*', get_count));		-- if there is at least one of our special reserved words, replace it with a count&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;
	row_numbers = row_numbers&lt;br /&gt;
	}&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Module:Yesno&amp;diff=159</id>
		<title>Module:Yesno</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Module:Yesno&amp;diff=159"/>
		<updated>2021-09-26T15:44:21Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- Function allowing for consistent treatment of boolean-like wikitext input.&lt;br /&gt;
-- It works similarly to the template {{yesno}}.&lt;br /&gt;
&lt;br /&gt;
return function (val, default)&lt;br /&gt;
	-- If your wiki uses non-ascii characters for any of &amp;quot;yes&amp;quot;, &amp;quot;no&amp;quot;, etc., you&lt;br /&gt;
	-- should replace &amp;quot;val:lower()&amp;quot; with &amp;quot;mw.ustring.lower(val)&amp;quot; in the&lt;br /&gt;
	-- following line.&lt;br /&gt;
	val = type(val) == 'string' and val:lower() or val&lt;br /&gt;
	if val == nil then&lt;br /&gt;
		return nil&lt;br /&gt;
	elseif val == true &lt;br /&gt;
		or val == 'yes'&lt;br /&gt;
		or val == 'y'&lt;br /&gt;
		or val == 'true'&lt;br /&gt;
		or val == 't'&lt;br /&gt;
		or val == 'on'&lt;br /&gt;
		or tonumber(val) == 1&lt;br /&gt;
	then&lt;br /&gt;
		return true&lt;br /&gt;
	elseif val == false&lt;br /&gt;
		or val == 'no'&lt;br /&gt;
		or val == 'n'&lt;br /&gt;
		or val == 'false'&lt;br /&gt;
		or val == 'f'&lt;br /&gt;
		or val == 'off'&lt;br /&gt;
		or tonumber(val) == 0&lt;br /&gt;
	then&lt;br /&gt;
		return false&lt;br /&gt;
	else&lt;br /&gt;
		return default&lt;br /&gt;
	end&lt;br /&gt;
end&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Module:Header&amp;diff=157</id>
		<title>Module:Header</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Module:Header&amp;diff=157"/>
		<updated>2021-09-26T15:44:21Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--[=[&lt;br /&gt;
This is a module to implement logic for the {{header}} template&lt;br /&gt;
&lt;br /&gt;
It doesn't do everything yet, but over time it can accrete functions from&lt;br /&gt;
the template, which will become simpler and simpler until it's just an invoke.&lt;br /&gt;
&lt;br /&gt;
Not implemented yet:&lt;br /&gt;
 * Categories (deprecated anyway)&lt;br /&gt;
 * Subpage checking&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local p = {} --p stands for package&lt;br /&gt;
&lt;br /&gt;
local yesno = require('Module:Yesno')&lt;br /&gt;
local getArgs = require('Module:Arguments').getArgs&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-- get the param_override or param parameter in that order&lt;br /&gt;
-- nil if neither is there&lt;br /&gt;
function get_arg_or_override(args, param)&lt;br /&gt;
	if args[&amp;quot;override_&amp;quot; .. param] then&lt;br /&gt;
		return args[&amp;quot;override_&amp;quot; .. param]&lt;br /&gt;
	elseif args[param] then&lt;br /&gt;
		return args[param]&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- return true if any value in list is nil in args&lt;br /&gt;
-- (nil means not present; empty string is not nil)&lt;br /&gt;
function any_arg_nil(args, list)&lt;br /&gt;
	for k,v in pairs(list) do&lt;br /&gt;
		if args[v] == nil 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;
-- return true if any value in list is not nil or empty in args&lt;br /&gt;
-- (nil means not present; empty string is not nil)&lt;br /&gt;
function has_any_arg(args, list)&lt;br /&gt;
	for k,v in pairs(list) do&lt;br /&gt;
		if args[v] ~= nil and args[v] ~= &amp;quot;&amp;quot; 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;
--[=[&lt;br /&gt;
Construct a warning if required parameters are missing&lt;br /&gt;
]=]&lt;br /&gt;
function p.missing_params_error(frame)&lt;br /&gt;
	local args = getArgs(frame, {&lt;br /&gt;
		removeBlanks = false&lt;br /&gt;
	})&lt;br /&gt;
	&lt;br /&gt;
	local s = &amp;quot;&amp;quot;&lt;br /&gt;
	&lt;br /&gt;
	local required_args = {'title', 'section', 'author', 'previous', 'next', 'notes'}&lt;br /&gt;
	if any_arg_nil(args, required_args) then&lt;br /&gt;
		local error_div = mw.html.create(&amp;quot;div&amp;quot;)&lt;br /&gt;
			:css({['margin-right'] = 'auto',&lt;br /&gt;
				['margin-left'] = 'auto',&lt;br /&gt;
				['border-top'] = '1px solid #CCC',&lt;br /&gt;
				['border-right']  = '1px solid #CCC',&lt;br /&gt;
				['border-bottom'] = '1px hidden transparent',&lt;br /&gt;
				['border-left'] = '1px solid #CCC',&lt;br /&gt;
				['text-align'] = 'center'&lt;br /&gt;
			})&lt;br /&gt;
			&lt;br /&gt;
		error_div:tag(&amp;quot;span&amp;quot;)&lt;br /&gt;
			:addClass(&amp;quot;error&amp;quot;)&lt;br /&gt;
			:css({&lt;br /&gt;
				['font-size'] = &amp;quot;90%&amp;quot;,&lt;br /&gt;
				['font-weight'] = &amp;quot;bold&amp;quot;,&lt;br /&gt;
			})&lt;br /&gt;
			:wikitext(&amp;quot;Template error: please do not remove empty parameters (see the [[WS:STYLE#Templates|style guide]] and [[Template:Header#documentation|template documentation]]).&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
		s = tostring(error_div)&lt;br /&gt;
		&lt;br /&gt;
		-- categorise only in mainspace&lt;br /&gt;
		if mw.title.getCurrentTitle().namespace == 0 then&lt;br /&gt;
			s = s .. &amp;quot;[[Category:Headers missing parameters]]&amp;quot;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return s&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Place each value from a table of IDs:values into the given parent element&lt;br /&gt;
function append_mf_values(parent, values)&lt;br /&gt;
	for k,v in pairs(values) do&lt;br /&gt;
		parent:tag(&amp;quot;span&amp;quot;)&lt;br /&gt;
			:attr(&amp;quot;id&amp;quot;, k)&lt;br /&gt;
			:wikitext(v)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Create the Microformat wrapper div&lt;br /&gt;
function construct_mf_wrapper(args)&lt;br /&gt;
	local mf_div =  mw.html.create(&amp;quot;div&amp;quot;)&lt;br /&gt;
	mf_div:addClass(&amp;quot;ws-noexport&amp;quot;)&lt;br /&gt;
	    :attr(&amp;quot;id&amp;quot;, &amp;quot;ws-data&amp;quot;)&lt;br /&gt;
		:css({&lt;br /&gt;
			speak = &amp;quot;none&amp;quot;&lt;br /&gt;
		})&lt;br /&gt;
	&lt;br /&gt;
	-- hide the microformat unless it's overriden&lt;br /&gt;
	if not (args[&amp;quot;show_microformat&amp;quot;] and yesno(args['show_microformat'])) then&lt;br /&gt;
		mf_div:css(&amp;quot;display&amp;quot;, &amp;quot;none&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	return mf_div&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Collect all the values of microformat data from the arguments provided&lt;br /&gt;
-- Returns a table of microformat ID:contents.&lt;br /&gt;
function collect_mf_data(args)&lt;br /&gt;
	-- collect the MF values here&lt;br /&gt;
	local mf = {};&lt;br /&gt;
&lt;br /&gt;
	mf[&amp;quot;ws-article-id&amp;quot;] = mw.title.getCurrentTitle().id &lt;br /&gt;
	&lt;br /&gt;
	-- add the title&lt;br /&gt;
	if args[&amp;quot;title&amp;quot;] then&lt;br /&gt;
		mf[&amp;quot;ws-title&amp;quot;] = args['title']&lt;br /&gt;
&lt;br /&gt;
		-- append section if there is one&lt;br /&gt;
		if args[&amp;quot;section&amp;quot;] then&lt;br /&gt;
			mf[&amp;quot;ws-title&amp;quot;] = mf[&amp;quot;ws-title&amp;quot;] .. &amp;quot; — &amp;quot; .. args[&amp;quot;section&amp;quot;]&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local author = get_arg_or_override(args, &amp;quot;contributor&amp;quot;)&lt;br /&gt;
	if not author then&lt;br /&gt;
		author = get_arg_or_override(args, &amp;quot;section_author&amp;quot;)	&lt;br /&gt;
	end&lt;br /&gt;
	if not author then&lt;br /&gt;
		author = get_arg_or_override(args, &amp;quot;author&amp;quot;)	&lt;br /&gt;
	end&lt;br /&gt;
	if author then&lt;br /&gt;
		mf['ws-author'] = author&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local translator = get_arg_or_override(args, &amp;quot;translator&amp;quot;)&lt;br /&gt;
	if translator then&lt;br /&gt;
		mf['ws-translator'] = translator&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local year = get_arg_or_override(args, &amp;quot;year&amp;quot;)&lt;br /&gt;
	if year then&lt;br /&gt;
		mf['ws-year'] = year&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if args['cover'] then&lt;br /&gt;
		mf['ws-cover'] = args['cover']	&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return mf&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[=[&lt;br /&gt;
Construct the [[Help:Microformat]] for the page.&lt;br /&gt;
&lt;br /&gt;
This is in the form:&lt;br /&gt;
&amp;lt;div id=&amp;quot;ws-data&amp;quot; ...&amp;gt;&lt;br /&gt;
  &amp;lt;span id=&amp;quot;ws-title&amp;quot;&amp;gt;Title here...&amp;lt;/span&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;div&amp;gt;&lt;br /&gt;
]=]&lt;br /&gt;
function p.microformat(frame)&lt;br /&gt;
	local args = getArgs(frame)&lt;br /&gt;
&lt;br /&gt;
	local mf_div =  construct_mf_wrapper(args)&lt;br /&gt;
	local mf = collect_mf_data(args)&lt;br /&gt;
&lt;br /&gt;
	append_mf_values(mf_div, mf)&lt;br /&gt;
	return tostring(mf_div)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function make_category_list(categories)&lt;br /&gt;
	local s = &amp;quot;&amp;quot;&lt;br /&gt;
	for k,v in pairs(categories) do&lt;br /&gt;
		s = s .. &amp;quot;[[Category:&amp;quot; .. v .. &amp;quot;]]\n&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	return s&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[=[&lt;br /&gt;
Detect illegal formatting in fields like &amp;quot;section&amp;quot; and &amp;quot;title&amp;quot;&lt;br /&gt;
]=]&lt;br /&gt;
function illegal_formatting(str)&lt;br /&gt;
	return string.match(str, &amp;quot;'''?&amp;quot;)&lt;br /&gt;
		or string.match(str, &amp;quot;&amp;lt;%s*/?%s*[iIbB]%s*&amp;gt;&amp;quot;)&lt;br /&gt;
		-- add more cases here&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function check_non_existent_author_pages(args, param, categories)&lt;br /&gt;
&lt;br /&gt;
	if args[param] then&lt;br /&gt;
		-- some pages expect an invalid author&lt;br /&gt;
		local special = false&lt;br /&gt;
		local lower_arg =  string.lower(args[param])&lt;br /&gt;
		if lower_arg == &amp;quot;unknown&amp;quot; or lower_arg == &amp;quot;not mentioned&amp;quot; then&lt;br /&gt;
			special = true&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		if not special then&lt;br /&gt;
			local target = mw.title.makeTitle(&amp;quot;Author&amp;quot;, args[param])&lt;br /&gt;
			-- expensive function!&lt;br /&gt;
			if not target.exists then&lt;br /&gt;
				table.insert(categories, &amp;quot;Works with non-existent author pages&amp;quot;)&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;
Construct the automatic categories for the header&lt;br /&gt;
]=]&lt;br /&gt;
function p.categories(frame)&lt;br /&gt;
	local args = getArgs(frame)&lt;br /&gt;
	&lt;br /&gt;
	local categories = {}&lt;br /&gt;
	local this_page = mw.title.getCurrentTitle();&lt;br /&gt;
&lt;br /&gt;
	if args[&amp;quot;override_author&amp;quot;] then&lt;br /&gt;
		table.insert(categories, &amp;quot;Pages with override author&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if this_page:inNamespaces(0, 114) then&lt;br /&gt;
		check_non_existent_author_pages(args, &amp;quot;author&amp;quot;, categories)&lt;br /&gt;
		check_non_existent_author_pages(args, &amp;quot;editor&amp;quot;, categories)&lt;br /&gt;
		check_non_existent_author_pages(args, &amp;quot;translator&amp;quot;, categories)&lt;br /&gt;
		check_non_existent_author_pages(args, &amp;quot;section_translator&amp;quot;, categories)&lt;br /&gt;
		check_non_existent_author_pages(args, &amp;quot;section_author&amp;quot;, categories)&lt;br /&gt;
		check_non_existent_author_pages(args, &amp;quot;contributor&amp;quot;, categories)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if args[&amp;quot;contributor&amp;quot;] or args[&amp;quot;section_author&amp;quot;] then&lt;br /&gt;
		table.insert(categories, &amp;quot;Pages with contributor&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if args[&amp;quot;override_contributor&amp;quot;] or args[&amp;quot;override_section_author&amp;quot;] then&lt;br /&gt;
		table.insert(categories, &amp;quot;Pages with override contributor&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local author = get_arg_or_override(args, &amp;quot;author&amp;quot;)&lt;br /&gt;
	if author and (string.lower(author) == &amp;quot;unknown&amp;quot;) then&lt;br /&gt;
		table.insert(categories, &amp;quot;Anonymous texts&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local editor = get_arg_or_override(args, &amp;quot;editor&amp;quot;)&lt;br /&gt;
	if editor then&lt;br /&gt;
		editor = string.lower(editor)&lt;br /&gt;
		if editor == &amp;quot;unknown&amp;quot; or editor == &amp;quot;?&amp;quot; then&lt;br /&gt;
			table.insert(categories, &amp;quot;Works with unknown editors&amp;quot;)&lt;br /&gt;
		elseif editor == &amp;quot;not mentioned&amp;quot; then&lt;br /&gt;
			table.insert(categories, &amp;quot;Works with unmentioned editors&amp;quot;)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local translator = get_arg_or_override(args, &amp;quot;translator&amp;quot;)&lt;br /&gt;
	if translator then&lt;br /&gt;
		translator = string.lower(translator)&lt;br /&gt;
		if translator == &amp;quot;unknown&amp;quot; or translator == &amp;quot;not mentioned&amp;quot; or translator == &amp;quot;?&amp;quot; then&lt;br /&gt;
			table.insert(categories, &amp;quot;Translations without translator information specified&amp;quot;)&lt;br /&gt;
		elseif translator == &amp;quot;wikisource&amp;quot; and (this_page.baseText == this_page.text) then&lt;br /&gt;
			-- if a basepage&lt;br /&gt;
			-- ?? why is this not done by {{translation}} ??&lt;br /&gt;
			table.insert(categories, &amp;quot;Wikisource translations&amp;quot;)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if args[&amp;quot;shortcut&amp;quot;] then&lt;br /&gt;
		table.insert(categories, &amp;quot;Mainspace pages with shortcuts&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if args[&amp;quot;override_year&amp;quot;] then&lt;br /&gt;
		table.insert(categories, &amp;quot;pages with override year&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	if args[&amp;quot;noyear&amp;quot;] then&lt;br /&gt;
		table.insert(categories, &amp;quot;pages with noyear&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	if args[&amp;quot;noyearcat&amp;quot;] then&lt;br /&gt;
		table.insert(categories, &amp;quot;pages with noyearcat&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if args[&amp;quot;cover&amp;quot;] then&lt;br /&gt;
		table.insert(categories, &amp;quot;Pages with an export cover&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- sanity/maintenance checks on various parameters&lt;br /&gt;
	&lt;br /&gt;
	-- allow_illegal_formatting parameter suppresses this check&lt;br /&gt;
	-- used by, for example, [[Template:Versions]]&lt;br /&gt;
	if args[&amp;quot;allow_illegal_formatting&amp;quot;] == nil then&lt;br /&gt;
&lt;br /&gt;
		if args[&amp;quot;title&amp;quot;] and illegal_formatting(args['title']) then&lt;br /&gt;
			table.insert(categories, &amp;quot;pages with illegal formatting in header fields&amp;quot;)&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		if args[&amp;quot;section&amp;quot;] and illegal_formatting(args['section']) then&lt;br /&gt;
			table.insert(categories, &amp;quot;pages with illegal formatting in header fields&amp;quot;)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return make_category_list(categories)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function get_plain_sister(frame, args, sister_args)&lt;br /&gt;
	local ps_args = {}&lt;br /&gt;
	for k,v in pairs(sister_args) do&lt;br /&gt;
		if args[v] then&lt;br /&gt;
			ps_args[v] = args[v]&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return frame:expandTemplate{title = &amp;quot;plain sister&amp;quot;, args = ps_args}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[=[&lt;br /&gt;
Return the title span&lt;br /&gt;
&lt;br /&gt;
&amp;gt; &lt;br /&gt;
--]=]&lt;br /&gt;
function construct_title(args)&lt;br /&gt;
	local title = mw.html.create(&amp;quot;span&amp;quot;)&lt;br /&gt;
		:attr(&amp;quot;id&amp;quot;, &amp;quot;header_title_text&amp;quot;)&lt;br /&gt;
		:css({&lt;br /&gt;
			[&amp;quot;font-weight&amp;quot;] = &amp;quot;bold&amp;quot;,&lt;br /&gt;
		})&lt;br /&gt;
		&lt;br /&gt;
	if args[&amp;quot;title&amp;quot;] then&lt;br /&gt;
		title:wikitext(args[&amp;quot;title&amp;quot;])&lt;br /&gt;
	else&lt;br /&gt;
		title:wikitext(&amp;quot;Untitled&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	return title&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[=[&lt;br /&gt;
Construct the title field&lt;br /&gt;
]=]&lt;br /&gt;
function p.title(frame)&lt;br /&gt;
	local args = getArgs(frame)&lt;br /&gt;
&lt;br /&gt;
	local title = construct_title(args)&lt;br /&gt;
	return tostring(title)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[=[&lt;br /&gt;
Construct the year span&lt;br /&gt;
--]=]&lt;br /&gt;
function construct_year(frame, args)&lt;br /&gt;
&lt;br /&gt;
	local year = mw.html.create(&amp;quot;span&amp;quot;)&lt;br /&gt;
		:attr(&amp;quot;id&amp;quot;, &amp;quot;header_year_text&amp;quot;)&lt;br /&gt;
		&lt;br /&gt;
	if args[&amp;quot;year_override&amp;quot;] then&lt;br /&gt;
		year:wikitext(args[&amp;quot;year_override&amp;quot;])&lt;br /&gt;
	else&lt;br /&gt;
		local year_args = {&lt;br /&gt;
			[1] = args[&amp;quot;year&amp;quot;],&lt;br /&gt;
			noprint = &amp;quot;0&amp;quot;,&lt;br /&gt;
			nocat = &amp;quot;0&amp;quot;,&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		if args[&amp;quot;noyear&amp;quot;] then&lt;br /&gt;
			year_args['noprint'] = &amp;quot;1&amp;quot;&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		if args[&amp;quot;disambiguation&amp;quot;] and yesno(args['disambiguation']) then&lt;br /&gt;
			-- disambiguations never categorise&lt;br /&gt;
			year_args['nocat'] = &amp;quot;1&amp;quot;&lt;br /&gt;
		else&lt;br /&gt;
			if args[&amp;quot;noyearcat&amp;quot;] and yesno(args['noyearcat']) then&lt;br /&gt;
				-- manually no-catted&lt;br /&gt;
				year_args['nocat'] = &amp;quot;1&amp;quot;&lt;br /&gt;
			elseif mw.title.getCurrentTitle().isSubpage then&lt;br /&gt;
				-- only categorise if this is a base page&lt;br /&gt;
				year_args['nocat'] = &amp;quot;1&amp;quot;&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		mw.logObject(year_args)&lt;br /&gt;
		year:wikitext(mw.text.trim(frame:expandTemplate{&lt;br /&gt;
			title = &amp;quot;header/year&amp;quot;,&lt;br /&gt;
			args  = year_args&lt;br /&gt;
		}))&lt;br /&gt;
	end&lt;br /&gt;
	return year&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[=[&lt;br /&gt;
Construct the year field&lt;br /&gt;
]=]	&lt;br /&gt;
function p.year(frame)&lt;br /&gt;
	local args = getArgs(frame)&lt;br /&gt;
&lt;br /&gt;
	ret = &amp;quot;&amp;quot;&lt;br /&gt;
	if get_arg_or_override(args, &amp;quot;year&amp;quot;) then&lt;br /&gt;
		ret = tostring(construct_year(frame, args))&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function create_vcard(id, content, wrap_fn)&lt;br /&gt;
	local span = mw.html.create(&amp;quot;span&amp;quot;)&lt;br /&gt;
		:addClass(&amp;quot;vcard&amp;quot;)&lt;br /&gt;
		:css({&lt;br /&gt;
			['font-style'] = 'italic'&lt;br /&gt;
		})&lt;br /&gt;
		:attr(&amp;quot;id&amp;quot;, id)&lt;br /&gt;
	&lt;br /&gt;
	if wrap_fn then&lt;br /&gt;
		span:tag(&amp;quot;span&amp;quot;)&lt;br /&gt;
			:addClass(&amp;quot;fn&amp;quot;)&lt;br /&gt;
			:wikitext(content)&lt;br /&gt;
	else&lt;br /&gt;
		span:wikitext(content)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return span&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.author(frame)&lt;br /&gt;
	local args = getArgs(frame)&lt;br /&gt;
	&lt;br /&gt;
	local param_name = &amp;quot;author&amp;quot;&lt;br /&gt;
	local prefix = &amp;quot;by&amp;quot;&lt;br /&gt;
	local id = &amp;quot;header_author_text&amp;quot;&lt;br /&gt;
&lt;br /&gt;
	local s = &amp;quot;&amp;quot;&lt;br /&gt;
	local atext;&lt;br /&gt;
	&lt;br /&gt;
	local wrap_fn = true&lt;br /&gt;
&lt;br /&gt;
	if args[&amp;quot;override_&amp;quot; .. param_name] then&lt;br /&gt;
		s = s .. &amp;quot;&amp;lt;br/&amp;gt;&amp;quot;&lt;br /&gt;
		atext = args[&amp;quot;override_&amp;quot; .. param_name]&lt;br /&gt;
	elseif args[param_name] then&lt;br /&gt;
		if args['section'] then&lt;br /&gt;
			s = s .. &amp;quot;&amp;amp;#32;&amp;quot;&lt;br /&gt;
		else&lt;br /&gt;
			s = s .. &amp;quot;&amp;lt;br/&amp;gt;&amp;quot;&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		if string.lower(args[param_name]) == &amp;quot;unknown&amp;quot; then&lt;br /&gt;
			atext = &amp;quot;Unknown&amp;quot;&lt;br /&gt;
			wrap_fn = false&lt;br /&gt;
		else&lt;br /&gt;
			atext = &amp;quot;[[Author:&amp;quot; .. args[param_name] .. &amp;quot;|&amp;quot; .. args[param_name] .. &amp;quot;]]&amp;quot;&lt;br /&gt;
		end&lt;br /&gt;
 		&lt;br /&gt;
		s = s .. &amp;quot;&amp;lt;i&amp;gt;&amp;quot; .. prefix .. &amp;quot;&amp;lt;/i&amp;gt;&amp;quot; .. &amp;quot; &amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local a_span = create_vcard(id, atext, wrap_fn)&lt;br /&gt;
	return s .. tostring(a_span)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function p.editor(frame)&lt;br /&gt;
	local args = getArgs(frame)&lt;br /&gt;
&lt;br /&gt;
	local ed = get_arg_or_override(args, &amp;quot;editor&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
	-- no editors&lt;br /&gt;
	if ed == nil then&lt;br /&gt;
		return &amp;quot;&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local have_authors = get_arg_or_override(args, &amp;quot;author&amp;quot;) ~= nil&lt;br /&gt;
&lt;br /&gt;
	local s = &amp;quot; &amp;quot;&lt;br /&gt;
	if have_authors then&lt;br /&gt;
		s = &amp;quot;, &amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if not have_authors and not args[&amp;quot;section&amp;quot;] then&lt;br /&gt;
		s = s .. &amp;quot;&amp;lt;br/&amp;gt;&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- need to tidy this up and check for override_editor = unknown|not mentioned|?&lt;br /&gt;
	local special&lt;br /&gt;
	if ed == &amp;quot;?&amp;quot; or string.lower(ed) == &amp;quot;unknown&amp;quot; then&lt;br /&gt;
		special = &amp;quot;editor unknown&amp;quot;&lt;br /&gt;
	elseif string.lower(ed) == &amp;quot;not mentioned&amp;quot; then&lt;br /&gt;
		special = &amp;quot;editor not mentioned&amp;quot;&lt;br /&gt;
	elseif ed ~= nil then&lt;br /&gt;
		s = s .. &amp;quot;edited by&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	s = &amp;quot;&amp;lt;i&amp;gt;&amp;quot; .. s .. &amp;quot;&amp;lt;/i&amp;gt; &amp;quot;&lt;br /&gt;
&lt;br /&gt;
	local etext&lt;br /&gt;
	local wrap_fn = true&lt;br /&gt;
	if args[&amp;quot;override_editor&amp;quot;] then&lt;br /&gt;
		etext = args[&amp;quot;override_editor&amp;quot;]&lt;br /&gt;
	elseif args[&amp;quot;editor&amp;quot;] then&lt;br /&gt;
&lt;br /&gt;
		if special then&lt;br /&gt;
			etext = special&lt;br /&gt;
			wrap_fn = false&lt;br /&gt;
		else&lt;br /&gt;
			etext = &amp;quot;[[Author:&amp;quot; .. args[&amp;quot;editor&amp;quot;] .. &amp;quot;|&amp;quot; .. args[&amp;quot;editor&amp;quot;] .. &amp;quot;]]&amp;quot;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local span = create_vcard(&amp;quot;header_editor_text&amp;quot;, etext, true)&lt;br /&gt;
	return s .. tostring(span)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.translator(frame)&lt;br /&gt;
	local args = getArgs(frame)&lt;br /&gt;
&lt;br /&gt;
	local tr = get_arg_or_override(args, &amp;quot;translator&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
	-- no translator&lt;br /&gt;
	if tr == nil then&lt;br /&gt;
		return &amp;quot;&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local have_authors = get_arg_or_override(args, &amp;quot;author&amp;quot;) ~= nil&lt;br /&gt;
	local have_editors = get_arg_or_override(args, &amp;quot;editor&amp;quot;) ~= nil&lt;br /&gt;
&lt;br /&gt;
	local s = &amp;quot; &amp;quot;&lt;br /&gt;
	if have_authors or have_editors then&lt;br /&gt;
		s = &amp;quot;, &amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if not have_authors and not have_authors and args[&amp;quot;section&amp;quot;] == nil then&lt;br /&gt;
		s = s .. &amp;quot;&amp;lt;br/&amp;gt;&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local special&lt;br /&gt;
	if tr == &amp;quot;?&amp;quot; or string.lower(tr) == &amp;quot;unknown&amp;quot; then&lt;br /&gt;
		special = &amp;quot;translator unknown&amp;quot;&lt;br /&gt;
	elseif string.lower(tr) == &amp;quot;not mentioned&amp;quot; then&lt;br /&gt;
		special = &amp;quot;translator not mentioned&amp;quot;&lt;br /&gt;
	elseif string.lower(tr) == &amp;quot;wikisource&amp;quot; then&lt;br /&gt;
		special = &amp;quot;translated by [[Wikisource:Translations|&amp;lt;span id=\&amp;quot;header_translator_text\&amp;quot;&amp;gt;Wikisource&amp;lt;/span&amp;gt;]]&amp;quot;&lt;br /&gt;
	elseif tr ~= nil then&lt;br /&gt;
		s = s .. &amp;quot;translated by&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	s = &amp;quot;&amp;lt;i&amp;gt;&amp;quot; .. s .. &amp;quot;&amp;lt;/i&amp;gt; &amp;quot;&lt;br /&gt;
&lt;br /&gt;
	local etext&lt;br /&gt;
	local wrap_fn = true&lt;br /&gt;
	if args[&amp;quot;override_translator&amp;quot;] then&lt;br /&gt;
		etext = args[&amp;quot;override_translator&amp;quot;]&lt;br /&gt;
	elseif args[&amp;quot;translator&amp;quot;] then&lt;br /&gt;
&lt;br /&gt;
		if special then&lt;br /&gt;
			etext = special&lt;br /&gt;
			wrap_fn = false&lt;br /&gt;
		else&lt;br /&gt;
			etext = &amp;quot;[[Author:&amp;quot; .. args[&amp;quot;translator&amp;quot;] .. &amp;quot;|&amp;quot; .. args[&amp;quot;translator&amp;quot;] .. &amp;quot;]]&amp;quot;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local span = create_vcard(&amp;quot;header_translator_text&amp;quot;, etext, true)&lt;br /&gt;
	return s .. tostring(span)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.section(frame)&lt;br /&gt;
	local args = getArgs(frame)&lt;br /&gt;
	&lt;br /&gt;
	if not args[&amp;quot;section&amp;quot;] then&lt;br /&gt;
		return&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local s = &amp;quot;&amp;lt;br /&amp;gt;&amp;lt;span id=\&amp;quot;header_section_text\&amp;quot;&amp;gt;&amp;quot; .. args[&amp;quot;section&amp;quot;] .. &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
	-- there are synonyms for this&lt;br /&gt;
	local trans = get_arg_or_override(args, &amp;quot;section_translator&amp;quot;)&lt;br /&gt;
	if trans == nil then&lt;br /&gt;
		trans = get_arg_or_override(args, &amp;quot;contributing_translator&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- there are synonyms for this&lt;br /&gt;
	local sec_author = get_arg_or_override(args, &amp;quot;section_author&amp;quot;)&lt;br /&gt;
	if sec_author == nil then&lt;br /&gt;
		sec_author = get_arg_or_override(args, &amp;quot;contributor&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- first part of section_translator, adds a line return to split to two lines due to length if section translator exists	&lt;br /&gt;
	if trans and sec_author then&lt;br /&gt;
		s = s .. &amp;quot;&amp;lt;br/&amp;gt;&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if sec_author then&lt;br /&gt;
		s = s .. &amp;quot;&amp;lt;i&amp;gt; by &amp;lt;span id=\&amp;quot;header_contributor_text\&amp;quot; class=\&amp;quot;vcard\&amp;quot;&amp;gt;&amp;quot;&lt;br /&gt;
		s = s .. &amp;quot;&amp;lt;span class=\&amp;quot;fn\&amp;quot;&amp;gt;&amp;quot;&lt;br /&gt;
		&lt;br /&gt;
		if args[&amp;quot;override_section_author&amp;quot;] then&lt;br /&gt;
			s = s .. args[&amp;quot;override_section_author&amp;quot;]&lt;br /&gt;
		elseif args[&amp;quot;override_contributor&amp;quot;] then&lt;br /&gt;
			s = s .. args[&amp;quot;override_contributor&amp;quot;]&lt;br /&gt;
		else&lt;br /&gt;
			s = s .. &amp;quot;[[Author:&amp;quot; .. sec_author .. &amp;quot;|&amp;quot; .. sec_author .. &amp;quot;]]&amp;quot;&lt;br /&gt;
		end&lt;br /&gt;
		s = s .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/i&amp;gt;&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if trans then&lt;br /&gt;
		if sec_author then&lt;br /&gt;
			s = s .. &amp;quot;,&amp;quot;	&lt;br /&gt;
		end&lt;br /&gt;
		s = s .. &amp;quot; &amp;lt;i&amp;gt;translated by &amp;lt;span id=\&amp;quot;header_section_translator_text\&amp;quot; class=\&amp;quot;vcard\&amp;quot;&amp;gt;&amp;quot;&lt;br /&gt;
		&lt;br /&gt;
		if args[&amp;quot;override_section_translator&amp;quot;] then&lt;br /&gt;
			s = s .. args['override_section_translator']&lt;br /&gt;
		else&lt;br /&gt;
			s = s .. &amp;quot;[[Author:&amp;quot; .. trans .. &amp;quot;|&amp;quot; .. trans .. &amp;quot;]]&amp;quot;&lt;br /&gt;
		end&lt;br /&gt;
		s = s .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/i&amp;gt;&amp;quot;		&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return s&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[=[&lt;br /&gt;
Construct the notes field&lt;br /&gt;
]=]&lt;br /&gt;
function p.notes(frame)&lt;br /&gt;
	local args = getArgs(frame)&lt;br /&gt;
	&lt;br /&gt;
	local notes_args = {&lt;br /&gt;
		style = &amp;quot;border-bottom: 1px solid #A0A0A0; background-color: #FAFAFF;&amp;quot;,&lt;br /&gt;
		id = navigationNotes&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	local wdid = mw.wikibase.getEntityIdForCurrentPage()&lt;br /&gt;
	local sister_args = {&amp;quot;disambiguation&amp;quot;, &amp;quot;edition&amp;quot;, &amp;quot;portal&amp;quot;, &amp;quot;related_author&amp;quot;,&lt;br /&gt;
		&amp;quot;wikipedia&amp;quot;, &amp;quot;commons&amp;quot;, &amp;quot;commonscat&amp;quot;, &amp;quot;wikiquote&amp;quot;, &amp;quot;wikinews&amp;quot;, &lt;br /&gt;
		&amp;quot;wiktionary&amp;quot;, &amp;quot;wikibooks&amp;quot;,  &amp;quot;wikidata&amp;quot;, &amp;quot;wikivoyage&amp;quot;, &lt;br /&gt;
		&amp;quot;wikiversity&amp;quot;, &amp;quot;wikispecies&amp;quot;, &amp;quot;meta&amp;quot;}&lt;br /&gt;
	local sisters = &amp;quot;&amp;quot;&lt;br /&gt;
	if wdid ~= nil or has_any_arg(args, sister_args) then&lt;br /&gt;
		notes_args['sister'] = (get_plain_sister(frame, args, sister_args))&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
    -- TODO: Temporarily track pages sisterlinking to Wikilivres.&lt;br /&gt;
    if args[&amp;quot;wikilivres&amp;quot;] ~= nil and args[&amp;quot;wikilivres&amp;quot;] ~= &amp;quot;&amp;quot; then&lt;br /&gt;
        table.insert(categories, &amp;quot;Pages using header with sister links to Wikilivres&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
	if args[&amp;quot;shortcut&amp;quot;] then&lt;br /&gt;
		notes_args['shortcut'] = args[&amp;quot;shortcut&amp;quot;]&lt;br /&gt;
	end&lt;br /&gt;
		&lt;br /&gt;
	if args[&amp;quot;notes&amp;quot;] then&lt;br /&gt;
		notes_args['content'] = args['notes'] &lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return frame:expandTemplate{title = &amp;quot;header/notes block&amp;quot;, args = notes_args}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Module:Edition&amp;diff=155</id>
		<title>Module:Edition</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Module:Edition&amp;diff=155"/>
		<updated>2021-09-26T15:44:20Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--------------------------------------------------------------------------------&lt;br /&gt;
-- Organisation of this module: the exports are listed at the bottom; their&lt;br /&gt;
-- direct functions are just above there, and supporting functions are higher&lt;br /&gt;
-- up.&lt;br /&gt;
--&lt;br /&gt;
-- Please add testcases before modifying anything.&lt;br /&gt;
--&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
instanceOfProp = 'P31'&lt;br /&gt;
authorProp = 'P50'&lt;br /&gt;
editionOrTranslationOfProp = 'P629'&lt;br /&gt;
equivalentClassProp = 'P1709'&lt;br /&gt;
topicsMainWikimediaPortalProp = 'P1151';&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Insert a value into a table, but not if it's already there.&lt;br /&gt;
function tableInsertUnique( theTable, value )&lt;br /&gt;
	for _, item in pairs( theTable ) do&lt;br /&gt;
		if item == value then&lt;br /&gt;
			-- Already present&lt;br /&gt;
			return&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	-- Otherwise, add the new value.&lt;br /&gt;
	table.insert( theTable, value )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- For the given author item, find the Wikisource sitelink. If there isn't one,&lt;br /&gt;
-- check to see if there the author has a topicsMainWikimediaPortal statement,&lt;br /&gt;
-- and then see if that portal has a sitelink instead.&lt;br /&gt;
function get_author_sitelink( authorItem )&lt;br /&gt;
	local siteLink = authorItem:getSitelink( mw.language.getContentLanguage().code .. 'wikisource' )&lt;br /&gt;
	if ( siteLink ~= nil ) then&lt;br /&gt;
		return siteLink&lt;br /&gt;
	end&lt;br /&gt;
	portalStatements = authorItem:getBestStatements( topicsMainWikimediaPortalProp )&lt;br /&gt;
	for _, mainPortal in pairs( portalStatements ) do&lt;br /&gt;
		local mainPortalId = mainPortal['mainsnak']['datavalue']['value']['id']&lt;br /&gt;
		local mainPortalItem = mw.wikibase.getEntity( mainPortalId )&lt;br /&gt;
		siteLink = mainPortalItem:getSitelink( mw.language.getContentLanguage().code .. 'wikisource' )&lt;br /&gt;
	end&lt;br /&gt;
	return siteLink&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Create the HTML (including wikitext link) for all provided authors,&lt;br /&gt;
-- and add it to the given authorLinks table (for later concatenation).&lt;br /&gt;
function process_authors( authorLinks, authors )&lt;br /&gt;
	if authors == nil or #authors == 0 then&lt;br /&gt;
		return&lt;br /&gt;
	end&lt;br /&gt;
	for _, author in pairs( authors ) do&lt;br /&gt;
		local authorId = author['mainsnak']['datavalue']['value']['id']&lt;br /&gt;
		local authorItem =  mw.wikibase.getEntity( authorId )&lt;br /&gt;
		local siteLink = get_author_sitelink( authorItem )&lt;br /&gt;
		local authorName = authorItem:getLabel()&lt;br /&gt;
		if siteLink ~= nil then&lt;br /&gt;
			authorName = mw.title.new( siteLink ).text&lt;br /&gt;
		end&lt;br /&gt;
		local authorHtml = mw.html.create('span')&lt;br /&gt;
			:attr('itemprop', 'author')&lt;br /&gt;
			:attr('itemscope', '')&lt;br /&gt;
			:attr('itemtype', getSchemaorgItemtype( authorItem ) )&lt;br /&gt;
		local authorNameHtml = authorHtml:tag( 'span' )&lt;br /&gt;
		authorNameHtml:attr( 'itemprop', 'name' )&lt;br /&gt;
			:wikitext( authorName )&lt;br /&gt;
		local authorHtmlStr = tostring( authorHtml )&lt;br /&gt;
		if siteLink == nil then&lt;br /&gt;
			tableInsertUnique( authorLinks, authorHtmlStr )&lt;br /&gt;
		else&lt;br /&gt;
			tableInsertUnique( authorLinks, '[[' .. siteLink .. '|' .. authorHtmlStr .. ']]' )&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Get the schema.org URL for the itemtype of the given item.&lt;br /&gt;
function getSchemaorgItemtype( item )&lt;br /&gt;
	local schemaPrefix = 'http://schema.org/'&lt;br /&gt;
	for _, instanceOf in pairs( item:getBestStatements( instanceOfProp ) ) do&lt;br /&gt;
		local instanceOfId = instanceOf['mainsnak']['datavalue']['value']['id']&lt;br /&gt;
		local instanceOfItem = mw.wikibase.getEntity( instanceOfId )&lt;br /&gt;
		-- Now go through each of the instance-of item's class statements,&lt;br /&gt;
		-- seeing if we can find a matching schema.org URL.&lt;br /&gt;
		for _, equivClass in pairs( instanceOfItem:getBestStatements( equivalentClassProp ) ) do&lt;br /&gt;
			local val = equivClass['mainsnak']['datavalue']['value']&lt;br /&gt;
			if string.sub( val, 1, #schemaPrefix ) == schemaPrefix then&lt;br /&gt;
				-- This is a schema.org URL.&lt;br /&gt;
				return val&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	-- If we've not figured it out by now, give up with the default.&lt;br /&gt;
	return schemaPrefix .. 'Thing'&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Exported method.&lt;br /&gt;
--&lt;br /&gt;
function author_list( args )&lt;br /&gt;
	local item = getItem( args )&lt;br /&gt;
	if item == nil then&lt;br /&gt;
		return ''&lt;br /&gt;
	end&lt;br /&gt;
	local authorLinks = {}&lt;br /&gt;
&lt;br /&gt;
	-- Collect the authors of this item.&lt;br /&gt;
	local authors = item:getBestStatements( authorProp )&lt;br /&gt;
	process_authors( authorLinks, authors )&lt;br /&gt;
&lt;br /&gt;
	-- Also collect the authors of the parent work.&lt;br /&gt;
	local works = item:getBestStatements( editionOrTranslationOfProp )&lt;br /&gt;
	for _, work in pairs( works ) do&lt;br /&gt;
		local workId = work['mainsnak']['datavalue']['value']['id']&lt;br /&gt;
		local workItem = mw.wikibase.getEntity( workId )&lt;br /&gt;
		authors = workItem:getBestStatements( authorProp )&lt;br /&gt;
		if #authors &amp;gt; 0 then&lt;br /&gt;
			process_authors( authorLinks, authors )&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Output the final list of links.&lt;br /&gt;
	local outHtml = mw.html.create()&lt;br /&gt;
	local separator = args.separator or ', '&lt;br /&gt;
	local last_separator = args.last_separator or ', and '&lt;br /&gt;
	local i = 1&lt;br /&gt;
	for _, link in pairs( authorLinks ) do&lt;br /&gt;
		outHtml:wikitext( link )&lt;br /&gt;
		if i == ( #authorLinks - 1 ) then&lt;br /&gt;
			outHtml:wikitext( last_separator )&lt;br /&gt;
		elseif #authorLinks &amp;gt; 1 and i ~= #authorLinks then&lt;br /&gt;
			outHtml:wikitext( separator )&lt;br /&gt;
		end&lt;br /&gt;
		i = i + 1&lt;br /&gt;
	end&lt;br /&gt;
	return tostring( outHtml )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Exported method.&lt;br /&gt;
--&lt;br /&gt;
function inline( args )&lt;br /&gt;
	local item = getItem( args )&lt;br /&gt;
	local outHtml = mw.html.create()&lt;br /&gt;
	mw.logObject(args)&lt;br /&gt;
	mw.logObject(item)&lt;br /&gt;
	if ( item == nil ) then&lt;br /&gt;
		outHtml:wikitext( '&amp;lt;span class=&amp;quot;error&amp;quot;&amp;gt;Unable to determine the Wikidata item to use&amp;lt;/span&amp;gt;' )&lt;br /&gt;
		return tostring( outHtml )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Make sure it's an edition.&lt;br /&gt;
	local editionOrTranslationOfStmts = item:getBestStatements( editionOrTranslationOfProp )&lt;br /&gt;
	if #editionOrTranslationOfStmts == 0 then&lt;br /&gt;
		outHtml:wikitext( '&amp;lt;span class=&amp;quot;error&amp;quot;&amp;gt;' .. item.id .. ' is not an edition or translation of a work (missing P629)&amp;lt;/span&amp;gt;' )&lt;br /&gt;
		return tostring( outHtml )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	-- Title/label.&lt;br /&gt;
	local title = item:getSitelink( 'enwikisource' )&lt;br /&gt;
	local label = item:getLabel( 'en' )&lt;br /&gt;
	local hasWikisourcePage = false&lt;br /&gt;
	if title == nil or title == '' then&lt;br /&gt;
		title = label&lt;br /&gt;
	else&lt;br /&gt;
		hasWikisourcePage = true&lt;br /&gt;
		title = '[[' .. title .. '|' .. label .. ']]'&lt;br /&gt;
	end&lt;br /&gt;
	outHtml:wikitext( title .. ' ' );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	-- Publication date&lt;br /&gt;
	local publicationDate = item:formatPropertyValues( 'P577' )&lt;br /&gt;
	outHtml:wikitext( '(' .. publicationDate.value .. ') ' )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	-- Scanned file on Wikimedia Commons.&lt;br /&gt;
	if not hasWikisourcePage then&lt;br /&gt;
		-- Add links to Index page or Commons file.&lt;br /&gt;
		local hasIndexOrCommonsLink = false&lt;br /&gt;
		local scannedFileOnWikimediaCommons = 'P996'&lt;br /&gt;
		local scannedFileOnWikimediaCommonsStmts = item:getBestStatements( scannedFileOnWikimediaCommons )&lt;br /&gt;
		for _, stmt in pairs( scannedFileOnWikimediaCommonsStmts ) do&lt;br /&gt;
			local commonsFilename = stmt['mainsnak']['datavalue']['value']&lt;br /&gt;
			outHtml:wikitext( ' ' .. mw.getCurrentFrame():expandTemplate{ title = 'Small scan link', args = { commonsFilename } } )&lt;br /&gt;
			hasIndexOrCommonsLink = true;&lt;br /&gt;
		end&lt;br /&gt;
		-- Add link to the IA item if no links were added above.&lt;br /&gt;
		if not hasIndexOrCommonsLink then&lt;br /&gt;
			local internetArchiveIdProp = 'P724'&lt;br /&gt;
			local internetArchiveIdStmts = item:getBestStatements( internetArchiveIdProp )&lt;br /&gt;
			for _, stmt in pairs( internetArchiveIdStmts ) do&lt;br /&gt;
				local internetArchiveId = stmt['mainsnak']['datavalue']['value']&lt;br /&gt;
				outHtml:wikitext( ' ' .. mw.getCurrentFrame():expandTemplate{ title = 'IA small link', args = { internetArchiveId } } )&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	-- Wikidata and Wikipedia links.&lt;br /&gt;
	local img = '[[File:Wikidata-books-task-force-logo.svg|20px|alt=Wikidata books task force logo|link=d:' .. item.id .. '|View on Wikidata]]'&lt;br /&gt;
	outHtml:wikitext( img )&lt;br /&gt;
&lt;br /&gt;
	return tostring( outHtml )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Exported method. Get wikitext for displaying an edition's badges from Wikidata.&lt;br /&gt;
-- To get an indicator, pass args.indicator = true&lt;br /&gt;
-- Testing: =p.badge({args={wikidata='Q75043199'}})&lt;br /&gt;
--&lt;br /&gt;
function badge( args )&lt;br /&gt;
	local item = getItem( args )&lt;br /&gt;
	if not ( item and item.sitelinks and item.sitelinks.enwikisource and item.sitelinks.enwikisource.badges ) then&lt;br /&gt;
		return ''&lt;br /&gt;
	end&lt;br /&gt;
	local badges = item.sitelinks.enwikisource.badges&lt;br /&gt;
	local out = ''&lt;br /&gt;
	for _, badge in pairs( badges ) do&lt;br /&gt;
		local badgeOut = ''&lt;br /&gt;
		local badgeItem = mw.wikibase.getEntity( badge )&lt;br /&gt;
		local badgeName = ''&lt;br /&gt;
		local wikisourceBadgeClass = 'Q75042035'&lt;br /&gt;
		if badgeItem.claims.P31[1].mainsnak.datavalue.value.id == wikisourceBadgeClass and badgeItem.claims.P18 ~= nil then&lt;br /&gt;
			local imageName = badgeItem.claims.P18[1].mainsnak.datavalue.value&lt;br /&gt;
			if mw.wikibase.getLabel( badge ) ~= nil then&lt;br /&gt;
				badgeName = mw.wikibase.getLabel( badge )&lt;br /&gt;
			end&lt;br /&gt;
			badgeOut = '&amp;lt;span class=&amp;quot;indicator-badge&amp;quot;&amp;gt;[[File:' .. imageName .. '|16px|link=Help:Text status|' .. badgeName .. ']]&amp;lt;/span&amp;gt;'&lt;br /&gt;
			if args.indicator ~= nil then&lt;br /&gt;
				badgeOut = '&amp;lt;indicator name=&amp;quot;wikisource-badge-' .. badgeName .. '&amp;quot;&amp;gt;' .. badgeOut .. '&amp;lt;/indicator&amp;gt;'&lt;br /&gt;
			end&lt;br /&gt;
			if args.category ~= nil and badgeItem.claims.P910 ~= nil then&lt;br /&gt;
				local categoryQid = badgeItem.claims.P910[1].mainsnak.datavalue.value.id&lt;br /&gt;
				local category = mw.wikibase.getEntity( categoryQid )&lt;br /&gt;
				badgeOut = badgeOut .. '[[' .. category.sitelinks.enwikisource.title .. ']]'&lt;br /&gt;
			end&lt;br /&gt;
			out = out .. badgeOut&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return mw.getCurrentFrame():preprocess( out )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Get an Item based on what's passed in the 'wikidata' or 'page' parameters of&lt;br /&gt;
-- the args, or the current page's ID otherwise.&lt;br /&gt;
function getItem( args )&lt;br /&gt;
	local id = nil&lt;br /&gt;
	-- If args is a table with an appropriate element, use it.&lt;br /&gt;
	if type( args ) == 'table' then&lt;br /&gt;
		if args.wikidata ~= '' and args.wikidata ~= nil then&lt;br /&gt;
			id = args.wikidata&lt;br /&gt;
		elseif args.wikidata_id ~= '' and args.wikidata_id ~= nil then&lt;br /&gt;
			id = args.wikidata_id&lt;br /&gt;
		elseif args.page ~= '' and args.page ~= nil then&lt;br /&gt;
			local title = mw.title.new( args.page )&lt;br /&gt;
			id = mw.wikibase.getEntityIdForTitle( title.nsText .. title.text )&lt;br /&gt;
			-- If no entity for this page, maybe it's a subpage and we should look for the root page's entity.&lt;br /&gt;
			if id == nil then&lt;br /&gt;
				id = mw.wikibase.getEntityIdForTitle( title.nsText .. title.rootText )&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if type( args ) == 'string' and args ~= '' then&lt;br /&gt;
		id = args&lt;br /&gt;
	end&lt;br /&gt;
	return mw.wikibase.getEntity( id )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Exported method.&lt;br /&gt;
function authority_control( args )&lt;br /&gt;
	local item = getItem( args )&lt;br /&gt;
	-- Gather every 'external-id' statement.&lt;br /&gt;
	local out = mw.html.create( '' )&lt;br /&gt;
	for propertyId,claims in pairs( item.claims) do&lt;br /&gt;
		local propItem = getItem( propertyId )&lt;br /&gt;
		for _,claim in pairs( claims ) do&lt;br /&gt;
			if claim.mainsnak.datatype == 'external-id' then&lt;br /&gt;
				local propLabel = propertyId&lt;br /&gt;
				if propItem.aliases.en[1].value then&lt;br /&gt;
					propLabel = propItem.aliases.en[1].value&lt;br /&gt;
				end&lt;br /&gt;
				-- mw.logObject(propItem)&lt;br /&gt;
				out:wikitext( '* [[' .. propLabel .. ']]: ' .. claim.mainsnak.datavalue.value .. '\n' )&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return tostring( out )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Export all public functions.&lt;br /&gt;
return {&lt;br /&gt;
	-- =p.author_list({args={wikidata='Q28913867'}})&lt;br /&gt;
	author_list = function( frame ) return author_list( frame.args ) end;&lt;br /&gt;
	-- =p.inline({args={wikidata_id='Q28913867'}})&lt;br /&gt;
	inline = function( frame ) return inline( frame.args ) end;&lt;br /&gt;
	-- =p.badge({args={wikidata='Q28020002'}})&lt;br /&gt;
	badge = function( frame ) return badge( frame.args ) end;&lt;br /&gt;
	-- =p.authority_control({args={wikidata='Q19035838'}})&lt;br /&gt;
	authority_control = function( frame ) return authority_control( frame.args ) end;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Module:Arguments&amp;diff=153</id>
		<title>Module:Arguments</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Module:Arguments&amp;diff=153"/>
		<updated>2021-09-26T15:44:20Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: 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('libraryUtil')&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'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) == 'string' then&lt;br /&gt;
		val = val:match('^%s*(.-)%s*$')&lt;br /&gt;
		if val == '' 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) == 'string' then&lt;br /&gt;
		return val:match('^%s*(.-)%s*$')&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) == 'string' then&lt;br /&gt;
		if val:find('%S') 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 == 'string' or tp == 'number') 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('getArgs', 1, frame, 'table', true)&lt;br /&gt;
	checkType('getArgs', 2, options, 'table', 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's availability. If we weren'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) == 'table' and type(frame.getParent) == 'function' 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'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('/sandbox$', '')&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) == 'table' 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'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'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) ~= 'function' then&lt;br /&gt;
			error(&lt;br /&gt;
				&amp;quot;bad value assigned to option 'valueFunc'&amp;quot;&lt;br /&gt;
					.. '(function expected, got '&lt;br /&gt;
					.. type(tidyVal)&lt;br /&gt;
					.. ')',&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 's' (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] ~= 'h' then&lt;br /&gt;
					local tidiedVal = tidyVal(key, val)&lt;br /&gt;
					if tidiedVal == nil then&lt;br /&gt;
						nilArgs[key] = 's'&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) == 'string' 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] = 'h'&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) == 'string' 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;
				'could not write to argument table key &amp;quot;'&lt;br /&gt;
					.. tostring(key)&lt;br /&gt;
					.. '&amp;quot;; the table is read-only',&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;
				'could not write to argument table key &amp;quot;'&lt;br /&gt;
					.. tostring(key)&lt;br /&gt;
					.. '&amp;quot;; overwriting existing arguments is not permitted',&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'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] = 'h'&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) ~= 'string' 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'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>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Module:Check_for_unknown_parameters&amp;diff=151</id>
		<title>Module:Check for unknown parameters</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Module:Check_for_unknown_parameters&amp;diff=151"/>
		<updated>2021-09-26T15:44:19Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: 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('^%s*(.-)%s*$')&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function isnotempty(s)&lt;br /&gt;
	return s and s:match('%S')&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 ''&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) .. '...'&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('([^\127]*)\127[^\127]*%-(%l+)%-[^\127]*\127()') do&lt;br /&gt;
		pos = remainder&lt;br /&gt;
		table.insert(parts, truncate(before) .. '&amp;amp;lt;' .. tag .. '&amp;amp;gt;...&amp;amp;lt;/' .. tag .. '&amp;amp;gt;')&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['ignoreblank'])&lt;br /&gt;
	local showblankpos = isnotempty(args['showblankpositional'])&lt;br /&gt;
	local knownargs = {}&lt;br /&gt;
	local unknown = args['unknown'] or 'Found _VALUE_, '&lt;br /&gt;
	local preview = args['preview']&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) == 'number' then&lt;br /&gt;
			v = trim(v)&lt;br /&gt;
			knownargs[v] = 1&lt;br /&gt;
		elseif k:find('^regexp[1-9][0-9]*$') then&lt;br /&gt;
			table.insert(regexps, '^' .. v .. '$')&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if isnotempty(preview) then&lt;br /&gt;
		preview = '&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; ' .. preview .. ' (this message is shown only in preview).&amp;lt;/div&amp;gt;'&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) == 'string' 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) == 'number' 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 .. ' = ' .. 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 == '' 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 = ' '&lt;br /&gt;
			end&lt;br /&gt;
			-- avoid error with v = 'example%2' (&amp;quot;invalid capture index&amp;quot;)&lt;br /&gt;
			local r =  unknown:gsub('_VALUE_', {_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>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Module:No_globals&amp;diff=149</id>
		<title>Module:No globals</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Module:No_globals&amp;diff=149"/>
		<updated>2021-09-26T15:44:19Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;local mt = getmetatable(_G) or {}&lt;br /&gt;
function mt.__index (t, k)&lt;br /&gt;
	if k ~= 'arg' then&lt;br /&gt;
		error('Tried to read nil global ' .. tostring(k), 2)&lt;br /&gt;
	end&lt;br /&gt;
	return nil&lt;br /&gt;
end&lt;br /&gt;
function mt.__newindex(t, k, v)&lt;br /&gt;
	if k ~= 'arg' then&lt;br /&gt;
		error('Tried to write global ' .. tostring(k), 2)&lt;br /&gt;
	end&lt;br /&gt;
	rawset(t, k, v)&lt;br /&gt;
end&lt;br /&gt;
setmetatable(_G, mt)&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Module:Citation/CS1/styles.css&amp;diff=147</id>
		<title>Module:Citation/CS1/styles.css</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Module:Citation/CS1/styles.css&amp;diff=147"/>
		<updated>2021-09-26T15:44:18Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Protection icon&lt;br /&gt;
the following line controls the page-protection icon in the upper right corner&lt;br /&gt;
it must remain within this comment&lt;br /&gt;
	{{sandbox other||{{pp-template}}}}&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/* Overrides&lt;br /&gt;
Some wikis do not override user agent default styles for HTML &amp;lt;cite&amp;gt; and &amp;lt;q&amp;gt;,&lt;br /&gt;
unlike en.wp. On en.wp, keep these the same as [[MediaWiki:Common.css]]&lt;br /&gt;
*/&lt;br /&gt;
cite.citation {&lt;br /&gt;
	font-style: inherit; /* Remove italics for &amp;lt;cite&amp;gt; */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.citation q {&lt;br /&gt;
	quotes: '&amp;quot;' '&amp;quot;' &amp;quot;'&amp;quot; &amp;quot;'&amp;quot;; /* Straight quote marks for &amp;lt;q&amp;gt; */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* ID and URL access&lt;br /&gt;
Both core and Common.css have selector .mw-parser-output a[href$=&amp;quot;.pdf&amp;quot;].external&lt;br /&gt;
for PDF pages. All TemplateStyles pages are hoisted to .mw-parser-output. We need&lt;br /&gt;
to have specificity equal to a[href$=&amp;quot;.pdf&amp;quot;].external for locks to override PDF icon.&lt;br /&gt;
&lt;br /&gt;
the .id-lock-... selectors are for use by non-citation templates like {{Catalog lookup link}}&lt;br /&gt;
*/&lt;br /&gt;
.id-lock-free a,&lt;br /&gt;
.citation .cs1-lock-free a {&lt;br /&gt;
	background: linear-gradient(transparent, transparent),&lt;br /&gt;
		url(//upload.wikimedia.org/wikipedia/commons/6/65/Lock-green.svg)&lt;br /&gt;
		right 0.1em center/9px no-repeat;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.id-lock-limited a,&lt;br /&gt;
.id-lock-registration a,&lt;br /&gt;
.citation .cs1-lock-limited a,&lt;br /&gt;
.citation .cs1-lock-registration a {&lt;br /&gt;
	background: linear-gradient(transparent, transparent),&lt;br /&gt;
		url(//upload.wikimedia.org/wikipedia/commons/d/d6/Lock-gray-alt-2.svg)&lt;br /&gt;
		right 0.1em center/9px no-repeat;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.id-lock-subscription a,&lt;br /&gt;
.citation .cs1-lock-subscription a {&lt;br /&gt;
	background: linear-gradient(transparent, transparent),&lt;br /&gt;
		url(//upload.wikimedia.org/wikipedia/commons/a/aa/Lock-red-alt-2.svg)&lt;br /&gt;
		right 0.1em center/9px no-repeat;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.cs1-subscription,&lt;br /&gt;
.cs1-registration {&lt;br /&gt;
	color: #555;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.cs1-subscription span,&lt;br /&gt;
.cs1-registration span {&lt;br /&gt;
	border-bottom: 1px dotted;&lt;br /&gt;
	cursor: help;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Wikisource&lt;br /&gt;
Wikisource icon when |chapter= or |title= is wikilinked to Wikisource&lt;br /&gt;
as in cite wikisource&lt;br /&gt;
*/&lt;br /&gt;
.cs1-ws-icon a {&lt;br /&gt;
	background: linear-gradient(transparent, transparent),&lt;br /&gt;
		url(//upload.wikimedia.org/wikipedia/commons/4/4c/Wikisource-logo.svg)&lt;br /&gt;
		right 0.1em center/12px no-repeat;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Errors and maintenance */&lt;br /&gt;
code.cs1-code {&lt;br /&gt;
	/* &amp;lt;code&amp;gt;...&amp;lt;/code&amp;gt; style override: mediawiki's css definition is specified here:&lt;br /&gt;
	https://git.wikimedia.org/blob/mediawiki%2Fcore.git/&lt;br /&gt;
		69cd73811f7aadd093050dbf20ed70ef0b42a713/skins%2Fcommon%2FcommonElements.css#L199&lt;br /&gt;
	*/&lt;br /&gt;
	color: inherit;&lt;br /&gt;
	background: inherit;&lt;br /&gt;
	border: none; /* this maybe can be inherit. MDN says yes, code editor says no */&lt;br /&gt;
	padding: inherit;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.cs1-hidden-error {&lt;br /&gt;
	display: none;&lt;br /&gt;
	font-size: 100%;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.cs1-visible-error {&lt;br /&gt;
	font-size: 100%;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.cs1-maint {&lt;br /&gt;
	display: none;&lt;br /&gt;
	color: #33aa33;&lt;br /&gt;
	margin-left: 0.3em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Small text size&lt;br /&gt;
Set small text size in one place. 0.95 (here) * 0.9 (from references list) is&lt;br /&gt;
~0.85, which is the lower bound for size for accessibility. Old styling for this&lt;br /&gt;
was just 0.85. We could write the rule so that when this template is inside&lt;br /&gt;
references/reflist, only then does it multiply by 0.95; else multiply by 0.85 */&lt;br /&gt;
.cs1-format {&lt;br /&gt;
	font-size: 95%;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* kerning */&lt;br /&gt;
.cs1-kern-left,&lt;br /&gt;
.cs1-kern-wl-left {&lt;br /&gt;
	padding-left: 0.2em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.cs1-kern-right,&lt;br /&gt;
.cs1-kern-wl-right {&lt;br /&gt;
	padding-right: 0.2em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* selflinks – avoid bold font style when cs1|2 template links to the current page */&lt;br /&gt;
.citation .mw-selflink {&lt;br /&gt;
	font-weight: inherit;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Module:Citation/CS1/Whitelist&amp;diff=145</id>
		<title>Module:Citation/CS1/Whitelist</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Module:Citation/CS1/Whitelist&amp;diff=145"/>
		<updated>2021-09-26T15:44:18Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: 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 basic_arguments = {&lt;br /&gt;
	['accessdate'] = true,&lt;br /&gt;
	['access-date'] = true,&lt;br /&gt;
	['agency'] = true,&lt;br /&gt;
	['archivedate'] = true,&lt;br /&gt;
	['archive-date'] = true,&lt;br /&gt;
	['archive-format'] = true,&lt;br /&gt;
	['archiveurl'] = true,&lt;br /&gt;
	['archive-url'] = true,&lt;br /&gt;
	['article'] = true,&lt;br /&gt;
	['article-format'] = true,&lt;br /&gt;
	['article-url'] = true,&lt;br /&gt;
	['article-url-access'] = true,&lt;br /&gt;
	['arxiv'] = true,															-- cite arxiv; here because allowed in cite ... as identifier&lt;br /&gt;
	['asin'] = true,&lt;br /&gt;
	['ASIN'] = true,&lt;br /&gt;
	['asin-tld'] = true,&lt;br /&gt;
	['at'] = true,&lt;br /&gt;
	['author'] = true,&lt;br /&gt;
	['author-first'] = true,&lt;br /&gt;
	['author-given'] = true,&lt;br /&gt;
	['author-last'] = true,&lt;br /&gt;
	['author-surname'] = true,&lt;br /&gt;
	['authorlink'] = true,&lt;br /&gt;
	['author-link'] = true,&lt;br /&gt;
	['author-mask'] = true,&lt;br /&gt;
	['authors'] = true,&lt;br /&gt;
	['bibcode'] = true,&lt;br /&gt;
	['bibcode-access'] = true,&lt;br /&gt;
	['biorxiv'] = true,															-- cite biorxiv; here because allowed in cite ... as identifier&lt;br /&gt;
	['chapter'] = true,&lt;br /&gt;
	['chapter-format'] = true,&lt;br /&gt;
	['chapter-url'] = true,&lt;br /&gt;
	['chapter-url-access'] = true,&lt;br /&gt;
	['citeseerx'] = true,														-- cite citeseerx; here because allowed in cite ... as identifier&lt;br /&gt;
	['collaboration'] = true,&lt;br /&gt;
	['contribution'] = true,&lt;br /&gt;
	['contribution-format'] = true,&lt;br /&gt;
	['contribution-url'] = true,&lt;br /&gt;
	['contribution-url-access'] = true,&lt;br /&gt;
	['contributor'] = true,&lt;br /&gt;
	['contributor-first'] = true,&lt;br /&gt;
	['contributor-given'] = true,&lt;br /&gt;
	['contributor-last'] = true,&lt;br /&gt;
	['contributor-surname'] = true,&lt;br /&gt;
	['contributor-link'] = true,&lt;br /&gt;
	['contributor-mask'] = true,&lt;br /&gt;
	['date'] = true,&lt;br /&gt;
	['department'] = true,&lt;br /&gt;
	['df'] = true,&lt;br /&gt;
	['dictionary'] = true,&lt;br /&gt;
	['display-authors'] = true,&lt;br /&gt;
	['display-contributors'] = true,&lt;br /&gt;
	['display-editors'] = true,&lt;br /&gt;
	['display-interviewers'] = true,&lt;br /&gt;
	['display-subjects'] = true,&lt;br /&gt;
	['display-translators'] = true,&lt;br /&gt;
	['doi'] = true,&lt;br /&gt;
	['DOI'] = true,&lt;br /&gt;
	['doi-access'] = true,&lt;br /&gt;
	['doi-broken-date'] = true,&lt;br /&gt;
	['edition'] = true,&lt;br /&gt;
	['editor'] = true,&lt;br /&gt;
	['editor-first'] = true,&lt;br /&gt;
	['editor-given'] = true,&lt;br /&gt;
	['editor-last'] = true,&lt;br /&gt;
	['editor-surname'] = true,&lt;br /&gt;
	['editor-link'] = true,&lt;br /&gt;
	['editor-mask'] = true,&lt;br /&gt;
	['eissn'] = true,&lt;br /&gt;
	['EISSN'] = true,&lt;br /&gt;
	['encyclopaedia'] = true,&lt;br /&gt;
	['encyclopedia'] = true,&lt;br /&gt;
	['entry'] = true,&lt;br /&gt;
	['entry-format'] = true,&lt;br /&gt;
	['entry-url'] = true,&lt;br /&gt;
	['entry-url-access'] = true,&lt;br /&gt;
	['eprint'] = true,															-- cite arxiv; here because allowed in cite ... as identifier&lt;br /&gt;
	['first'] = true,&lt;br /&gt;
	['format'] = true,&lt;br /&gt;
	['given'] = true,&lt;br /&gt;
	['hdl'] = true,&lt;br /&gt;
	['HDL'] = true,&lt;br /&gt;
	['hdl-access'] = true,&lt;br /&gt;
	['host'] = true,															-- unique to certain templates?&lt;br /&gt;
	['id'] = true,&lt;br /&gt;
	['ID'] = true,&lt;br /&gt;
	['institution'] = true,														-- constrain to cite thesis?&lt;br /&gt;
	['interviewer'] = true,&lt;br /&gt;
	['interviewer-first'] = true,&lt;br /&gt;
	['interviewer-given'] = true,&lt;br /&gt;
	['interviewer-last'] = true,&lt;br /&gt;
	['interviewer-surname'] = true,&lt;br /&gt;
	['interviewer-link'] = true,&lt;br /&gt;
	['interviewer-mask'] = true,&lt;br /&gt;
	['isbn'] = true,&lt;br /&gt;
	['ISBN'] = true,&lt;br /&gt;
	['ismn'] = true,&lt;br /&gt;
	['ISMN'] = true,&lt;br /&gt;
	['issn'] = true,&lt;br /&gt;
	['ISSN'] = true,&lt;br /&gt;
	['issue'] = true,&lt;br /&gt;
	['jfm'] = true,&lt;br /&gt;
	['JFM'] = true,&lt;br /&gt;
	['journal'] = true,&lt;br /&gt;
	['jstor'] = true,&lt;br /&gt;
	['JSTOR'] = true,&lt;br /&gt;
	['jstor-access'] = true,&lt;br /&gt;
	['lang'] = true,&lt;br /&gt;
	['language'] = true,&lt;br /&gt;
	['last'] = true,&lt;br /&gt;
	['lay-date'] = true,&lt;br /&gt;
	['lay-format'] = true,&lt;br /&gt;
	['lay-source'] = true,&lt;br /&gt;
	['lay-url'] = true,&lt;br /&gt;
	['lccn'] = true,&lt;br /&gt;
	['LCCN'] = true,&lt;br /&gt;
	['location'] = true,&lt;br /&gt;
	['magazine'] = true,&lt;br /&gt;
	['medium'] = true,&lt;br /&gt;
	['minutes'] = true,															-- constrain to cite AV media and podcast?&lt;br /&gt;
	['mode'] = true,&lt;br /&gt;
	['mr'] = true,&lt;br /&gt;
	['MR'] = true,&lt;br /&gt;
	['name-list-style'] = true,&lt;br /&gt;
	['newspaper'] = true,&lt;br /&gt;
	['no-pp'] = true,&lt;br /&gt;
	['no-tracking'] = true,&lt;br /&gt;
	['number'] = true,&lt;br /&gt;
	['oclc'] = true,&lt;br /&gt;
	['OCLC'] = true,&lt;br /&gt;
	['ol'] = true,&lt;br /&gt;
	['OL'] = true,&lt;br /&gt;
	['ol-access'] = true,&lt;br /&gt;
	['orig-date'] = true,&lt;br /&gt;
	['origyear'] = true,&lt;br /&gt;
	['orig-year'] = true,&lt;br /&gt;
	['osti'] = true,&lt;br /&gt;
	['OSTI'] = true,&lt;br /&gt;
	['osti-access'] = true,&lt;br /&gt;
	['others'] = true,&lt;br /&gt;
	['p'] = true,&lt;br /&gt;
	['page'] = true,&lt;br /&gt;
	['pages'] = true,&lt;br /&gt;
	['people'] = true,&lt;br /&gt;
	['periodical'] = true,&lt;br /&gt;
	['place'] = true,&lt;br /&gt;
	['pmc'] = true,&lt;br /&gt;
	['PMC'] = true,&lt;br /&gt;
	['pmc-embargo-date'] = true,&lt;br /&gt;
	['pmid'] = true,&lt;br /&gt;
	['PMID'] = true,&lt;br /&gt;
	['postscript'] = true,&lt;br /&gt;
	['pp'] = true,&lt;br /&gt;
	['publication-date'] = true,&lt;br /&gt;
	['publication-place'] = true,&lt;br /&gt;
	['publisher'] = true,&lt;br /&gt;
	['quotation'] = true,&lt;br /&gt;
	['quote'] = true,&lt;br /&gt;
	['quote-page'] = true,&lt;br /&gt;
	['quote-pages'] = true,&lt;br /&gt;
	['ref'] = true,&lt;br /&gt;
	['rfc'] = true,&lt;br /&gt;
	['RFC'] = true,&lt;br /&gt;
	['sbn'] = true,&lt;br /&gt;
	['SBN'] = true,&lt;br /&gt;
	['scale'] = true,&lt;br /&gt;
	['script-article'] = true,&lt;br /&gt;
	['script-chapter'] = true,&lt;br /&gt;
	['script-contribution'] = true,&lt;br /&gt;
	['script-entry'] = true,&lt;br /&gt;
	['script-journal'] = true,&lt;br /&gt;
	['script-magazine'] = true,&lt;br /&gt;
	['script-newspaper'] = true,&lt;br /&gt;
	['script-periodical'] = true,&lt;br /&gt;
	['script-quote'] = true,&lt;br /&gt;
	['script-section'] = true,&lt;br /&gt;
	['script-title'] = true,&lt;br /&gt;
	['script-website'] = true,&lt;br /&gt;
	['script-work'] = true,&lt;br /&gt;
	['section'] = true,&lt;br /&gt;
	['section-format'] = true,&lt;br /&gt;
	['section-url'] = true,&lt;br /&gt;
	['section-url-access'] = true,&lt;br /&gt;
	['series'] = true,&lt;br /&gt;
	['ssrn'] = true,															-- cite ssrn; these three here because allowed in cite ... as identifier&lt;br /&gt;
	['SSRN'] = true,&lt;br /&gt;
	['ssrn-access'] = true,&lt;br /&gt;
	['subject'] = true,&lt;br /&gt;
	['subject-link'] = true,&lt;br /&gt;
	['subject-mask'] = true,&lt;br /&gt;
	['surname'] = true,&lt;br /&gt;
	['s2cid'] = true,&lt;br /&gt;
	['S2CID'] = true,&lt;br /&gt;
	['s2cid-access'] = true,&lt;br /&gt;
	['template-doc-demo'] = true,&lt;br /&gt;
	['time'] = true,															-- constrain to cite av media and podcast?&lt;br /&gt;
	['time-caption'] = true,													-- constrain to cite av media and podcast?&lt;br /&gt;
	['title'] = true,&lt;br /&gt;
	['title-link'] = true,&lt;br /&gt;
	['translator'] = true,&lt;br /&gt;
	['translator-first'] = true,&lt;br /&gt;
	['translator-given'] = true,&lt;br /&gt;
	['translator-last'] = true,	&lt;br /&gt;
	['translator-surname'] = true,&lt;br /&gt;
	['translator-link'] = true,&lt;br /&gt;
	['translator-mask'] = true,&lt;br /&gt;
	['trans-article'] = true,&lt;br /&gt;
	['trans-chapter'] = true,&lt;br /&gt;
	['trans-contribution'] = true,&lt;br /&gt;
	['trans-entry'] = true,&lt;br /&gt;
	['trans-journal'] = true,&lt;br /&gt;
	['trans-magazine'] = true,&lt;br /&gt;
	['trans-newspaper'] = true,&lt;br /&gt;
	['trans-periodical'] = true,&lt;br /&gt;
	['trans-quote'] = true,&lt;br /&gt;
	['trans-section'] = true,&lt;br /&gt;
	['trans-title'] = true,&lt;br /&gt;
	['trans-website'] = true,&lt;br /&gt;
	['trans-work'] = true,&lt;br /&gt;
	['type'] = true,&lt;br /&gt;
	['url'] = true,&lt;br /&gt;
	['URL'] = true,&lt;br /&gt;
	['url-access'] = true,&lt;br /&gt;
	['url-status'] = true,&lt;br /&gt;
	['vauthors'] = true,&lt;br /&gt;
	['veditors'] = true,&lt;br /&gt;
	['version'] = true,&lt;br /&gt;
	['via'] = true,&lt;br /&gt;
	['volume'] = true,&lt;br /&gt;
	['website'] = true,&lt;br /&gt;
	['work'] = true,&lt;br /&gt;
	['year'] = true,&lt;br /&gt;
	['zbl'] = true,&lt;br /&gt;
	['ZBL'] = true,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local numbered_arguments = {&lt;br /&gt;
	['author#'] = true,&lt;br /&gt;
	['author-first#'] = true,&lt;br /&gt;
	['author#-first'] = true,&lt;br /&gt;
	['author-given#'] = true,&lt;br /&gt;
	['author#-given'] = true,&lt;br /&gt;
	['author-last#'] = true,&lt;br /&gt;
	['author#-last'] = true,&lt;br /&gt;
	['author-surname#'] = true,&lt;br /&gt;
	['author#-surname'] = true,&lt;br /&gt;
	['author-link#'] = true,&lt;br /&gt;
	['author#-link'] = true,&lt;br /&gt;
	['authorlink#'] = true,&lt;br /&gt;
	['author#link'] = true,&lt;br /&gt;
	['author-mask#'] = true,&lt;br /&gt;
	['author#-mask'] = true,&lt;br /&gt;
	['contributor#'] = true,&lt;br /&gt;
	['contributor-first#'] = true,&lt;br /&gt;
	['contributor#-first'] = true,&lt;br /&gt;
	['contributor-given#'] = true,&lt;br /&gt;
	['contributor#-given'] = true,&lt;br /&gt;
	['contributor-last#'] = true,&lt;br /&gt;
	['contributor#-last'] = true,&lt;br /&gt;
	['contributor-surname#'] = true,&lt;br /&gt;
	['contributor#-surname'] = true,&lt;br /&gt;
	['contributor-link#'] = true,&lt;br /&gt;
	['contributor#-link'] = true,&lt;br /&gt;
	['contributor-mask#'] = true,&lt;br /&gt;
	['contributor#-mask'] = true,&lt;br /&gt;
	['editor#'] = true,&lt;br /&gt;
	['editor-first#'] = true,&lt;br /&gt;
	['editor#-first'] = true,&lt;br /&gt;
	['editor-given#'] = true,&lt;br /&gt;
	['editor#-given'] = true,&lt;br /&gt;
	['editor-last#'] = true,&lt;br /&gt;
	['editor#-last'] = true,&lt;br /&gt;
	['editor-surname#'] = true,&lt;br /&gt;
	['editor#-surname'] = true,&lt;br /&gt;
	['editor-link#'] = true,&lt;br /&gt;
	['editor#-link'] = true,&lt;br /&gt;
	['editor-mask#'] = true,&lt;br /&gt;
	['editor#-mask'] = true,&lt;br /&gt;
	['first#'] = true,&lt;br /&gt;
	['given#'] = true,&lt;br /&gt;
	['host#'] = true,&lt;br /&gt;
	['interviewer#'] = true,&lt;br /&gt;
	['interviewer-first#'] = true,&lt;br /&gt;
	['interviewer#-first'] = true,&lt;br /&gt;
	['interviewer-given#'] = true,&lt;br /&gt;
	['interviewer#-given'] = true,&lt;br /&gt;
	['interviewer-last#'] = true,&lt;br /&gt;
	['interviewer#-last'] = true,&lt;br /&gt;
	['interviewer-surname#'] = true,&lt;br /&gt;
	['interviewer#-surname'] = true,&lt;br /&gt;
	['interviewer-link#'] = true,&lt;br /&gt;
	['interviewer#-link'] = true,&lt;br /&gt;
	['interviewer-mask#'] = true,&lt;br /&gt;
	['interviewer#-mask'] = true,&lt;br /&gt;
	['last#'] = true,&lt;br /&gt;
	['subject#'] = true,&lt;br /&gt;
	['subject-link#'] = true,&lt;br /&gt;
	['subject#-link'] = true,&lt;br /&gt;
	['subject-mask#'] = true,&lt;br /&gt;
	['subject#-mask'] = true,&lt;br /&gt;
	['surname#'] = true,&lt;br /&gt;
	['translator#'] = true,&lt;br /&gt;
	['translator-first#'] = true,&lt;br /&gt;
	['translator#-first'] = true,&lt;br /&gt;
	['translator-given#'] = true,&lt;br /&gt;
	['translator#-given'] = true,&lt;br /&gt;
	['translator-last#'] = true,&lt;br /&gt;
	['translator#-last'] = true,&lt;br /&gt;
	['translator-surname#'] = true,&lt;br /&gt;
	['translator#-surname'] = true,&lt;br /&gt;
	['translator-link#'] = true,&lt;br /&gt;
	['translator#-link'] = true,&lt;br /&gt;
	['translator-mask#'] = true,&lt;br /&gt;
	['translator#-mask'] = 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/dicouraged/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;
		['arxiv'] = true,														-- cite arxiv and arxiv identifiers&lt;br /&gt;
		['class'] = true,&lt;br /&gt;
		['eprint'] = true,														-- cite arxiv and arxiv identifiers&lt;br /&gt;
		},&lt;br /&gt;
	biorxiv = {&lt;br /&gt;
		['biorxiv'] = true,&lt;br /&gt;
		},&lt;br /&gt;
	citeseerx = {&lt;br /&gt;
		['citeseerx'] = true,&lt;br /&gt;
		},&lt;br /&gt;
	ssrn = {&lt;br /&gt;
		['ssrn'] = true,&lt;br /&gt;
		['SSRN'] = true,&lt;br /&gt;
		['ssrn-access'] = true,&lt;br /&gt;
		},&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; L I M I T E D   S U P P O R T E D   P A R A M E T E R S &amp;gt;----------------------&lt;br /&gt;
&lt;br /&gt;
cite arxiv, cite biorxiv, cite citeseerx, and cite ssrn templates are preprint templates so are allowed only a&lt;br /&gt;
limited subset of parameters allowed to all other cs1|2 templates.  The limited subset is defined here.&lt;br /&gt;
&lt;br /&gt;
Same conventions for true/false/dicouraged/nil as above.&lt;br /&gt;
	&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local limited_basic_arguments = {&lt;br /&gt;
	['at'] = true,&lt;br /&gt;
	['author'] = true,&lt;br /&gt;
	['author-first'] = true,&lt;br /&gt;
	['author-given'] = true,&lt;br /&gt;
	['author-last'] = true,&lt;br /&gt;
	['author-surname'] = true,&lt;br /&gt;
	['author-link'] = true,&lt;br /&gt;
	['authorlink'] = true,&lt;br /&gt;
	['author-mask'] = true,&lt;br /&gt;
	['authors'] = true,&lt;br /&gt;
	['collaboration'] = true,&lt;br /&gt;
	['date'] = true,&lt;br /&gt;
	['df'] = true,&lt;br /&gt;
	['display-authors'] = true,&lt;br /&gt;
	['first'] = true,&lt;br /&gt;
	['given'] = true,&lt;br /&gt;
	['language'] = true,&lt;br /&gt;
	['last'] = true,&lt;br /&gt;
	['mode'] = true,&lt;br /&gt;
	['name-list-style'] = true,&lt;br /&gt;
	['no-tracking'] = true,&lt;br /&gt;
	['p'] = true,&lt;br /&gt;
	['page'] = true,&lt;br /&gt;
	['pages'] = true,&lt;br /&gt;
	['postscript'] = true,&lt;br /&gt;
	['pp'] = true,&lt;br /&gt;
	['quotation'] = true,&lt;br /&gt;
	['quote'] = true,&lt;br /&gt;
	['ref'] = true,&lt;br /&gt;
	['surname'] = true,&lt;br /&gt;
	['template-doc-demo'] = true,&lt;br /&gt;
	['title'] = true,&lt;br /&gt;
	['trans-title'] = true,&lt;br /&gt;
	['vauthors'] = true,&lt;br /&gt;
	['year'] = true,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local limited_numbered_arguments = {&lt;br /&gt;
	['author#'] = true,&lt;br /&gt;
	['author-first#'] = true,&lt;br /&gt;
	['author#-first'] = true,&lt;br /&gt;
	['author-given#'] = true,&lt;br /&gt;
	['author#-given'] = true,&lt;br /&gt;
	['author-last#'] = true,&lt;br /&gt;
	['author#-last'] = true,&lt;br /&gt;
	['author-surname#'] = true,&lt;br /&gt;
	['author#-surname'] = true,&lt;br /&gt;
	['author-link#'] = true,&lt;br /&gt;
	['author#-link'] = true,&lt;br /&gt;
	['authorlink#'] = true,&lt;br /&gt;
	['author#link'] = true,&lt;br /&gt;
	['author-mask#'] = true,&lt;br /&gt;
	['author#-mask'] = true,&lt;br /&gt;
	['first#'] = true,&lt;br /&gt;
	['given#'] = true,&lt;br /&gt;
	['last#'] = true,&lt;br /&gt;
	['surname#'] = 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's CitationClass parameter value&lt;br /&gt;
&lt;br /&gt;
Same conventions for true/false/dicouraged/nil as above.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local unique_arguments = {&lt;br /&gt;
	['audio-visual'] = {&lt;br /&gt;
		['transcript'] = true,&lt;br /&gt;
		['transcript-format'] = true,&lt;br /&gt;
		['transcript-url'] = true,&lt;br /&gt;
		},&lt;br /&gt;
	conference = {&lt;br /&gt;
		['book-title'] = true,&lt;br /&gt;
		['conference'] = true,&lt;br /&gt;
		['conference-format'] = true,&lt;br /&gt;
		['conference-url'] = true,&lt;br /&gt;
		['event'] = true,&lt;br /&gt;
		},&lt;br /&gt;
	episode = {&lt;br /&gt;
		['airdate'] = true,&lt;br /&gt;
		['air-date'] = true,&lt;br /&gt;
		['credits'] = true,&lt;br /&gt;
		['episode-link'] = true,												-- alias of |title-link=&lt;br /&gt;
		['network'] = true,&lt;br /&gt;
		['season'] = true,&lt;br /&gt;
		['series-link'] = true,&lt;br /&gt;
		['series-no'] = true,&lt;br /&gt;
		['series-number'] = true,&lt;br /&gt;
		['station'] = true,&lt;br /&gt;
		['transcript'] = true,&lt;br /&gt;
		['transcript-format'] = true,&lt;br /&gt;
		['transcripturl'] = false,&lt;br /&gt;
		['transcript-url'] = true,&lt;br /&gt;
		},&lt;br /&gt;
	mailinglist = {&lt;br /&gt;
		['mailing-list'] = true,&lt;br /&gt;
		},&lt;br /&gt;
	map = {&lt;br /&gt;
		['cartography'] = true,&lt;br /&gt;
		['inset'] = true,&lt;br /&gt;
		['map'] = true,&lt;br /&gt;
		['map-format'] = true,&lt;br /&gt;
		['map-url'] = true,&lt;br /&gt;
		['map-url-access'] = true,&lt;br /&gt;
		['script-map'] = true,&lt;br /&gt;
		['sections'] = true,&lt;br /&gt;
		['sheet'] = true,&lt;br /&gt;
		['sheets'] = true,&lt;br /&gt;
		['trans-map'] = true,&lt;br /&gt;
		},&lt;br /&gt;
	newsgroup = {&lt;br /&gt;
		['message-id'] = true,&lt;br /&gt;
		['newsgroup'] = true,&lt;br /&gt;
		},&lt;br /&gt;
	report = {&lt;br /&gt;
		['docket'] = true,&lt;br /&gt;
		},&lt;br /&gt;
	serial = {&lt;br /&gt;
		['airdate'] = true,&lt;br /&gt;
		['air-date'] = true,&lt;br /&gt;
		['credits'] = true,&lt;br /&gt;
		['episode'] = true,														-- cite serial only TODO: make available to cite episode?&lt;br /&gt;
		['episode-link'] = true,												-- alias of |title-link=&lt;br /&gt;
		['network'] = true,&lt;br /&gt;
		['series-link'] = true,&lt;br /&gt;
		['station'] = true,&lt;br /&gt;
		},&lt;br /&gt;
	speech = {&lt;br /&gt;
		['conference'] = true,&lt;br /&gt;
		['conference-format'] = true,&lt;br /&gt;
		['conference-url'] = true,&lt;br /&gt;
		['event'] = true,&lt;br /&gt;
		},&lt;br /&gt;
	thesis = {&lt;br /&gt;
		['degree'] = true,&lt;br /&gt;
		['docket'] = 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>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Module:Citation/CS1/Utilities&amp;diff=143</id>
		<title>Module:Citation/CS1/Utilities</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Module:Citation/CS1/Utilities&amp;diff=143"/>
		<updated>2021-09-26T15:44:17Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: 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'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; H A S _ A C C E P T _ A S _ W R I T T E N &amp;gt;------------------------------------&lt;br /&gt;
&lt;br /&gt;
When &amp;lt;str&amp;gt; is wholly wrapped in accept-as-written markup, return &amp;lt;str&amp;gt; without markup and true; return &amp;lt;str&amp;gt; and false else&lt;br /&gt;
&lt;br /&gt;
with allow_empty = false, &amp;lt;str&amp;gt; must have at least one character inside the markup&lt;br /&gt;
with allow_empty = true, &amp;lt;str&amp;gt; the markup frame can be empty like (()) to distinguish an empty template parameter from the specific condition &amp;quot;has no applicable value&amp;quot; in citation-context.&lt;br /&gt;
&lt;br /&gt;
After further evaluation the two cases might be merged at a later stage, but should be kept separated for now.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function has_accept_as_written (str, allow_empty)&lt;br /&gt;
	local count;&lt;br /&gt;
	if true == allow_empty then&lt;br /&gt;
		str, count = str:gsub ('^%(%((.*)%)%)$', '%1'); 						-- allows (()) to be an empty set&lt;br /&gt;
	else&lt;br /&gt;
		str, count = str:gsub ('^%(%((.+)%)%)$', '%1');&lt;br /&gt;
	end&lt;br /&gt;
	return str, 0 ~= count;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; I S _ S E T &amp;gt;------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Returns true if argument is set; false otherwise. Argument is 'set' 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 == '');&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['hidden-error'] or cfg.presentation['visible-error'], 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 both link and display text is provided, returns a wikilink in the form [[L|D]]; if only&lt;br /&gt;
link is provided (or link and display are the same), returns a wikilink in the form [[L]]; if neither are&lt;br /&gt;
provided or link is omitted, returns an empty string.&lt;br /&gt;
&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local function make_wikilink (link, display)&lt;br /&gt;
	if not is_set (link) then return '' end&lt;br /&gt;
&lt;br /&gt;
	if is_set (display) and link ~= display then			&lt;br /&gt;
		return table.concat ({'[[', link, '|', display, ']]'});			&lt;br /&gt;
	else&lt;br /&gt;
		return table.concat ({'[[', link, ']]'});&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S E T _ M E S S A G E &amp;gt;----------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Sets an error 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;
TODO: change z.error_categories and z.maintenance_cats to have the form cat_name = true; to avoid dups without having to have an extra cat&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; TODO: figure out how to delete this table&lt;br /&gt;
&lt;br /&gt;
local function set_message (error_id, arguments, raw, prefix, suffix)&lt;br /&gt;
	local error_state = cfg.error_conditions[error_id];&lt;br /&gt;
	&lt;br /&gt;
	prefix = prefix or '';&lt;br /&gt;
	suffix = suffix or '';&lt;br /&gt;
	&lt;br /&gt;
	if error_state == nil then&lt;br /&gt;
		error (cfg.messages['undefined_error'] .. ': ' .. error_id);			-- because missing error handler in Module:Citation/CS1/Configuration&lt;br /&gt;
&lt;br /&gt;
	elseif is_set (error_state.category) then&lt;br /&gt;
		if error_state.message then												-- when error_state.message defined, this is an error message&lt;br /&gt;
			table.insert (z.error_categories, error_state.category);&lt;br /&gt;
		else&lt;br /&gt;
			if not added_maint_cats[error_id] then&lt;br /&gt;
				added_maint_cats[error_id] = true;								-- note that we've added this category&lt;br /&gt;
				table.insert (z.maintenance_cats, substitute (error_state.category, arguments));	-- make cat name then add to table&lt;br /&gt;
			end&lt;br /&gt;
			return;																-- because no message, nothing more to do&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local message = substitute (error_state.message, arguments);&lt;br /&gt;
&lt;br /&gt;
	message = table.concat (&lt;br /&gt;
		{&lt;br /&gt;
		message,&lt;br /&gt;
		' (',&lt;br /&gt;
		make_wikilink (&lt;br /&gt;
			table.concat (&lt;br /&gt;
				{&lt;br /&gt;
				cfg.messages['help page link'],&lt;br /&gt;
				'#',&lt;br /&gt;
				error_state.anchor&lt;br /&gt;
				}),&lt;br /&gt;
			cfg.messages['help page label']),&lt;br /&gt;
		')'&lt;br /&gt;
		});&lt;br /&gt;
&lt;br /&gt;
	z.error_ids[error_id] = true;&lt;br /&gt;
	if z.error_ids['err_citation_missing_title'] and							-- if missing-title error already noted&lt;br /&gt;
		in_array (error_id, {'err_bare_url_missing_title', 'err_trans_missing_title'}) then		-- and this error is one of these&lt;br /&gt;
			return '', false;													-- don't bother because one flavor of missing title is sufficient&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	message = table.concat ({prefix, message, suffix});&lt;br /&gt;
&lt;br /&gt;
	if 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 to choose how enumerated aliases are examined&lt;br /&gt;
	value – value associated with an alias that has previously been selected; nil if not yet selected&lt;br /&gt;
	selected – the alias that has previously been selected; nil if not yet selected&lt;br /&gt;
	error_list – list of aliases that are duplicates of the alias already selected&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
	value – value associated with alias we selected or that was previously selected or nil if an alias not yet selected&lt;br /&gt;
	selected – the alias we selected or the alias that was previously selected or nil if an alias not yet selected&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function is_alias_used (args, alias, index, enumerated, value, selected, error_list)&lt;br /&gt;
	if enumerated then															-- is this a test for an enumerated parameters?&lt;br /&gt;
		alias = alias:gsub ('#', index);										-- replace '#' with the value in index&lt;br /&gt;
	else&lt;br /&gt;
		alias = alias:gsub ('#', '');											-- remove '#' if it exists&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if is_set (args[alias]) then													-- alias is in the template'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'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 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'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; 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 added_prop_cats = {};														-- list of property categories that have been added to z.properties_cats&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've added this category&lt;br /&gt;
		key = key:gsub ('(foreign_lang_source_?2?)%a%a%a?[%a%-]*', '%1');		-- 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; 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 '' ... ''&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 ''...'' 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 '' tend to interact&lt;br /&gt;
poorly under Mediawiki's HTML tidy.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function safe_for_italics (str)&lt;br /&gt;
	if not is_set (str) then return str end&lt;br /&gt;
&lt;br /&gt;
	if str:sub (1, 1) == &amp;quot;'&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;'&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 ('\n', ' ');&lt;br /&gt;
&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, {'italic-title', 'trans-italic-title'}) then&lt;br /&gt;
		str = safe_for_italics (str);&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return substitute (cfg.presentation[key], {str});&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; M A K E _ S E P _ L I S T &amp;gt;------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
make a separated list of items using provided separators.&lt;br /&gt;
	&amp;lt;sep_list&amp;gt; - typically '&amp;lt;comma&amp;gt;&amp;lt;space&amp;gt;'&lt;br /&gt;
	&amp;lt;sep_list_pair&amp;gt; - typically '&amp;lt;space&amp;gt;and&amp;lt;space&amp;gt;'&lt;br /&gt;
	&amp;lt;sep_list_end&amp;gt; - typically '&amp;lt;comma&amp;gt;&amp;lt;space&amp;gt;and&amp;lt;space&amp;gt;' or '&amp;lt;comma&amp;gt;&amp;lt;space&amp;gt;&amp;amp;&amp;lt;space&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
defaults to cfg.presentation['sep_list'], cfg.presentation['sep_list_pair'], and cfg.presentation['sep_list_end']&lt;br /&gt;
if &amp;lt;sep_list_end&amp;gt; is specified, &amp;lt;sep_list&amp;gt; and &amp;lt;sep_list_pair&amp;gt; must also be supplied&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function make_sep_list (count, list_seq, sep_list, sep_list_pair, sep_list_end)&lt;br /&gt;
	local list = '';&lt;br /&gt;
&lt;br /&gt;
	if not sep_list then														-- set the defaults&lt;br /&gt;
		sep_list = cfg.presentation['sep_list'];&lt;br /&gt;
		sep_list_pair = cfg.presentation['sep_list_pair'];&lt;br /&gt;
		sep_list_end = cfg.presentation['sep_list_end'];&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if 2 &amp;gt;= count then&lt;br /&gt;
		list = table.concat (list_seq, sep_list_pair);							-- insert separator between two items; returns list_seq[1] then only one item&lt;br /&gt;
	elseif 2 &amp;lt; count then&lt;br /&gt;
		list = table.concat (list_seq, sep_list, 1, count - 1);					-- concatenate all but last item with plain list separator&lt;br /&gt;
		list = table.concat ({list, list_seq[count]}, sep_list_end);			-- concatenate last item onto end of &amp;lt;list&amp;gt; with final separator&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return list;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S E L E C T _ O N E &amp;gt;----------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Chooses one matching parameter from a list of parameters to consider.  The list of parameters to consider is just&lt;br /&gt;
names.  For parameters that may be enumerated, the position of the numerator in the parameter name is identified&lt;br /&gt;
by the '#' so |author-last1= and |author1-last= are represented as 'author-last#' and 'author#-last'.&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 = '';														-- 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 ('#') then												-- if this alias can be enumerated&lt;br /&gt;
			if '1' == 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 'none' ~= error_condition then						-- for cases where this code is used outside of extract_names()&lt;br /&gt;
		for i, v in ipairs (error_list) do&lt;br /&gt;
			error_list[i] = wrap_style ('parameter', v);&lt;br /&gt;
		end&lt;br /&gt;
		table.insert (error_list, wrap_style ('parameter', selected));&lt;br /&gt;
		table.insert (z.message_tail, {set_message (error_condition, {make_sep_list (#error_list, error_list)}, 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 whitespace from the label&lt;br /&gt;
if str was wrapped in wikilink markup.  Presumably, this is because without wikimarkup in str, there is no match&lt;br /&gt;
in the initial gsub, the replacement function l() doesn't get called.&lt;br /&gt;
&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local function remove_wiki_link (str)&lt;br /&gt;
	return (str:gsub (&amp;quot;%[%[([^%[%]]*)%]%]&amp;quot;, function(l)&lt;br /&gt;
		return l:gsub (&amp;quot;^[^|]*|(.*)$&amp;quot;, &amp;quot;%1&amp;quot; ):gsub (&amp;quot;^%s*(.-)%s*$&amp;quot;, &amp;quot;%1&amp;quot;);&lt;br /&gt;
	end));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[=[-------------------------&amp;lt; I S _ W I K I L I N K &amp;gt;--------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Determines if str is a wikilink, extracts, and returns the wikilink type, link text, and display text parts.&lt;br /&gt;
If str is a complex wikilink ([[L|D]]):&lt;br /&gt;
	returns wl_type 2 and D and L from [[L|D]];&lt;br /&gt;
if str is a simple wikilink ([[D]])&lt;br /&gt;
	returns wl_type 1 and D from [[D]] and L as empty string;&lt;br /&gt;
if not a wikilink:&lt;br /&gt;
	returns wl_type 0, str as D, and L as empty string.&lt;br /&gt;
&lt;br /&gt;
trims leading and trailing whitespace and pipes from L and D ([[L|]] and [[|D]] are accepted by MediaWiki and&lt;br /&gt;
treated like [[D]]; while [[|D|]] is not accepted by MediaWiki, here, we accept it and return D without the pipes).&lt;br /&gt;
&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local function is_wikilink (str)&lt;br /&gt;
	local D, L&lt;br /&gt;
	local wl_type = 2;															-- assume that str is a complex wikilink [[L|D]]&lt;br /&gt;
&lt;br /&gt;
	if not str:match ('^%[%[[^%]]+%]%]$') then									-- is str some sort of a wikilink (must have some sort of content)&lt;br /&gt;
		return 0, str, '';														-- not a wikilink; return wl_type as 0, str as D, and empty string as L&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	L, D = str:match ('^%[%[([^|]+)|([^%]]+)%]%]$');							-- 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 ('^%[%[([^%]]*)|*%]%]$');									-- 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, '%s|');												-- trim white space and pipe characters &lt;br /&gt;
	return wl_type, D, L or '';&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'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'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;''&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;'''''&amp;quot;, 1, true) then								-- bold italic (5)&lt;br /&gt;
			argument, flag = argument:gsub (&amp;quot;%'%'%'%'%'&amp;quot;, &amp;quot;&amp;quot;);						-- remove all instances of it&lt;br /&gt;
		elseif argument:find (&amp;quot;''''&amp;quot;, 1, true) then							-- italic start and end without content (4)&lt;br /&gt;
			argument, flag=argument:gsub (&amp;quot;%'%'%'%'&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
		elseif argument:find (&amp;quot;'''&amp;quot;, 1, true) then							-- bold (3)&lt;br /&gt;
			argument, flag=argument:gsub (&amp;quot;%'%'%'&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
		elseif argument:find (&amp;quot;''&amp;quot;, 1, true) then								-- italic (2)&lt;br /&gt;
			argument, flag = argument:gsub (&amp;quot;%'%'&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
		else&lt;br /&gt;
			break;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return argument, flag;														-- done&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S E T _ S E L E C T E D _ M O D U L E S &amp;gt;--------------------------------------&lt;br /&gt;
&lt;br /&gt;
Sets local cfg table to same (live or sandbox) as that used by the other modules.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function set_selected_modules (cfg_table_ptr)&lt;br /&gt;
	cfg = cfg_table_ptr;&lt;br /&gt;
	&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; E X P O R T S &amp;gt;----------------------------------------------------------------&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
return {&lt;br /&gt;
	add_maint_cat = add_maint_cat,												-- exported functions&lt;br /&gt;
	add_prop_cat = add_prop_cat,&lt;br /&gt;
	error_comment = error_comment,&lt;br /&gt;
	has_accept_as_written = has_accept_as_written,&lt;br /&gt;
	in_array = in_array,&lt;br /&gt;
	is_set = is_set,&lt;br /&gt;
	is_wikilink = is_wikilink,&lt;br /&gt;
	make_sep_list = make_sep_list,&lt;br /&gt;
	make_wikilink = make_wikilink,&lt;br /&gt;
	remove_wiki_link = remove_wiki_link,&lt;br /&gt;
	safe_for_italics = safe_for_italics,&lt;br /&gt;
	select_one = select_one,&lt;br /&gt;
	set_message = set_message,&lt;br /&gt;
	set_selected_modules = set_selected_modules,&lt;br /&gt;
	strip_apostrophe_markup = strip_apostrophe_markup,&lt;br /&gt;
	substitute = substitute,&lt;br /&gt;
	wrap_style = wrap_style,&lt;br /&gt;
&lt;br /&gt;
	z = z,																		-- exported table&lt;br /&gt;
	}&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Module:Citation/CS1/Identifiers&amp;diff=141</id>
		<title>Module:Citation/CS1/Identifiers</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Module:Citation/CS1/Identifiers&amp;diff=141"/>
		<updated>2021-09-26T15:44:17Z</updated>

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

		<summary type="html">&lt;p&gt;Jayprakash12345: 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 add_prop_cat, is_set, in_array, set_message, substitute, wrap_style;		-- imported functions from selected Module:Citation/CS1/Utilities&lt;br /&gt;
local cfg;																		-- table of tables imported from selected Module:Citation/CS1/Configuration&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; F I L E - S C O P E   D E C L A R A T I O N S &amp;gt;--------------------------------&lt;br /&gt;
&lt;br /&gt;
File-scope variables are declared here&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local lang_object = mw.getContentLanguage();									-- used by is_valid_accessdate(), is_valid_year(), date_name_xlate(); TODO: move to ~/Configuration?&lt;br /&gt;
local year_limit;																-- used by is_valid_year()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[=[-------------------------&amp;lt; I S _ V A L I D _ A C C E S S D A T E &amp;gt;----------------------------------------&lt;br /&gt;
&lt;br /&gt;
returns true if:&lt;br /&gt;
	Wikipedia start date &amp;lt;= accessdate &amp;lt; today + 2 days&lt;br /&gt;
&lt;br /&gt;
Wikipedia start date is 2001-01-15T00:00:00 UTC which is 979516800 seconds after 1970-01-01T00:00:00 UTC (the start of Unix time)&lt;br /&gt;
accessdate is the date provided in |access-date= at time 00:00:00 UTC&lt;br /&gt;
today is the current date at time 00:00:00 UTC plus 48 hours&lt;br /&gt;
	if today is 2015-01-01T00:00:00 then&lt;br /&gt;
		adding 24 hours gives 2015-01-02T00:00:00 – one second more than today&lt;br /&gt;
		adding 24 hours gives 2015-01-03T00:00:00 – one second more than tomorrow&lt;br /&gt;
&lt;br /&gt;
This function does not work if it is fed month names for languages other than English.  Wikimedia #time: parser&lt;br /&gt;
apparently doesn't understand non-English date month names. This function will always return false when the date&lt;br /&gt;
contains a non-English month name because good1 is false after the call to lang.formatDate().  To get around that&lt;br /&gt;
call this function with YYYY-MM-DD format dates.&lt;br /&gt;
&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local function is_valid_accessdate (accessdate)&lt;br /&gt;
	local good1, good2;&lt;br /&gt;
	local access_ts, tomorrow_ts;												-- to hold Unix time stamps representing the dates&lt;br /&gt;
&lt;br /&gt;
	good1, access_ts = pcall (lang_object.formatDate, lang_object, 'U', accessdate );			-- convert accessdate value to Unix timestamp &lt;br /&gt;
	good2, tomorrow_ts = pcall (lang_object.formatDate, lang_object, 'U', 'today + 2 days' );	-- 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'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 |pmc-embargo-date= is&lt;br /&gt;
set, the editor intended to embargo a PMC but |pmc-embargo-date= does not hold a single date.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function is_valid_embargo_date (v)&lt;br /&gt;
	if v:match ('^%d%d%d%d%-%d%d%-%d%d$') or									-- ymd&lt;br /&gt;
		v:match ('^%d%d?%s+%a+%s+%d%d%d%d$') or									-- dmy&lt;br /&gt;
		v:match ('^%a+%s+%d%d?%s*,%s*%d%d%d%d$') then							-- mdy&lt;br /&gt;
			return true, v;&lt;br /&gt;
	end&lt;br /&gt;
	return false, '9999';														-- 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['local'].long[month] or cfg.date_names['local'].short[month] or	-- look for local names first&lt;br /&gt;
			cfg.date_names['en'].long[month] or	cfg.date_names['en'].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 '§Sub-year groupings'.  The standard defines various divisions using&lt;br /&gt;
numbers 21-41.  cs1|2 only supports generic seasons.  EDTF does support the distinction between north and south&lt;br /&gt;
hemisphere seasons but cs1|2 has no way to make that distinction.&lt;br /&gt;
&lt;br /&gt;
These additional divisions not currently supported:&lt;br /&gt;
	25-28 = Spring - Northern Hemisphere, Summer- Northern Hemisphere, Autumn - Northern Hemisphere, Winter - Northern Hemisphere&lt;br /&gt;
	29-32 = Spring – Southern Hemisphere, Summer– Southern Hemisphere, Autumn – Southern Hemisphere, Winter - Southern Hemisphere&lt;br /&gt;
	33-36 = Quarter 1, Quarter 2, Quarter 3, Quarter 4 (3 months each)&lt;br /&gt;
	37-39 = Quadrimester 1, Quadrimester 2, Quadrimester 3 (4 months each)&lt;br /&gt;
	40-41 = Semestral 1, Semestral-2 (6 months each)&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function get_season_number (season, param)&lt;br /&gt;
	if 'date' ~= param then&lt;br /&gt;
		return 0;																-- season dates only supported by |date=&lt;br /&gt;
	end&lt;br /&gt;
	return cfg.date_names['local'].season[season] or							-- look for local names first&lt;br /&gt;
			cfg.date_names['en'].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 '§Sub-year groupings'.  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 'date' ~= 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, ' +', ' ');								-- special case replace multiple space chars with a single space char&lt;br /&gt;
	return cfg.date_names['local'].quarter[quarter] or							-- look for local names first&lt;br /&gt;
			cfg.date_names['en'].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 'date' ~= 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['local'].named[name] or								-- look for local names dates first&lt;br /&gt;
			cfg.date_names['en'].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 'May' == month1 or 'May'== month2 then -- ToDo: I18N&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, hence treat as ok&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function is_valid_month_season_range(range_start, range_end, param)&lt;br /&gt;
	local range_start_number = get_month_number (range_start);&lt;br /&gt;
	local range_end_number;&lt;br /&gt;
&lt;br /&gt;
	if 0 == range_start_number then												-- is this a month range?&lt;br /&gt;
		range_start_number = get_season_number (range_start, param);			-- not a month; is it a season? get start season number&lt;br /&gt;
		range_end_number = get_season_number (range_end, param);				-- get end season number&lt;br /&gt;
&lt;br /&gt;
		if (0 ~= range_start_number) and (0 ~= range_end_number) and (range_start_number ~= range_end_number) then&lt;br /&gt;
			return true;														-- any season pairing is accepted except when both are the same&lt;br /&gt;
		end&lt;br /&gt;
		return false;															-- range_start and/or range_end is not a season&lt;br /&gt;
	end&lt;br /&gt;
																				-- here when range_start is a month&lt;br /&gt;
	range_end_number = get_month_number (range_end);							-- get end month number&lt;br /&gt;
	if range_start_number &amp;lt; range_end_number and								-- range_start is a month; does range_start precede range_end?&lt;br /&gt;
		is_valid_month_range_style (range_start, range_end) then				-- do months have the same style?&lt;br /&gt;
			return true;														-- proper order and same style&lt;br /&gt;
	end&lt;br /&gt;
	return false;																-- range_start month number is greater than or equal to range end number; or range end isn'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't have to do calendar conversion from&lt;br /&gt;
Julian to Proleptic Gregorian.&lt;br /&gt;
&lt;br /&gt;
The input table has:&lt;br /&gt;
	year, year2 – always present; if before 1582, ignore months and days if present&lt;br /&gt;
	month, month2 – 0 if not provided, 1-12 for months, 21-24 for seasons; 99 Christmas&lt;br /&gt;
	day, day2 –  0 if not provided, 1-31 for days&lt;br /&gt;
	&lt;br /&gt;
the output table receives:&lt;br /&gt;
	rftdate:	an ISO 8601 formatted date&lt;br /&gt;
	rftchron:	a free-form version of the date, usually without year which is in rftdate (season ranges and proper-name dates)&lt;br /&gt;
	rftssn:		one of four season keywords: winter, spring, summer, fall (lowercase)&lt;br /&gt;
	rftquarter:	one of four values: 1, 2, 3, 4&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function make_COinS_date (input, tCOinS_date)&lt;br /&gt;
	local date;																	-- one date or first date in a range&lt;br /&gt;
	local date2 = '';															-- end of range date&lt;br /&gt;
-- start temporary Julian / Gregorian calendar uncertainty detection&lt;br /&gt;
	local year = tonumber(input.year);											-- this temporary code to determine the extent of sources dated to the Julian/Gregorian&lt;br /&gt;
	local month = tonumber(input.month);										-- interstice 1 October 1582 – 1 January 1926&lt;br /&gt;
	local day = tonumber (input.day);&lt;br /&gt;
	if (0 ~= day) and															-- day must have a value for this to be a whole date&lt;br /&gt;
		(((1582 == year) and (10 &amp;lt;= month) and (12 &amp;gt;= month)) or				-- any whole 1582 date from 1 October to 31 December or&lt;br /&gt;
			((1926 == year) and (1 == month) and (1 == input.day)) or			-- 1 January 1926 or&lt;br /&gt;
				((1582 &amp;lt; year) and (1925 &amp;gt;= year))) then						-- any date 1 January 1583 – 31 December 1925&lt;br /&gt;
					tCOinS_date.inter_cal_cat = true;							-- set category flag true&lt;br /&gt;
	end&lt;br /&gt;
-- end temporary Julian / Gregorian calendar uncertainty detection&lt;br /&gt;
	&lt;br /&gt;
	if 1582 &amp;gt; tonumber(input.year) or 20 &amp;lt; tonumber(input.month) then			-- Julian calendar or season so &amp;amp;rft.date gets year only&lt;br /&gt;
		date = input.year;&lt;br /&gt;
		if 0 ~= input.year2 and input.year ~= input.year2 then					-- if a range, only the second year portion when not the same as range start year&lt;br /&gt;
			date = string.format ('%.4d/%.4d', 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] = 'winter', [21] = 'spring', [22] = 'summer', [23] = 'fall', [33] = '1', [34] = '2', [35] = '3', [36] = '4', [98] = 'Easter', [99] = 'Christmas'};	-- 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 ('%s %s – %s %s', 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] .. '–' .. 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 ('%s-%.2d-%.2d', input.year, tonumber(input.month), tonumber(input.day));	-- whole date&lt;br /&gt;
	elseif 0 ~= input.month then&lt;br /&gt;
		date = string.format ('%s-%.2d', input.year, tonumber(input.month));	-- year and month&lt;br /&gt;
	else&lt;br /&gt;
		date = string.format ('%s', 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 ('/%s-%.2d-%.2d', input.year2, tonumber(input.month2), tonumber(input.day2));		-- whole date&lt;br /&gt;
		elseif 0 ~= input.month2 then&lt;br /&gt;
			date2 = string.format ('/%s-%.2d', input.year2, tonumber(input.month2));	-- year and month&lt;br /&gt;
		else&lt;br /&gt;
			date2 = string.format ('/%s', 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 '/' 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;
'indicator' letters that identify the content of the matching capture: 'd' (day), 'm' (month), 'a' (anchor year),&lt;br /&gt;
'y' (year); second day, month, year have a '2' 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;
	['ymd'] = {'^(%d%d%d%d)%-(%d%d)%-(%d%d)$', 'y', 'm', 'd'},					&lt;br /&gt;
																				-- month-initial: month day, year&lt;br /&gt;
	['Mdy'] = {'^(%D-) +([1-9]%d?), +((%d%d%d%d?)%a?)$', 'm', 'd', 'a', 'y'},&lt;br /&gt;
																				-- month-initial day range: month day–day, year; days are separated by endash&lt;br /&gt;
	['Md-dy'] = {'^(%D-) +([1-9]%d?)[%-–]([1-9]%d?), +((%d%d%d%d)%a?)$', 'm', 'd', 'd2', 'a', 'y'},&lt;br /&gt;
																				-- day-initial: day month year&lt;br /&gt;
	['dMy'] = {'^([1-9]%d?) +(%D-) +((%d%d%d%d?)%a?)$', 'd', 'm', 'a', 'y'},&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;
	--	['yMd'] = {'^((%d%d%d%d?)%a?) +(%D-) +(%d%d?)$', 'a', 'y', 'm', 'd'},&lt;br /&gt;
																				-- day-range-initial: day–day month year; days are separated by endash&lt;br /&gt;
	['d-dMy'] = {'^([1-9]%d?)[%-–]([1-9]%d?) +(%D-) +((%d%d%d%d)%a?)$', 'd', 'd2', 'm', 'a', 'y'},&lt;br /&gt;
																				-- day initial month-day-range: day month - day month year; uses spaced endash&lt;br /&gt;
	['dM-dMy'] = {'^([1-9]%d?) +(%D-) +[%-–] +([1-9]%d?) +(%D-) +((%d%d%d%d)%a?)$', 'd', 'm', 'd2', 'm2', 'a', 'y'},&lt;br /&gt;
																				-- month initial month-day-range: month day – month day, year;  uses spaced endash&lt;br /&gt;
	['Md-Mdy'] = {'^(%D-) +([1-9]%d?) +[%-–] +(%D-) +([1-9]%d?), +((%d%d%d%d)%a?)$','m', 'd', 'm2', 'd2', 'a', 'y'},&lt;br /&gt;
																				-- day initial month-day-year-range: day month year - day month year; uses spaced endash&lt;br /&gt;
	['dMy-dMy'] = {'^([1-9]%d?) +(%D-) +(%d%d%d%d) +[%-–] +([1-9]%d?) +(%D-) +((%d%d%d%d)%a?)$', 'd', 'm', 'y', 'd2', 'm2', 'a', 'y2'},&lt;br /&gt;
																				-- month initial month-day-year-range: month day, year – month day, year;  uses spaced endash&lt;br /&gt;
	['Mdy-Mdy'] = {'^(%D-) +([1-9]%d?), +(%d%d%d%d) +[%-–] +(%D-) +([1-9]%d?), +((%d%d%d%d)%a?)$', 'm', 'd', 'y', 'm2', 'd2', 'a', 'y2'},&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;
	['My-My'] = {'^(%D-) +(%d%d%d%d) +[%-–] +(%D-) +((%d%d%d%d)%a?)$', 'm', 'y', 'm2', 'a', 'y2'},&lt;br /&gt;
																				-- month/season range year; months separated by endash&lt;br /&gt;
	['M-My'] = {'^(%D-)[%-–](%D-) +((%d%d%d%d)%a?)$', 'm', 'm2', 'a', 'y'},&lt;br /&gt;
																				-- month/season year or proper-name year; quarter year when First Quarter YYYY etc.&lt;br /&gt;
	['My'] = {'^([^%d–]-) +((%d%d%d%d)%a?)$', 'm', 'a', 'y'},					-- this way because endash is a member of %D; %D- will match January–March 2019 when it shouldn't&lt;br /&gt;
&lt;br /&gt;
																				-- these date formats cannot be converted&lt;br /&gt;
	['Sy4-y2'] = {'^(%D-) +((%d%d)%d%d)[%-–]((%d%d)%a?)$'},						-- special case Winter/Summer year-year (YYYY-YY); year separated with unspaced endash&lt;br /&gt;
	['Sy-y'] = {'^(%D-) +(%d%d%d%d)[%-–]((%d%d%d%d)%a?)$'},						-- special case Winter/Summer year-year; year separated with unspaced endash&lt;br /&gt;
	['y-y'] = {'^(%d%d%d%d?)[%-–]((%d%d%d%d?)%a?)$'},							-- year range: YYY-YYY or YYY-YYYY or YYYY–YYYY; separated by unspaced endash; 100-9999&lt;br /&gt;
	['y4-y2'] = {'^((%d%d)%d%d)[%-–]((%d%d)%a?)$'},								-- year range: YYYY–YY; separated by unspaced endash&lt;br /&gt;
	['ymx'] = {'^(%d%d%d%d)%-(%d%d)%-XX$', 'y', 'm'},							-- edtf year-initial numerical year-month-XX&lt;br /&gt;
	['y'] = {'^((%d%d%d%d?)%a?)$'},												-- 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 (DEBUG: not?) used in the COinS metadata and the CITEREF identifier gets&lt;br /&gt;
its year from the year parameter if present otherwise CITEREF does not get a date value.&lt;br /&gt;
&lt;br /&gt;
Inputs:&lt;br /&gt;
	date_string - date string from date-holding parameters (date, year, publication-date, access-date, pmc-embargo-date, archive-date, lay-date)&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
	false if date string is not a real date; else&lt;br /&gt;
	true, anchor_year, COinS_date&lt;br /&gt;
		anchor_year can be used in CITEREF anchors&lt;br /&gt;
		COinS_date is ISO 8601 format date; see make_COInS_date()&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function check_date (date_string, param, tCOinS_date)&lt;br /&gt;
	local year;																	-- assume that year2, months, and days are not used;&lt;br /&gt;
	local year2 = 0;															-- second year in a year range&lt;br /&gt;
	local month = 0;&lt;br /&gt;
	local month2 = 0;															-- second month in a month range&lt;br /&gt;
	local day = 0;&lt;br /&gt;
	local day2 = 0;																-- second day in a day range&lt;br /&gt;
	local anchor_year;&lt;br /&gt;
	local coins_date;&lt;br /&gt;
&lt;br /&gt;
	if date_string:match (patterns['ymd'][1]) then								-- year-initial numerical year month day format&lt;br /&gt;
		year, month, day = date_string:match (patterns['ymd'][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 date_string:match (patterns['ymx'][1]) then							-- year-initial numerical year month edtf format&lt;br /&gt;
		year, month = date_string:match (patterns['ymx'][1]);&lt;br /&gt;
		if 12 &amp;lt; tonumber(month) or 1 &amp;gt; tonumber(month) or 1582 &amp;gt; tonumber(year) or not is_valid_year(year) then return false; end	-- month number not valid or not Gregorian calendar or future year&lt;br /&gt;
		anchor_year = year;&lt;br /&gt;
&lt;br /&gt;
	elseif mw.ustring.match(date_string, patterns['Mdy'][1]) then				-- month-initial: month day, year&lt;br /&gt;
		month, day, anchor_year, year = mw.ustring.match(date_string, patterns['Mdy'][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't one of the twelve months&lt;br /&gt;
				&lt;br /&gt;
	elseif mw.ustring.match(date_string, patterns['Md-dy'][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['Md-dy'][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'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['dMy'][1]) then				-- day-initial: day month year&lt;br /&gt;
		day, month, anchor_year, year = mw.ustring.match(date_string, patterns['dMy'][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'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['yMd'][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['yMd'][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'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['d-dMy'][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['d-dMy'][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'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['dM-dMy'][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['dM-dMy'][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['Md-Mdy'][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['Md-Mdy'][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['dMy-dMy'][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['dMy-dMy'][1]);&lt;br /&gt;
		if tonumber(year2) &amp;lt;= tonumber(year) then return false; end				-- must be sequential years, left to right, earlier to later&lt;br /&gt;
		if not is_valid_year(year2) or not is_valid_month_range_style(month, month2) then return false; end		-- year2 no more than one year in the future; months same style&lt;br /&gt;
		month = get_month_number (month);										-- for metadata&lt;br /&gt;
		month2 = get_month_number (month2);&lt;br /&gt;
		if 0 == month or 0 == month2 then return false; end						-- both must be valid&lt;br /&gt;
&lt;br /&gt;
	elseif mw.ustring.match(date_string, patterns['Mdy-Mdy'][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['Mdy-Mdy'][1]);&lt;br /&gt;
		if tonumber(year2) &amp;lt;= tonumber(year) then return false; end				-- must be sequential years, left to right, earlier to later&lt;br /&gt;
		if not is_valid_year(year2) or not is_valid_month_range_style(month, month2) then return false; end		-- year2 no more than one year in the future; months same style&lt;br /&gt;
		month = get_month_number (month);										-- for metadata&lt;br /&gt;
		month2 = get_month_number(month2);&lt;br /&gt;
		if 0 == month or 0 == month2 then return false; end						-- both must be valid&lt;br /&gt;
&lt;br /&gt;
	elseif mw.ustring.match(date_string, patterns['Sy4-y2'][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['Sy4-y2'][1]);&lt;br /&gt;
		if 'Winter' ~= month and 'Summer' ~= month then return false end;		-- 'month' can only be Winter or Summer&lt;br /&gt;
		anchor_year = year .. '–' .. 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['Sy-y'][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['Sy-y'][1]);&lt;br /&gt;
		if 'Winter' ~= month and 'Summer' ~= month then return false end;		-- 'month' can only be Winter or Summer&lt;br /&gt;
		anchor_year = year .. '–' .. 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['My-My'][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['My-My'][1]);&lt;br /&gt;
		anchor_year = year .. '–' .. 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['M-My'][1]) then				-- month/season range year; months separated by endash &lt;br /&gt;
		month, month2, anchor_year, year = mw.ustring.match(date_string, patterns['M-My'][1]);&lt;br /&gt;
		if (not is_valid_month_season_range(month, month2, param)) or (not is_valid_year(year)) then return false; end&lt;br /&gt;
		if 0 ~= get_month_number(month) then									-- determined to be a valid range so just check this one to know if month or season&lt;br /&gt;
			month = get_month_number(month);&lt;br /&gt;
			month2 = get_month_number(month2);&lt;br /&gt;
			if 0 == month or 0 == month2 then return false; end&lt;br /&gt;
		else&lt;br /&gt;
			month = get_season_number(month, param);&lt;br /&gt;
			month2 = get_season_number(month2, param);&lt;br /&gt;
		end&lt;br /&gt;
		year2 = year;&lt;br /&gt;
		&lt;br /&gt;
	elseif mw.ustring.match(date_string, patterns['My'][1]) then				-- month/season/quarter/proper-name year&lt;br /&gt;
		month, anchor_year, year = mw.ustring.match(date_string, patterns['My'][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['y-y'][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['y-y'][1]);&lt;br /&gt;
		anchor_year = year .. '–' .. 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['y4-y2'][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['y4-y2'][1]);&lt;br /&gt;
		anchor_year = year .. '–' .. anchor_year;								-- assemble anchor year from both years&lt;br /&gt;
&lt;br /&gt;
		if in_array (param, {'date', 'publication-date', 'year'}) then&lt;br /&gt;
			add_prop_cat ('year_range_abbreviated');&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		if 13 &amp;gt; tonumber(year2) then return false; end							-- don'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['y'][1]) then					-- year; here accept either YYY or YYYY&lt;br /&gt;
		anchor_year, year = mw.ustring.match(date_string, patterns['y'][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 'access-date' == 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 .. '-' .. month .. '-' .. 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;
parameters with errors are added to the &amp;lt;error_list&amp;gt; sequence table as the dates are tested.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function dates(date_parameters_list, tCOinS_date, error_list)&lt;br /&gt;
	local anchor_year;															-- will return as nil if the date being tested is not |date=&lt;br /&gt;
	local COinS_date;															-- will return as nil if the date being tested is not |date=&lt;br /&gt;
	local embargo_date;															-- if embargo date is a good dmy, mdy, ymd date then holds original value else reset to 9999&lt;br /&gt;
	local good_date = false;&lt;br /&gt;
&lt;br /&gt;
	for k, v in pairs(date_parameters_list) do									-- for each date-holding parameter in the list&lt;br /&gt;
		if is_set(v.val) then													-- if the parameter has a value&lt;br /&gt;
			v.val = mw.ustring.gsub(v.val, '%d', cfg.date_names.local_digits);	-- translate 'local' 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 'date' == 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 'year' == k then&lt;br /&gt;
					good_date = is_valid_year(year);&lt;br /&gt;
				end&lt;br /&gt;
			elseif 'date' == k then												-- if the parameter is |date=&lt;br /&gt;
				if v.val:match(&amp;quot;^n%.d%.%a?$&amp;quot;) then -- ToDo: I18N								-- if |date=n.d. with or without a CITEREF disambiguator&lt;br /&gt;
					good_date, anchor_year, COinS_date = true, v.val:match(&amp;quot;((n%.d%.)%a?)&amp;quot;); -- ToDo: I18N	-- &amp;quot;n.d.&amp;quot;; no error when date parameter is set to no date&lt;br /&gt;
				elseif v.val:match(&amp;quot;^nd%a?$&amp;quot;) then -- ToDo: I18N								-- if |date=nd with or without a CITEREF disambiguator&lt;br /&gt;
					good_date, anchor_year, COinS_date = true, v.val:match(&amp;quot;((nd)%a?)&amp;quot;); -- ToDo: I18N	-- &amp;quot;nd&amp;quot;;	no error when date parameter is set to no date&lt;br /&gt;
				else&lt;br /&gt;
					good_date, anchor_year, COinS_date = check_date (v.val, k, tCOinS_date);	-- go test the date&lt;br /&gt;
				end&lt;br /&gt;
			elseif 'year' == 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 'pmc-embargo-date' == k then											-- if the parameter is |pmc-embargo-date=&lt;br /&gt;
				good_date = check_date (v.val, k);								-- go test the date&lt;br /&gt;
				if true == good_date then										-- if the date is a valid date&lt;br /&gt;
					good_date, embargo_date = is_valid_embargo_date (v.val);	-- is |pmc-embargo-date= date a single dmy, mdy, or ymd formatted date? yes: returns embargo; 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't add the tracking category multiple times&lt;br /&gt;
				table.insert (error_list, wrap_style ('parameter', v.name));	-- make parameter name suitable for error message list&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return anchor_year, embargo_date;											-- and done&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; Y E A R _ D A T E _ C H E C K &amp;gt;------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Compare the value provided in |year= with the year value(s) provided in |date=.  This function sets a local numeric value:&lt;br /&gt;
	0 - year value does not match the year value in date&lt;br /&gt;
	1 - (default) year value matches the year value in date or one of the year values when date contains two years&lt;br /&gt;
	2 - year value matches the year value in date when date is in the form YYYY-MM-DD and year is disambiguated (|year=YYYYx)&lt;br /&gt;
&lt;br /&gt;
the numernic value in &amp;lt;result&amp;gt; determines the 'output' if any from this function:&lt;br /&gt;
	0 – adds error message to error_list sequence table&lt;br /&gt;
	1 – adds maint cat&lt;br /&gt;
	2 – does nothing&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function year_date_check (year_string, year_origin, date_string, date_origin, error_list)&lt;br /&gt;
	local year;&lt;br /&gt;
	local date1;&lt;br /&gt;
	local date2;&lt;br /&gt;
	local result = 1;															-- result of the test; assume that the test passes&lt;br /&gt;
&lt;br /&gt;
	year = year_string:match ('(%d%d%d%d?)');&lt;br /&gt;
&lt;br /&gt;
	if date_string:match ('%d%d%d%d%-%d%d%-%d%d') and year_string:match ('%d%d%d%d%a') then	--special case where both date and year are required YYYY-MM-DD and YYYYx&lt;br /&gt;
		date1 = date_string:match ('(%d%d%d%d)');&lt;br /&gt;
		year = year_string:match ('(%d%d%d%d)');&lt;br /&gt;
		if year ~= date1 then&lt;br /&gt;
			result = 0;															-- years don't match&lt;br /&gt;
		else&lt;br /&gt;
			result = 2;															-- years match; but because disambiguated, don't add to maint cat&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
	elseif date_string:match (&amp;quot;%d%d%d%d?.-%d%d%d%d?&amp;quot;) then						-- any of the standard range formats of date with two three- or four-digit years&lt;br /&gt;
		date1, date2 = date_string:match (&amp;quot;(%d%d%d%d?).-(%d%d%d%d?)&amp;quot;);&lt;br /&gt;
		if year ~= date1 and year ~= date2 then&lt;br /&gt;
			result = 0;&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
	elseif mw.ustring.match(date_string, &amp;quot;%d%d%d%d[%-–]%d%d&amp;quot;) then				-- YYYY-YY date ranges&lt;br /&gt;
		local century;&lt;br /&gt;
		date1, century, date2 = mw.ustring.match(date_string, &amp;quot;((%d%d)%d%d)[%-–]+(%d%d)&amp;quot;);&lt;br /&gt;
		date2 = century..date2;													-- convert YY to YYYY&lt;br /&gt;
		if year ~= date1 and year ~= date2 then&lt;br /&gt;
			result = 0;&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
	elseif date_string:match (&amp;quot;%d%d%d%d?&amp;quot;) then									-- any of the standard formats of date with one year&lt;br /&gt;
		date1 = date_string:match (&amp;quot;(%d%d%d%d?)&amp;quot;);&lt;br /&gt;
		if year ~= date1 then&lt;br /&gt;
			result = 0;&lt;br /&gt;
		end&lt;br /&gt;
	else																		-- should never get here; this function called only when no other date errors&lt;br /&gt;
		result = 0;																-- no recognizable year in date&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if 0 == result then															-- year / date mismatch&lt;br /&gt;
		table.insert (error_list, substitute (cfg.messages['mismatch'], {year_origin, date_origin}));	-- add error message to error_list sequence table&lt;br /&gt;
	elseif 1 == result then														-- redundant year / date&lt;br /&gt;
		set_message ('maint_date_year');										-- add a maint cat&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; R E F O R M A T T E R &amp;gt;--------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
reformat 'date' into new format specified by format_param if pattern_idx (the current format of 'date') can be&lt;br /&gt;
reformatted.  Does the grunt work for reformat_dates().&lt;br /&gt;
&lt;br /&gt;
The table re_formats maps pattern_idx (current format) and format_param (desired format) to a table that holds:&lt;br /&gt;
	format string used by string.format()&lt;br /&gt;
	identifier letters ('d', 'm', 'y', 'd2', 'm2', 'y2') 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;
	['ymd'] = {'^(%d%d%d%d)%-(%d%d)%-(%d%d)$', 'y', 'm', 'd'}, where:&lt;br /&gt;
		['ymd'] is pattern_idx&lt;br /&gt;
		patterns['ymd'][1] is the match pattern with captures for mw.ustring.match()&lt;br /&gt;
		patterns['ymd'][2] is an indicator letter identifying the content of the first capture&lt;br /&gt;
		patterns['ymd'][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;
	['ymd'] = {																	-- date format is ymd; reformat to:&lt;br /&gt;
		['mdy'] = {'%s %s, %s', 'm', 'd', 'y'},									-- |df=mdy&lt;br /&gt;
		['dmy'] = {'%s %s %s', 'd', 'm', 'y'},									-- |df=dmy&lt;br /&gt;
	--		['yMd'] = {'%s %s %s', 'y', 'm', 'd'},								-- |df=yMd; not supported at en.wiki&lt;br /&gt;
		},&lt;br /&gt;
	['Mdy'] = {																	-- date format is Mdy; reformat to:&lt;br /&gt;
		['mdy'] = {'%s %s, %s', 'm', 'd', 'y'},									-- for long/short reformatting&lt;br /&gt;
		['dmy'] = {'%s %s %s', 'd', 'm', 'y'},									-- |df=dmy&lt;br /&gt;
		['ymd'] = {'%s-%s-%s', 'y', 'm', 'd'},									-- |df=ymd&lt;br /&gt;
	--		['yMd'] = {'%s %s %s', 'y', 'm', 'd'},								-- |df=yMd; not supported at en.wiki&lt;br /&gt;
		},&lt;br /&gt;
	['dMy'] = {																	-- date format is dMy; reformat to:&lt;br /&gt;
		['dmy'] = {'%s %s %s', 'd', 'm', 'y'},									-- for long/short reformatting&lt;br /&gt;
		['mdy'] = {'%s %s, %s', 'm', 'd', 'y'},									-- |df=mdy&lt;br /&gt;
		['ymd'] = {'%s-%s-%s', 'y', 'm', 'd'},									-- |df=ymd&lt;br /&gt;
	--		['yMd'] = {'%s %s %s', 'y', 'm', 'd'},								-- |df=yMd; not supported at en.wiki&lt;br /&gt;
		},&lt;br /&gt;
	['Md-dy'] = {																-- date format is Md-dy; reformat to:&lt;br /&gt;
		['mdy'] = {'%s %s–%s, %s', 'm', 'd', 'd2', 'y'},						-- for long/short reformatting&lt;br /&gt;
		['dmy'] = {'%s–%s %s %s', 'd', 'd2', 'm', 'y'},							-- |df=dmy -&amp;gt; d-dMy &lt;br /&gt;
		},&lt;br /&gt;
	['d-dMy'] = {																-- date format is d-d&amp;gt;y; reformat to:&lt;br /&gt;
		['dmy'] = {'%s–%s %s %s', 'd', 'd2', 'm', 'y'},							-- for long/short reformatting&lt;br /&gt;
		['mdy'] = {'%s %s–%s, %s', 'm', 'd', 'd2', 'y'},						-- |df=mdy -&amp;gt; Md-dy &lt;br /&gt;
		},&lt;br /&gt;
	['dM-dMy'] = {																-- date format is dM-dMy; reformat to:&lt;br /&gt;
		['dmy'] = {'%s %s – %s %s %s', 'd', 'm', 'd2', 'm2', 'y'},				-- for long/short reformatting&lt;br /&gt;
		['mdy'] = {'%s %s – %s %s, %s', 'm', 'd', 'm2', 'd2', 'y'},				-- |df=mdy -&amp;gt; Md-Mdy &lt;br /&gt;
		},&lt;br /&gt;
	['Md-Mdy'] = {																-- date format is Md-Mdy; reformat to:&lt;br /&gt;
		['mdy'] = {'%s %s – %s %s, %s', 'm', 'd',  'm2', 'd2', 'y'},			-- for long/short reformatting&lt;br /&gt;
		['dmy'] = {'%s %s – %s %s %s', 'd', 'm', 'd2', 'm2', 'y'},				-- |df=dmy -&amp;gt; dM-dMy &lt;br /&gt;
		},&lt;br /&gt;
	['dMy-dMy'] = {																-- date format is dMy-dMy; reformat to:&lt;br /&gt;
		['dmy'] = {'%s %s %s – %s %s %s', 'd', 'm', 'y', 'd2', 'm2', 'y2'},		-- for long/short reformatting&lt;br /&gt;
		['mdy'] = {'%s %s, %s – %s %s, %s', 'm', 'd', 'y', 'm2', 'd2', 'y2'},	-- |df=mdy -&amp;gt; Mdy-Mdy &lt;br /&gt;
		},&lt;br /&gt;
	['Mdy-Mdy'] = {																-- date format is Mdy-Mdy; reformat to:&lt;br /&gt;
		['mdy'] = {'%s %s, %s – %s %s, %s', 'm', 'd', 'y', 'm2', 'd2', 'y2'},	-- for long/short reformatting&lt;br /&gt;
		['dmy'] = {'%s %s %s – %s %s %s', 'd', 'm', 'y', 'd2', 'm2', 'y2'},		-- |df=dmy -&amp;gt; dMy-dMy &lt;br /&gt;
		},&lt;br /&gt;
	['My-My'] = {																-- these for long/short reformatting&lt;br /&gt;
		['any'] = {'%s %s – %s %s', 'm', 'y', 'm2', 'y2'},						-- dmy/mdy agnostic&lt;br /&gt;
		},&lt;br /&gt;
	['M-My'] = {																-- these for long/short reformatting&lt;br /&gt;
		['any'] = {'%s–%s %s', 'm', 'm2', 'y'},									-- dmy/mdy agnostic&lt;br /&gt;
		},&lt;br /&gt;
	['My'] = {																	-- these for long/short reformatting&lt;br /&gt;
		['any'] = {'%s %s', 'm', 'y'},											-- dmy/mdy agnostic&lt;br /&gt;
		},&lt;br /&gt;
	--	['yMd'] = {																-- not supported at en.wiki&lt;br /&gt;
	--		['mdy'] = {'%s %s, %s', 'm', 'd', 'y'},								-- |df=mdy&lt;br /&gt;
	--		['dmy'] = {'%s %s %s', 'd', 'm', 'y'},								-- |df=dmy&lt;br /&gt;
	--		['ymd'] = {'%s-%s-%s', 'y', 'm', 'd'},								-- |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, {'ymd', 'Mdy', 'Md-dy', 'dMy', 'yMd', 'd-dMy', 'dM-dMy', 'Md-Mdy', 'dMy-dMy', 'Mdy-Mdy', 'My-My', 'M-My', 'My'}) 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 'ymd' == format_param and in_array (pattern_idx, {'ymd', 'Md-dy', 'd-dMy', 'dM-dMy', 'Md-Mdy', 'dMy-dMy', 'Mdy-Mdy', 'My-My', 'M-My', 'My'}) 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, {'My', 'M-My', 'My-My'}) then						-- these are not dmy/mdy so can't be 'reformatted' into either&lt;br /&gt;
		format_param = 'any';													-- so format-agnostic &lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
																				-- yMd is not supported at en.wiki; if yMd is supported at your wiki, uncomment the next line&lt;br /&gt;
	--	if 'yMd' == format_param and in_array (pattern_idx, {'yMd', 'Md-dy', 'd-dMy', 'dM-dMy', 'Md-Mdy', 'dMy-dMy', 'Mdy-Mdy'}) then	-- these formats not convertable; yMd not supported at en.wiki&lt;br /&gt;
	-- if yMd is supported at your wiki, remove or comment-out the next line&lt;br /&gt;
	if 'yMd' == format_param then												-- yMd 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 'x'] = c2;									-- patterns can have a variable number of captures; each capture requires an indicator letter;&lt;br /&gt;
		[patterns[pattern_idx][4] or 'x'] = 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 'x'] = c4;									-- the 'x' here spoofs an indicator letter to prevent 'table index is nil' error&lt;br /&gt;
		[patterns[pattern_idx][6] or 'x'] = c5;&lt;br /&gt;
		[patterns[pattern_idx][7] or 'x'] = c6;&lt;br /&gt;
		[patterns[pattern_idx][8] or 'x'] = 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 's' == mon_len then													-- if we are to use abbreviated month names&lt;br /&gt;
			t.m = cfg.date_names['inv_local_s'][tonumber(t.m)];					-- convert it to a month name&lt;br /&gt;
		else&lt;br /&gt;
			t.m = cfg.date_names['inv_local_l'][tonumber(t.m)];					-- convert it to a month name&lt;br /&gt;
		end&lt;br /&gt;
		t.d = t.d:gsub ('0(%d)', '%1');											-- strip leading '0' from day if present&lt;br /&gt;
	elseif 'ymd' == 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 ('%02d', get_month_number (t.m));					-- make sure that month and day are two digits&lt;br /&gt;
		t.d = string.format ('%02d', t.d);&lt;br /&gt;
	elseif mon_len then															-- if mon_len is set to either 'short' or 'long'&lt;br /&gt;
		for _, mon in ipairs ({'m', 'm2'}) 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't be converted&lt;br /&gt;
				t[mon] = (('s' == mon_len) and cfg.date_names['inv_local_s'][t[mon]]) or cfg.date_names['inv_local_l'][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 = 'l';															-- default publication date length shall be long&lt;br /&gt;
	local len_a = 'l';															-- 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('%a+%-all') then											-- manual df keyword; auto df keyword when length not specified in {{use xxx dates}}; &lt;br /&gt;
		format = format:match('(%a+)%-all');									-- extract the format&lt;br /&gt;
		all = true;																-- all dates are long format dates because this keyword doesn't specify length&lt;br /&gt;
	elseif format:match('%a+%-[lsy][sy]?') 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('(%a+)%-([lsy])([sy]?)');			-- extract the format and length keywords&lt;br /&gt;
		if 'y' == len_p then													-- because allowed by MOS:DATEUNIFY (sort of) range dates and My dates not reformatted&lt;br /&gt;
			format = 'ymd';														-- 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, {'access-date', 'archive-date'})) 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, {'access-date', 'archive-date'}) then	-- if this date is an access- or archive-date&lt;br /&gt;
							new_date = reformatter (param_val.val, pattern_idx, (('y' == len_a) and 'ymd') or format, len_a);	-- choose ymd or dmy/mdy according to len_a setting&lt;br /&gt;
						else													-- all other dates&lt;br /&gt;
							new_date = reformatter (param_val.val, pattern_idx, format, len_p);&lt;br /&gt;
						end&lt;br /&gt;
						&lt;br /&gt;
						if new_date then										-- set when date was reformatted&lt;br /&gt;
							date_parameters_list[param_name].val = new_date;	-- update date in date list&lt;br /&gt;
							result = true;										-- and announce that changes have been made&lt;br /&gt;
						end&lt;br /&gt;
					end	-- if&lt;br /&gt;
				end		-- for&lt;br /&gt;
			end			-- if&lt;br /&gt;
		end				-- if&lt;br /&gt;
	end					-- for&lt;br /&gt;
return result;																	-- declare boolean result and done&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; D A T E _ H Y P H E N _ T O _ D A S H &amp;gt;----------------------------------------&lt;br /&gt;
&lt;br /&gt;
Loops through the list of date-holding parameters and converts any hyphen to an ndash.  Not called if the cs1|2&lt;br /&gt;
template has any date errors.&lt;br /&gt;
&lt;br /&gt;
Modifies the date_parameters_list and returns true if hyphens are replaced, else returns false.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function date_hyphen_to_dash (date_parameters_list)&lt;br /&gt;
	local result = false;&lt;br /&gt;
	local n;&lt;br /&gt;
	for param_name, param_val in pairs(date_parameters_list) do					-- for each date-holding parameter in the list&lt;br /&gt;
		if is_set (param_val.val) and&lt;br /&gt;
			not mw.ustring.match (param_val.val, patterns.ymd[1]) then			-- for those that are not ymd dates (ustring because here digits may not be Western)&lt;br /&gt;
				param_val.val, n = param_val.val:gsub ('%-', '–');				-- replace any hyphen with ndash&lt;br /&gt;
				if 0 ~= n then&lt;br /&gt;
					date_parameters_list[param_name].val = param_val.val;		-- update the list&lt;br /&gt;
					result = true;&lt;br /&gt;
				end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return result;																-- so we know if any hyphens were replaced&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; E D T F _ T R A N S F O R M &amp;gt;--------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Loops through the list of date-holding parameters and converts any EDTF formatted dates to MOS compliant dates.&lt;br /&gt;
Only YYY-MM-XX supported at this time. Not called if the cs1|2 template has any date errors.&lt;br /&gt;
&lt;br /&gt;
must be done before reformat_dates() and before date_hyphen_to_dash()&lt;br /&gt;
&lt;br /&gt;
Modifies the date_parameters_list and returns true if transformation is performed, else returns false.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function edtf_transform (date_parameters_list)&lt;br /&gt;
	local result = false;&lt;br /&gt;
	local source_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) and param_val.val:match (patterns.ymx[1]) then	-- if parameter is set and is an EDTF dates&lt;br /&gt;
			source_date.year, source_date.month = param_val.val:match (patterns.ymx[1]);	-- get year and month number&lt;br /&gt;
			source_date.day = 1;												-- required by os.time()&lt;br /&gt;
			date_parameters_list[param_name].val = mw.text.trim (os.date ('%B %Y', os.time (source_date)));&lt;br /&gt;
			result = true;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return result;																-- so we know if a transform was done&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'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'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, '%a+') 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 = 'F';													-- English name is long so use long local name&lt;br /&gt;
				elseif cfg.date_names.en.short[month] then&lt;br /&gt;
					mode = 'M';													-- 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, '1' .. 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 ('%d', cfg.date_names.xlate_digits);			-- translate digits from Western to 'local digits'&lt;br /&gt;
				date_parameters_list[param_name].val = date;					-- save the translated date&lt;br /&gt;
				modified = true;&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return modified;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S E T _ S E L E C T E D _ M O D U L E S &amp;gt;--------------------------------------&lt;br /&gt;
&lt;br /&gt;
Sets local imported functions table to same (live or sandbox) as that used by the other modules.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function set_selected_modules (cfg_table_ptr, utilities_page_ptr)&lt;br /&gt;
	add_prop_cat = utilities_page_ptr.add_prop_cat ;							-- import functions from selected Module:Citation/CS1/Utilities module&lt;br /&gt;
	is_set = utilities_page_ptr.is_set;&lt;br /&gt;
	in_array = utilities_page_ptr.in_array;&lt;br /&gt;
	set_message = utilities_page_ptr.set_message;&lt;br /&gt;
	substitute = utilities_page_ptr.substitute;&lt;br /&gt;
	wrap_style = utilities_page_ptr.wrap_style;&lt;br /&gt;
&lt;br /&gt;
	cfg = cfg_table_ptr;														-- import tables from selected Module:Citation/CS1/Configuration&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; E X P O R T E D   F U N C T I O N S &amp;gt;------------------------------------------&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
return {																		-- return exported functions&lt;br /&gt;
	dates = dates,&lt;br /&gt;
	year_date_check = year_date_check,&lt;br /&gt;
	reformat_dates = reformat_dates,&lt;br /&gt;
	date_hyphen_to_dash = date_hyphen_to_dash,&lt;br /&gt;
	date_name_xlate = date_name_xlate,&lt;br /&gt;
	edtf_transform = edtf_transform,&lt;br /&gt;
	set_selected_modules = set_selected_modules&lt;br /&gt;
	}&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Module:Citation/CS1/Configuration&amp;diff=137</id>
		<title>Module:Citation/CS1/Configuration</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Module:Citation/CS1/Configuration&amp;diff=137"/>
		<updated>2021-09-26T15:44:16Z</updated>

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

		<summary type="html">&lt;p&gt;Jayprakash12345: 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'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 = '';																-- 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 ('^%l%l%s*:%s*', '');								-- 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 = '';															-- 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 = ' ' .. 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'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'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'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'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'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's preference before the page is saved.  It&lt;br /&gt;
then searches the rendering for the text equivalent of the rendered equation and replaces the rendering with that so&lt;br /&gt;
that the page is saved without extraneous HTML/CSS markup and with a reasonably readable text form of the equation.&lt;br /&gt;
&lt;br /&gt;
When a replacement is made, this function returns true and the value with replacement; otherwise false and the initial&lt;br /&gt;
value.  To replace multipe equations it is necessary to call this function from within a loop.&lt;br /&gt;
&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local function coins_replace_math_stripmarker (value)&lt;br /&gt;
	local stripmarker = cfg.stripmarkers['math'];&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'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? ''? when math render error)&lt;br /&gt;
	&lt;br /&gt;
	if rendering:match ('alt=&amp;quot;[^&amp;quot;]+&amp;quot;') then										-- if PNG math option&lt;br /&gt;
		rendering = rendering:match ('alt=&amp;quot;([^&amp;quot;]+)&amp;quot;');							-- extract just the math text&lt;br /&gt;
	elseif rendering:match ('$%s+.+%s+%$') then									-- if TeX math option; $ is legit character that is escapes as \$&lt;br /&gt;
		rendering = rendering:match ('$%s+(.+)%s+%$')							-- extract just the math text&lt;br /&gt;
	elseif rendering:match ('&amp;lt;annotation[^&amp;gt;]+&amp;gt;.+&amp;lt;/annotation&amp;gt;') then			-- if MathML math option&lt;br /&gt;
		rendering = rendering:match ('&amp;lt;annotation[^&amp;gt;]+&amp;gt;(.+)&amp;lt;/annotation&amp;gt;')		-- 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'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['math'], &amp;quot;MATH RENDER ERROR&amp;quot;);			-- one or more couldn'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 ('&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;', &amp;quot;'%1&amp;quot;);	-- replace {{'}} or {{'s}} with simple apostrophe or apostrophe-s&lt;br /&gt;
	value = value:gsub ('&amp;amp;nbsp;', ' ');											-- replace &amp;amp;nbsp; entity with plain space&lt;br /&gt;
	value = value:gsub ('\226\128\138', ' ');									-- replace hair space with plain space&lt;br /&gt;
	if not mw.ustring.find (value, cfg.indic_script) then						-- don't remove zero-width joiner characters from indic script&lt;br /&gt;
		value = value:gsub ('&amp;amp;zwj;', '');										-- remove &amp;amp;zwj; entities&lt;br /&gt;
		value = mw.ustring.gsub (value, '[\226\128\141\226\128\139\194\173]', '');	-- remove zero-width joiner, zero-width space, soft hyphen&lt;br /&gt;
	end&lt;br /&gt;
	value = value:gsub ('[\009\010\013 ]+', ' ');								-- 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 'table' ~= type(data) or nil == next(data) then&lt;br /&gt;
		return '';&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 'ID_list' ~= k and 'Authors' ~= 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, '=', 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, {'arxiv', 'biorxiv', 'citeseerx', 'ssrn', 'journal', 'news', 'magazine'}) or (in_array (class, {'conference', 'interview', 'map', 'press release', 'web'}) and is_set(data.Periodical)) or &lt;br /&gt;
		('citation' == 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, {'arxiv', 'biorxiv', 'citeseerx', 'ssrn'}) 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 'conference' == 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 'web' == 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 'periodical' 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;								-- 'periodical' article titles&lt;br /&gt;
&lt;br /&gt;
																				-- these used only for periodicals&lt;br /&gt;
			OCinSoutput[&amp;quot;rft.ssn&amp;quot;] = data.Season;								-- keywords: winter, spring, summer, fall&lt;br /&gt;
			OCinSoutput[&amp;quot;rft.quarter&amp;quot;] = data.Quarter;							-- single digits 1-&amp;gt;first quarter, etc.&lt;br /&gt;
			OCinSoutput[&amp;quot;rft.chron&amp;quot;] = data.Chron;								-- free-form date components&lt;br /&gt;
			OCinSoutput[&amp;quot;rft.volume&amp;quot;] = data.Volume;							-- does not apply to books&lt;br /&gt;
			OCinSoutput[&amp;quot;rft.issue&amp;quot;] = data.Issue;&lt;br /&gt;
			OCinSoutput[&amp;quot;rft.pages&amp;quot;] = data.Pages;								-- also used in book metadata&lt;br /&gt;
&lt;br /&gt;
	elseif 'thesis' ~= class then												-- all others except cite thesis are treated as 'book' 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 'report' == class or 'techreport' == 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 'conference' == 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, {'book', 'citation', 'encyclopaedia', 'interview', 'map'}) 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 'map' == class or 'interview' == class then&lt;br /&gt;
					OCinSoutput[&amp;quot;rft.genre&amp;quot;] = 'unknown';						-- standalone map or interview&lt;br /&gt;
				else&lt;br /&gt;
					OCinSoutput[&amp;quot;rft.genre&amp;quot;] = 'book';							-- book and encyclopedia&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		else	-- {'audio-visual', 'AV-media-notes', 'DVD-notes', 'episode', 'interview', 'mailinglist', 'map', 'newsgroup', 'podcast', 'press release', 'serial', 'sign', 'speech', 'web'}&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['rft.inst'] = data.PublisherName;							-- book and dissertation&lt;br /&gt;
	end&lt;br /&gt;
	-- NB. Not currently supported are &amp;quot;info:ofi/fmt:kev:mtx:patent&amp;quot;, &amp;quot;info:ofi/fmt:kev:mtx:dc&amp;quot;, &amp;quot;info:ofi/fmt:kev:mtx:sch_svc&amp;quot;, &amp;quot;info:ofi/fmt:kev:mtx:ctx&amp;quot;&lt;br /&gt;
																				-- and now common parameters (as much as possible)&lt;br /&gt;
	OCinSoutput[&amp;quot;rft.date&amp;quot;] = data.Date;										-- book, journal, dissertation&lt;br /&gt;
&lt;br /&gt;
	for k, v in pairs( data.ID_list ) do										-- what to do about these? For now assume that they are common to all?&lt;br /&gt;
		if k == 'ISBN' 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 ) == 'info' 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 ) == 'rft' then						-- for isbn, issn, eissn, etc. that have defined COinS keywords&lt;br /&gt;
			OCinSoutput[ id ] = v;&lt;br /&gt;
		elseif 'url' == id then													-- for urls that are assembled in ~/Identifiers; |asin= and |ol=&lt;br /&gt;
			OCinSoutput[&amp;quot;rft_id&amp;quot;] = table.concat ({data.ID_list[k], &amp;quot;#id-name=&amp;quot;, cfg.id_handlers[k].label});&lt;br /&gt;
		elseif id then															-- when cfg.id_handlers[k].COinS is not nil so urls created here&lt;br /&gt;
			OCinSoutput[&amp;quot;rft_id&amp;quot;] = table.concat{ cfg.id_handlers[k].prefix, v, cfg.id_handlers[k].suffix or '', &amp;quot;#id-name=&amp;quot;, cfg.id_handlers[k].label };	-- others; provide a URL and indicate identifier name as #fragment (human-readable, but transparent to browsers)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local last, first;&lt;br /&gt;
	for k, v in ipairs( data.Authors ) do&lt;br /&gt;
		last, first = coins_cleanup (v.last), coins_cleanup (v.first or '');	-- replace any nowiki stripmarkers, non-printing or invisible characters&lt;br /&gt;
		if k == 1 then															-- for the first author name only&lt;br /&gt;
			if is_set(last) and is_set(first) then								-- set these COinS values if |first= and |last= specify the first author name&lt;br /&gt;
				OCinSoutput[&amp;quot;rft.aulast&amp;quot;] = last;								-- book, journal, dissertation&lt;br /&gt;
				OCinSoutput[&amp;quot;rft.aufirst&amp;quot;] = first;								-- book, journal, dissertation&lt;br /&gt;
			elseif is_set(last) then &lt;br /&gt;
				OCinSoutput[&amp;quot;rft.au&amp;quot;] = last;									-- book, journal, dissertation -- otherwise use this form for the first name&lt;br /&gt;
			end&lt;br /&gt;
		else																	-- for all other authors&lt;br /&gt;
			if is_set(last) and is_set(first) then&lt;br /&gt;
				OCinSoutput[&amp;quot;rft.au&amp;quot;] = table.concat{ last, &amp;quot;, &amp;quot;, first };		-- book, journal, dissertation&lt;br /&gt;
			elseif is_set(last) then&lt;br /&gt;
				OCinSoutput[&amp;quot;rft.au&amp;quot;] = last;									-- book, journal, dissertation&lt;br /&gt;
			end&lt;br /&gt;
			-- TODO: At present we do not report &amp;quot;et al.&amp;quot;. Add anything special if this condition applies?&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	OCinSoutput.rft_id = data.URL;&lt;br /&gt;
	OCinSoutput.rfr_id = table.concat{ &amp;quot;info:sid/&amp;quot;, mw.site.server:match( &amp;quot;[^/]*$&amp;quot; ), &amp;quot;:&amp;quot;, data.RawPage };&lt;br /&gt;
&lt;br /&gt;
	-- TODO: Add optional extra info:&lt;br /&gt;
	-- rfr_dat=#REVISION&amp;lt;version&amp;gt; (referrer private data)&lt;br /&gt;
	-- ctx_id=&amp;lt;data.RawPage&amp;gt;#&amp;lt;ref&amp;gt; (identifier for the context object)&lt;br /&gt;
	-- ctx_tim=&amp;lt;ts&amp;gt; (timestamp in format yyyy-mm-ddThh:mm:ssTZD or yyyy-mm-dd)&lt;br /&gt;
	-- ctx_enc=info:ofi/enc:UTF-8 (character encoding)&lt;br /&gt;
	&lt;br /&gt;
	OCinSoutput = setmetatable( OCinSoutput, nil );&lt;br /&gt;
&lt;br /&gt;
	-- sort with version string always first, and combine.&lt;br /&gt;
	-- table.sort( OCinSoutput );&lt;br /&gt;
	table.insert( OCinSoutput, 1, &amp;quot;ctx_ver=&amp;quot; .. ctx_ver ); -- such as &amp;quot;Z39.88-2004&amp;quot;&lt;br /&gt;
	return table.concat(OCinSoutput, &amp;quot;&amp;amp;&amp;quot;);&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S E T _ S E L E C T E D _ M O D U L E S &amp;gt;--------------------------------------&lt;br /&gt;
&lt;br /&gt;
Sets local cfg table and imported functions table to same (live or sandbox) as that used by the other modules.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function set_selected_modules (cfg_table_ptr, utilities_page_ptr)&lt;br /&gt;
	cfg = cfg_table_ptr;&lt;br /&gt;
&lt;br /&gt;
	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>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Module:Citation/CS1&amp;diff=133</id>
		<title>Module:Citation/CS1</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Module:Citation/CS1&amp;diff=133"/>
		<updated>2021-09-26T15:44:15Z</updated>

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

		<summary type="html">&lt;p&gt;Jayprakash12345: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Template:Short_description&amp;diff=129</id>
		<title>Template:Short description</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Template:Short_description&amp;diff=129"/>
		<updated>2021-09-26T15:44:14Z</updated>

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

		<summary type="html">&lt;p&gt;Jayprakash12345: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#if:{{{1|}}}| {{DISPLAYTITLE:{{{1}}}}} | __NOTITLE__}}&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Template:Row_numbers&amp;diff=125</id>
		<title>Template:Row numbers</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Template:Row_numbers&amp;diff=125"/>
		<updated>2021-09-26T15:44:14Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{{#invoke:row numbers|row_numbers|{{{1}}}|index={{{index|}}}}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Usage ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{{row numbers|&amp;lt;nowiki&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+test incrementor&lt;br /&gt;
!count !! lorem&lt;br /&gt;
|-&lt;br /&gt;
|_row_count || A&lt;br /&gt;
|-&lt;br /&gt;
|_row_count || B&lt;br /&gt;
|-&lt;br /&gt;
|_row_count || C&lt;br /&gt;
|-&lt;br /&gt;
| _row_count || D&lt;br /&gt;
|-&lt;br /&gt;
|_row_count || E&lt;br /&gt;
|}&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Output:-'''&lt;br /&gt;
{{row numbers|&amp;lt;nowiki&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+test incrementor&lt;br /&gt;
!count !! lorem&lt;br /&gt;
|-&lt;br /&gt;
|_row_count || A&lt;br /&gt;
|-&lt;br /&gt;
|_row_count || B&lt;br /&gt;
|-&lt;br /&gt;
|_row_count || C&lt;br /&gt;
|-&lt;br /&gt;
| _row_count || D&lt;br /&gt;
|-&lt;br /&gt;
|_row_count || E&lt;br /&gt;
|}&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Template:Right&amp;diff=123</id>
		<title>Template:Right</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Template:Right&amp;diff=123"/>
		<updated>2021-09-26T15:44:14Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{{{{{|safesubst:}}}#ifeq:{{{1|a}}}|{{{1|b}}}&lt;br /&gt;
|&amp;lt;span style=&amp;quot;float:right;&amp;quot;&amp;gt;{{{1|}}}&amp;lt;/span&amp;gt;&lt;br /&gt;
|style=&amp;quot;text-align:right&amp;quot;{{{{{|safesubst:}}}!}}[[Category:Pages using right with no input arguments]]&lt;br /&gt;
}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
== Usage ==&lt;br /&gt;
&amp;lt;nowiki&amp;gt;{{Right|This should be in right side}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:-&lt;br /&gt;
{{Right|This should be in right side}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Template:Reflist/styles.css&amp;diff=121</id>
		<title>Template:Reflist/styles.css</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Template:Reflist/styles.css&amp;diff=121"/>
		<updated>2021-09-26T15:44:14Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* {{pp|small=yes}} */&lt;br /&gt;
/* can we remove the font size declarations? .references gets a font-size in&lt;br /&gt;
 * common.css that is always 90, and there is nothing else in reflist out in&lt;br /&gt;
 * the wild. May affect column sizes.&lt;br /&gt;
 */&lt;br /&gt;
.reflist {&lt;br /&gt;
	font-size: 90%;            /* Default font-size */&lt;br /&gt;
	margin-bottom: 0.5em;&lt;br /&gt;
	list-style-type: decimal;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.reflist .references {&lt;br /&gt;
	font-size: 100%;           /* Reset font-size when nested in div.reflist */&lt;br /&gt;
	margin-bottom: 0;          /* Avoid double margin when nested in div.reflist */&lt;br /&gt;
	list-style-type: inherit;  /* Enable custom list style types */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* columns-2 and columns-3 are legacy for &amp;quot;2 or more&amp;quot; column view from when the&lt;br /&gt;
 * template was implemented with column-count.&lt;br /&gt;
 */&lt;br /&gt;
.reflist-columns-2 {&lt;br /&gt;
	column-width: 30em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.reflist-columns-3 {&lt;br /&gt;
	column-width: 25em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Reset top margin for lists embedded in columns */&lt;br /&gt;
.reflist-columns {&lt;br /&gt;
	margin-top: 0.3em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.reflist-columns ol {&lt;br /&gt;
	margin-top: 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Avoid elements breaking between columns */&lt;br /&gt;
.reflist-columns li {&lt;br /&gt;
	page-break-inside: avoid; /* Removed from CSS in favor of break-inside c. 2020 */&lt;br /&gt;
	break-inside: avoid-column;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.reflist-upper-alpha {&lt;br /&gt;
	list-style-type: upper-alpha;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.reflist-upper-roman {&lt;br /&gt;
	list-style-type: upper-roman;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.reflist-lower-alpha {&lt;br /&gt;
	list-style-type: lower-alpha;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.reflist-lower-greek {&lt;br /&gt;
	list-style-type: lower-greek;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.reflist-lower-roman {&lt;br /&gt;
	list-style-type: lower-roman;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Template:Reflist&amp;diff=119</id>
		<title>Template:Reflist</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Template:Reflist&amp;diff=119"/>
		<updated>2021-09-26T15:44:14Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;templatestyles src=&amp;quot;Reflist/styles.css&amp;quot; /&amp;gt;&amp;lt;div class=&amp;quot;reflist &amp;lt;!--&lt;br /&gt;
--&amp;gt;{{#if:{{{1|}}}{{{colwidth|}}}|reflist-columns references-column-width}} &amp;lt;!--&lt;br /&gt;
--&amp;gt;{{#switch:{{{group|}}}|upper-alpha|upper-roman|lower-alpha|lower-greek|lower-roman=reflist-{{{group}}}}} &amp;lt;!--&lt;br /&gt;
--&amp;gt;{{#if:{{{1|}}}|{{#iferror:{{#ifexpr: {{{1|1}}} &amp;gt; 1 }}||{{#switch:{{{1|}}}|1=|2=reflist-columns-2|#default=reflist-columns-3}} }}}}&amp;quot; &amp;lt;!-- end class&lt;br /&gt;
--&amp;gt;{{#if:{{{1|}}}{{{colwidth|}}}{{{liststyle|}}}|&amp;lt;!-- start style&lt;br /&gt;
--&amp;gt;style=&amp;quot;{{#if: {{{1|}}}&lt;br /&gt;
    | {{#iferror: {{#ifexpr: {{{1|1}}} &amp;gt; 1 }} |column-width: {{{1}}};}}&lt;br /&gt;
    | {{#if: {{{colwidth|}}}|column-width: {{{colwidth}}};}}&lt;br /&gt;
    }} &amp;lt;!--&lt;br /&gt;
--&amp;gt;{{#if:{{{group|}}}||{{#if:{{{liststyle|}}}|list-style-type: {{{liststyle}}};}}}}&amp;quot;&amp;lt;!--&lt;br /&gt;
--&amp;gt;}}&amp;gt;&lt;br /&gt;
{{#tag:references|{{{refs|}}}|group={{{group|}}}|responsive={{#if:{{{1|}}}{{{colwidth|}}}|0|1}}}}&amp;lt;/div&amp;gt;{{#invoke:Check for unknown parameters|check|unknown={{main other|[[Category:Pages using reflist with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Reflist]] with unknown parameter &amp;quot;_VALUE_&amp;quot;|ignoreblank=y| 1 | colwidth | group | liststyle | refs }}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
It is used for footnotes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Lorem ipsum.&amp;lt;ref&amp;gt;Source name, access date, etc.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Lorem ipsum dolor sit amet.&amp;lt;ref&amp;gt;Source name, access date, etc.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;References&lt;br /&gt;
{{Reflist}}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Output''':&lt;br /&gt;
&lt;br /&gt;
Lorem ipsum.&amp;lt;ref&amp;gt;Source name, access date, etc.&amp;lt;/ref&amp;gt;&lt;br /&gt;
Lorem ipsum dolor sit amet.&amp;lt;ref&amp;gt;Source name, access date, etc.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;References&lt;br /&gt;
{{Reflist}}&lt;br /&gt;
{{Reflist}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Template:Portal_dynamic_image/styles.css&amp;diff=117</id>
		<title>Template:Portal dynamic image/styles.css</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Template:Portal_dynamic_image/styles.css&amp;diff=117"/>
		<updated>2021-09-26T15:44:13Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;.dynamic-image-portal img{&lt;br /&gt;
 width:100%;&lt;br /&gt;
 height:auto;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Template:Portal_dynamic_image&amp;diff=115</id>
		<title>Template:Portal dynamic image</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Template:Portal_dynamic_image&amp;diff=115"/>
		<updated>2021-09-26T15:44:13Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;templatestyles src=&amp;quot;Portal dynamic image/styles.css&amp;quot;/&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;div class=&amp;quot;dynamic-image-portal&amp;quot; style=&amp;quot;width:{{{width|}}};{{#if:{{{center|}}}|margin:0 auto;|}}{{#if:{{{max-height|}}}|max-height:{{{max-height}}};|}}{{#if:{{{max-width|}}}|max-width:{{{max-width}}};|}}{{#if:{{{float|}}}|float:{{{float}}};|}}&amp;quot;&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;[[File:{{{1}}}|{{{caption| }}}]]&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Template:Poem2Open&amp;diff=113</id>
		<title>Template:Poem2Open</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Template:Poem2Open&amp;diff=113"/>
		<updated>2021-09-26T15:44:13Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;Poem2-Ekatra&amp;quot;&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Template:Poem2Close&amp;diff=111</id>
		<title>Template:Poem2Close</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Template:Poem2Close&amp;diff=111"/>
		<updated>2021-09-26T15:44:13Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Template:Markup2&amp;diff=109</id>
		<title>Template:Markup2</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Template:Markup2&amp;diff=109"/>
		<updated>2021-09-26T15:44:13Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#if: {{{t|}}}|'''{{{t|}}}'''&lt;br /&gt;
*&amp;lt;code&amp;gt;{{{m|}}}&amp;lt;/code&amp;gt;&lt;br /&gt;
:{{{r|}}}|*&amp;lt;code&amp;gt;{{{m|}}}&amp;lt;/code&amp;gt;&lt;br /&gt;
:{{{r|}}}}}{{#if: {{{m2|}}}|&lt;br /&gt;
*&amp;lt;code&amp;gt;{{{m2|}}}&amp;lt;/code&amp;gt;&lt;br /&gt;
:{{{r2|}}}}}{{#if: {{{m3|}}}|&lt;br /&gt;
*&amp;lt;code&amp;gt;{{{m3|}}}&amp;lt;/code&amp;gt;&lt;br /&gt;
:{{{r3|}}}}}{{#if: {{{m4|}}}|&lt;br /&gt;
*&amp;lt;code&amp;gt;{{{m4|}}}&amp;lt;/code&amp;gt;&lt;br /&gt;
:{{{r4|}}}}}{{#if: {{{m5|}}}|&lt;br /&gt;
*&amp;lt;code&amp;gt;{{{m5|}}}&amp;lt;/code&amp;gt;&lt;br /&gt;
:{{{r5|}}}}}&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Template:Markup&amp;diff=107</id>
		<title>Template:Markup</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Template:Markup&amp;diff=107"/>
		<updated>2021-09-26T15:44:13Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{| style=&amp;quot;width:{{{width|auto}}}; margin-top:0;margin-left:{{{margin-left|{{{margin|0}}}}}}; border-width:medium; padding:0; {{{style|}}}&amp;quot;&lt;br /&gt;
{{#if:{{{title|}}} |{{!}}+ '''{{{title}}}'''}}&lt;br /&gt;
{{#if:{{{noheaders|}}}{{{notitle|}}} |&lt;br /&gt;
 |!   scope=&amp;quot;col&amp;quot; style=&amp;quot;{{{colheaderstyle|}}}{{{col1headerstyle|}}}&amp;quot;{{!}} {{{col1|{{{t1|Markup}}}}}} {{!!}}&amp;lt;!--&lt;br /&gt;
   --&amp;gt;scope=&amp;quot;col&amp;quot; style=&amp;quot;{{{colheaderstyle|}}}{{{col2headerstyle|}}}&amp;quot;{{!}} {{{col2|{{{t2|Renders as}}}}}}&lt;br /&gt;
}}&amp;lt;!--&lt;br /&gt;
--&amp;gt;{{for loop||call=format item|pc1n=template|pc1v=Markup/row|pc2n=c1style|pc2v={{{col1style|{{{codestyle|{{{markupstyle|}}}}}}}}}|pc3n=c2style|pc3v={{{col2style|{{{outputstyle|}}}}}}|pv=item|{{item|c1={{{1|}}}|c2={{{2|}}}}}|{{item|c1={{{3|}}}|c2={{{4|}}}}}|{{item|c1={{{5|}}}|c2={{{6|}}}}}|{{item|c1={{{7|}}}|c2={{{8|}}}}}|{{item|c1={{{9|}}}|c2={{{10|}}}}}|{{item|c1={{{11|}}}|c2={{{12|}}}}}|{{item|c1={{{13|}}}|c2={{{14|}}}}}|{{item|c1={{{15|}}}|c2={{{16|}}}}}|{{item|c1={{{17|}}}|c2={{{18|}}}}}|{{item|c1={{{19|}}}|c2={{{20|}}}}}|{{item|c1={{{21|}}}|c2={{{22|}}}}}|{{item|c1={{{23|}}}|c2={{{24|}}}}}|{{item|c1={{{25|}}}|c2={{{26|}}}}}|{{item|c1={{{27|}}}|c2={{{28|}}}}}|{{item|c1={{{29|}}}|c2={{{30|}}}}}|{{item|c1={{{31|}}}|c2={{{32|}}}}}|{{item|c1={{{33|}}}|c2={{{34|}}}}}|{{item|c1={{{35|}}}|c2={{{36|}}}}}|{{item|c1={{{37|}}}|c2={{{38|}}}}}|{{item|c1={{{39|}}}|c2={{{40|}}}}}}}&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;border-width:1px;border-style: none none none;border-color:#ddd; padding:5px; vertical-align:top;&amp;quot;| &lt;br /&gt;
|style=&amp;quot;border-width:1px;border-style: none none none;border-color:#ddd; padding:5px; vertical-align:top;&amp;quot;| &lt;br /&gt;
|}&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Template:Legend/styles.css&amp;diff=105</id>
		<title>Template:Legend/styles.css</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Template:Legend/styles.css&amp;diff=105"/>
		<updated>2021-09-26T15:44:13Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* {{pp-template}} */&lt;br /&gt;
&lt;br /&gt;
.legend {&lt;br /&gt;
	page-break-inside: avoid;&lt;br /&gt;
	break-inside: avoid-column;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.legend-color {&lt;br /&gt;
	display: inline-block;&lt;br /&gt;
	min-width: 1.25em;&lt;br /&gt;
	height: 1.25em;&lt;br /&gt;
	line-height: 1.25;&lt;br /&gt;
	margin: 1px 0;&lt;br /&gt;
	text-align: center;&lt;br /&gt;
	border: 1px solid black;&lt;br /&gt;
	background-color: transparent;&lt;br /&gt;
	color: black;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.legend-text {/*empty for now, but part of the design!*/}&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Template:Infobox_person&amp;diff=103</id>
		<title>Template:Infobox person</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Template:Infobox_person&amp;diff=103"/>
		<updated>2021-09-26T15:44:12Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;table class=&amp;quot;infobox biography vcard&amp;quot;&amp;gt;&lt;br /&gt;
{{#if:{{{name|}}} | &amp;lt;tr&amp;gt;&amp;lt;td colspan='2' class=&amp;quot;infobox-heading-name&amp;quot;&amp;gt; {{{name}}}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;   }}&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td colspan='2'&amp;gt; [[{{{cover_image|File:No-Book.svg}}}|{{{cover_size|250px}}}|frameless|center|link={{{title}}}]] &amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
{{#if:{{{caption|}}} | &amp;lt;tr&amp;gt;&amp;lt;td colspan='2' class=&amp;quot;infobox-heading-caption&amp;quot;&amp;gt; {{{caption}}}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;   }}&lt;br /&gt;
{{#if:{{{birth_date|}}} | &amp;lt;tr&amp;gt;&amp;lt;th &amp;gt;જન્મતારીખ &amp;lt;/td&amp;gt; &amp;lt;td&amp;gt;{{{birth_date|}}}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;   }}&lt;br /&gt;
{{#if:{{{birth_place|}}} | &amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;જન્મસ્થળ&amp;lt;/td&amp;gt; &amp;lt;td&amp;gt;{{{birth_place|}}}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;   }}&lt;br /&gt;
{{#if:{{{death|}}} | &amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;અવસાન&amp;lt;/td&amp;gt; &amp;lt;td&amp;gt;{{{death|}}}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;   }}&lt;br /&gt;
{{#if:{{{study|}}} | &amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;અભ્યાસ&amp;lt;/td&amp;gt; &amp;lt;td&amp;gt;{{{study|}}}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;   }}&lt;br /&gt;
{{#if:{{{activity|}}} | &amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;પ્રવૃત્તિ&amp;lt;/td&amp;gt; &amp;lt;td&amp;gt;{{{activity|}}}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;   }}&lt;br /&gt;
{{#if:{{{address|}}} | &amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;સરનામું&amp;lt;/td&amp;gt; &amp;lt;td&amp;gt;{{{address|}}}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;   }}&lt;br /&gt;
{{#if:{{{moreinfo|}}} | &amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;વિશેષ નોંધ&amp;lt;/td&amp;gt; &amp;lt;td&amp;gt;{{{moreinfo|}}}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;   }}&lt;br /&gt;
{{#if:{{{significant_works|}}} | &amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;નોંધપાત્ર કૃતિઓ&amp;lt;/td&amp;gt; &amp;lt;td&amp;gt;{{{significant_works|}}}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;   }}&lt;br /&gt;
{{#if:{{{significant_award|}}} | &amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;નોંધપાત્ર એવોર્ડ&amp;lt;/td&amp;gt; &amp;lt;td&amp;gt;{{{significant_award|}}}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;   }}&lt;br /&gt;
{{#if:{{{signature|}}} | &amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;હસ્તાક્ષર&amp;lt;/td&amp;gt; &amp;lt;td&amp;gt;{{{signature|}}}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;   }}&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Template:Heading&amp;diff=101</id>
		<title>Template:Heading</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Template:Heading&amp;diff=101"/>
		<updated>2021-09-26T15:44:12Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&amp;lt;div class=&amp;quot;heading-detail-page center&amp;quot; &amp;gt;&amp;lt;span style=&amp;quot;color: #7A1C21;font-size: 1.6em;font-family: Ekatra;border-bottom: 1px #d2d2d2 solid&amp;quot;&amp;gt;'''{{{1}}}'''&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{#if:{{{2|}}} |  &amp;lt;span style=&amp;quot;color: #7A1C21;font-size: 1.1em;font-family: Ekatra;border-bottom: 1px #d2d2d2 solid&amp;quot;&amp;gt;{{{2}}}&amp;lt;/span&amp;gt;}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Template:HeaderNav2&amp;diff=99</id>
		<title>Template:HeaderNav2</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Template:HeaderNav2&amp;diff=99"/>
		<updated>2021-09-26T15:44:12Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Header/main block&lt;br /&gt;
 | style = border:1px solid green; background-color: #eee;&lt;br /&gt;
 | previous = {{#if: {{{previous|}}} | [[{{#titleparts:{{FULLPAGENAME}}| -1}}/{{{previous}}}|{{{previous}}}]] | }}&lt;br /&gt;
 | next =  {{#if: {{{next|}}} | [[{{#titleparts:{{FULLPAGENAME}}| -1}}/{{{next}}}|{{{next}}}]] | }}&lt;br /&gt;
 | title =&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Template:HeaderNav&amp;diff=97</id>
		<title>Template:HeaderNav</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Template:HeaderNav&amp;diff=97"/>
		<updated>2021-09-26T15:44:12Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Header/main block&lt;br /&gt;
 | style = border:1px solid green; background-color: #eee;&lt;br /&gt;
 | previous = {{{previous|}}}&lt;br /&gt;
 | next = {{{next|}}}&lt;br /&gt;
 | title =&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Template:Header/notes_block&amp;diff=95</id>
		<title>Template:Header/notes block</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Template:Header/notes_block&amp;diff=95"/>
		<updated>2021-09-26T15:44:12Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&amp;lt;div &amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
  --&amp;gt;{{#if:{{{id|}}}|id=&amp;quot;{{{id}}}&amp;quot;}} &amp;lt;!--&lt;br /&gt;
  --&amp;gt;class=&amp;quot;header_notes searchaux {{{class|}}}&amp;quot; &amp;lt;!--&lt;br /&gt;
  --&amp;gt;style=&amp;quot;display: table; border-collapse: collapse; border-spacing: 0; empty-cells: hide; font-size: 0.9em; line-height:1.4; margin: 0 auto 4px auto; width: 100%; {{{style|}}}&amp;quot; &amp;lt;!--&lt;br /&gt;
  --&amp;gt;&amp;gt;&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
  --&amp;gt;{{#if:{{{sister|}}}|{{{sister}}}}}&amp;lt;!--&lt;br /&gt;
  --&amp;gt;{{#if:{{{shortcut|}}}|{{shortcut|{{{shortcut}}}}}}}&amp;lt;!--&lt;br /&gt;
  --&amp;gt;{{#if:{{{content|}}}|&amp;lt;!--&lt;br /&gt;
    --&amp;gt;&amp;lt;div class=&amp;quot;header_notes_content&amp;quot;&amp;gt;&lt;br /&gt;
{{{content|}}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;!--&lt;br /&gt;
  --&amp;gt;}}&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
	<entry>
		<id>https://sureshjoshi.org/index.php?title=Template:Header/main_block&amp;diff=93</id>
		<title>Template:Header/main block</title>
		<link rel="alternate" type="text/html" href="https://sureshjoshi.org/index.php?title=Template:Header/main_block&amp;diff=93"/>
		<updated>2021-09-26T15:44:12Z</updated>

		<summary type="html">&lt;p&gt;Jayprakash12345: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div &amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
  --&amp;gt;{{#if:{{{id|}}}|id=&amp;quot;{{{id}}}&amp;quot; &amp;lt;!--&lt;br /&gt;
  --&amp;gt;class=&amp;quot;header-mainblock {{{class|}}}&amp;quot;&amp;lt;!--&lt;br /&gt;
  --&amp;gt;style=&amp;quot;margin:4px auto 4px auto; padding: 0 3px; display:flex; align-items:center; {{{style}}}&amp;quot;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;gt;&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
  -------------------------------------------------------------------------------------------------------&lt;br /&gt;
  --&amp;gt;{{#if:{{{previous|}}}{{{next|}}}|&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
    --&amp;gt;&amp;lt;div class=&amp;quot;gen_header_backlink searchaux&amp;quot; style=&amp;quot;flex-grow:1; display:flex; align-items:center;&amp;quot;&amp;gt;&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
      --&amp;gt;{{#if:{{{previous|}}}|&amp;lt;!--&lt;br /&gt;
        --&amp;gt;&amp;lt;div&amp;gt;←&amp;lt;/div&amp;gt;&amp;lt;!--&lt;br /&gt;
        --&amp;gt;&amp;lt;div id=&amp;quot;headerprevious&amp;quot;&amp;gt;{{{previous}}}&amp;lt;/div&amp;gt;&amp;lt;!--&lt;br /&gt;
      --&amp;gt;|&amp;amp;nbsp;}}&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
    close prev div--&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&amp;lt;!--&lt;br /&gt;
  --&amp;gt;}}&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
  -------------------------------------------------------------------------------------------------------&lt;br /&gt;
  Main central cell&lt;br /&gt;
  --&amp;gt;&amp;lt;div class=&amp;quot;gen_header_title&amp;quot; style=&amp;quot;flex-grow:4; text-align:center;&amp;quot;&amp;gt;&amp;lt;!--&lt;br /&gt;
    --&amp;gt;{{{title|}}}&amp;lt;!--&lt;br /&gt;
  End main cell&lt;br /&gt;
  --&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
  -------------------------------------------------------------------------------------------------------&lt;br /&gt;
  Next page link&lt;br /&gt;
  --&amp;gt;{{#if:{{{previous|}}}{{{next|}}}|&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
    --&amp;gt;&amp;lt;div class=&amp;quot;gen_header_forelink searchaux&amp;quot; style=&amp;quot;flex-grow:1; justify-content: flex-end; display:flex; align-items:center; text-align:right;&amp;quot;&amp;gt;&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
    --&amp;gt;{{#if:{{{next|}}}|&amp;lt;!--&lt;br /&gt;
      --&amp;gt;&amp;lt;div id=&amp;quot;headernext&amp;quot;&amp;gt;{{{next}}}&amp;lt;/div&amp;gt;&amp;lt;!--&lt;br /&gt;
      --&amp;gt;&amp;lt;div&amp;gt;→&amp;lt;/div&amp;gt;&amp;lt;!--&lt;br /&gt;
    --&amp;gt;|&amp;amp;nbsp;}}&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
    close next div --&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&amp;lt;!--&lt;br /&gt;
  --&amp;gt;}}&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
  -------------------------------------------------------------------------------------------------------&lt;br /&gt;
end of outer div&lt;br /&gt;
--&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jayprakash12345</name></author>
	</entry>
</feed>