<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.tiffa.net/w/index.php?action=history&amp;feed=atom&amp;title=Module%3ACategory_described_in_year</id>
	<title>Module:Category described in year - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.tiffa.net/w/index.php?action=history&amp;feed=atom&amp;title=Module%3ACategory_described_in_year"/>
	<link rel="alternate" type="text/html" href="https://wiki.tiffa.net/w/index.php?title=Module:Category_described_in_year&amp;action=history"/>
	<updated>2026-04-13T20:22:21Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.0</generator>
	<entry>
		<id>https://wiki.tiffa.net/w/index.php?title=Module:Category_described_in_year&amp;diff=140179&amp;oldid=prev</id>
		<title>Fire: Created page with &quot;require(&#039;strict&#039;)  --========================================================================== --                             Local functions                               --==========================================================================  local function addOrd( i ) --12 -&gt; 12th, etc. 	if tonumber(i) then 		local s = tostring(i) 		local  tens = string.match(s, &#039;1%d$&#039;) 		local  ones = string.match(s,  &#039;%d$&#039;) 		if     tens        then return s..&#039;th&#039;...&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.tiffa.net/w/index.php?title=Module:Category_described_in_year&amp;diff=140179&amp;oldid=prev"/>
		<updated>2024-04-16T22:58:31Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;require(&amp;#039;strict&amp;#039;)  --&lt;a href=&quot;/w/index.php?title=%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;========================================================================== (page does not exist)&quot;&gt;==========================================================================&lt;/a&gt; --&lt;a href=&quot;/w/index.php?title=Local_functions&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;Local functions (page does not exist)&quot;&gt;Local functions                              &lt;/a&gt; --&lt;a href=&quot;/w/index.php?title=%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D%3D&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;========================================================================== (page does not exist)&quot;&gt;==========================================================================&lt;/a&gt;  local function addOrd( i ) --12 -&amp;gt; 12th, etc. 	if tonumber(i) then 		local s = tostring(i) 		local  tens = string.match(s, &amp;#039;1%d$&amp;#039;) 		local  ones = string.match(s,  &amp;#039;%d$&amp;#039;) 		if     tens        then return s..&amp;#039;th&amp;#039;...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;require(&amp;#039;strict&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
--[[==========================================================================]]&lt;br /&gt;
--[[                             Local functions                              ]]&lt;br /&gt;
--[[==========================================================================]]&lt;br /&gt;
&lt;br /&gt;
local function addOrd( i ) --12 -&amp;gt; 12th, etc.&lt;br /&gt;
	if tonumber(i) then&lt;br /&gt;
		local s = tostring(i)&lt;br /&gt;
		local  tens = string.match(s, &amp;#039;1%d$&amp;#039;)&lt;br /&gt;
		local  ones = string.match(s,  &amp;#039;%d$&amp;#039;)&lt;br /&gt;
		if     tens        then return s..&amp;#039;th&amp;#039;&lt;br /&gt;
		elseif ones == &amp;#039;1&amp;#039; then return s..&amp;#039;st&amp;#039;&lt;br /&gt;
		elseif ones == &amp;#039;2&amp;#039; then return s..&amp;#039;nd&amp;#039;&lt;br /&gt;
		elseif ones == &amp;#039;3&amp;#039; then return s..&amp;#039;rd&amp;#039;&lt;br /&gt;
		elseif ones ~= nil then return s..&amp;#039;th&amp;#039;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return &amp;#039;&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function isNilOrEmpty( thing )&lt;br /&gt;
	return (thing == nil or thing == &amp;#039;&amp;#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
--[[==========================================================================]]&lt;br /&gt;
--[[                            External function                             ]]&lt;br /&gt;
--[[==========================================================================]]&lt;br /&gt;
&lt;br /&gt;
function p.autodetect( frame )&lt;br /&gt;
	local conf = require( &amp;#039;Module:Category described in year/conf&amp;#039; ) --configuration module&lt;br /&gt;
	local commonsLink = require(&amp;#039;Module:Commons link&amp;#039;)&lt;br /&gt;
	local currentTitle = mw.title.getCurrentTitle()&lt;br /&gt;
	local parentArg = frame:getParent().args[1] --accept 1 unnamed category parameter if not in category namespace; required for testing/doc/etc. purposes&lt;br /&gt;
	local header = &amp;#039; &amp;#039; --header template(s), nav bar, and category description text; whitespace-initialized for convenience&lt;br /&gt;
	local nav = nil&lt;br /&gt;
	local portal = nil --for {{Portal|...}}&lt;br /&gt;
	local commons = nil --for {{Commons|...}}&lt;br /&gt;
	local wikispecies = nil --for {{Wikispecies|...}}&lt;br /&gt;
	local description = nil&lt;br /&gt;
	local toc = nil&lt;br /&gt;
	local categories = {}&lt;br /&gt;
	local trackingCats = {&lt;br /&gt;
		[1] = &amp;#039;&amp;#039;, --placeholder for [[Category:Described in year unknown category]]&lt;br /&gt;
		[2] = &amp;#039;&amp;#039;, --placeholder for [[Category:Described in year error]]&lt;br /&gt;
	}&lt;br /&gt;
	local outString = nil&lt;br /&gt;
	local bConfError = false&lt;br /&gt;
	&lt;br /&gt;
	--prelim namespace/title determination&lt;br /&gt;
	local currCat = nil&lt;br /&gt;
	local currQID = nil&lt;br /&gt;
	if currentTitle.namespace == 14 then --category namespace&lt;br /&gt;
		currCat = currentTitle.text --without namespace nor interwiki prefixes&lt;br /&gt;
		currQID = mw.wikibase.getEntityIdForCurrentPage()&lt;br /&gt;
	else&lt;br /&gt;
		if parentArg then&lt;br /&gt;
			currCat = mw.ustring.gsub(parentArg, &amp;#039;Category:&amp;#039;, &amp;#039;&amp;#039;)&lt;br /&gt;
			currQID = mw.wikibase.getEntityIdForTitle(&amp;#039;Category:&amp;#039;..currCat)&lt;br /&gt;
		else --currQID &amp;amp; currCat both nil&lt;br /&gt;
			if currentTitle.fullText ~= &amp;#039;Template:Category described in year&amp;#039; then --ignore self...&lt;br /&gt;
				trackingCats[2] = &amp;#039;[[Category:Described in year error|P]]&amp;#039; --missing a category parameter outside category namespace&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	--find commons &amp;amp; wikispecies link(s); produce {{Commons and category}} and/or {{Wikispecies}} template(s)&lt;br /&gt;
	if currQID then&lt;br /&gt;
		if commonsLink._hasGallery(currQID) or commonsLink._hasCategory(currQID) then&lt;br /&gt;
			commons = frame:expandTemplate{ title = &amp;#039;Commons and category&amp;#039;, args = { qid=currQID }}&lt;br /&gt;
		end&lt;br /&gt;
		local currEntity = mw.wikibase.getEntity(currQID)&lt;br /&gt;
		if currEntity then&lt;br /&gt;
			--check &amp;quot;Other sites&amp;quot; sitelinks for Wikispecies&lt;br /&gt;
			local currSiteLinks = currEntity.sitelinks&lt;br /&gt;
			if currSiteLinks then&lt;br /&gt;
				local currSpeciesWiki = currEntity.sitelinks.specieswiki&lt;br /&gt;
				if currSpeciesWiki then&lt;br /&gt;
					local currSpeciesWikiTitle = currSpeciesWiki.title&lt;br /&gt;
					if currSpeciesWikiTitle then&lt;br /&gt;
						wikispecies = frame:expandTemplate{ title = &amp;#039;Wikispecies&amp;#039;, args = { currSpeciesWikiTitle } }&lt;br /&gt;
	end	end	end	end	end&lt;br /&gt;
	&lt;br /&gt;
	--[[======================================================================]]&lt;br /&gt;
	--[[                                 Main                                 ]]&lt;br /&gt;
	--[[======================================================================]]&lt;br /&gt;
	if currCat then&lt;br /&gt;
		&lt;br /&gt;
		--determine current/related/adjacent cats&amp;#039; properties/vars/etc.&lt;br /&gt;
		local currGroup = mw.ustring.match(currCat, &amp;#039;^([%w ]+) described in&amp;#039;) --Bacteria/Plants/etc.&lt;br /&gt;
		if isNilOrEmpty(currGroup) then currGroup = mw.ustring.match(currCat, &amp;#039;^([%w ]+) by year of formal description&amp;#039;) end&lt;br /&gt;
		if conf[currGroup] == nil then conf[currGroup] = conf[&amp;#039;Default&amp;#039;] end --default to Default&lt;br /&gt;
		local currYDCF = nil --possible future values: year/decade/century/formal&lt;br /&gt;
		local currYear = mw.ustring.match(currCat, &amp;#039;described in (%d%d%d%d)$&amp;#039;)&lt;br /&gt;
		local currDeca = mw.ustring.match(currCat, &amp;#039;described in the (%d%d%d%d)s$&amp;#039;) --deprecated&lt;br /&gt;
		local currCent = mw.ustring.match(currCat, &amp;#039;described in the (%d+)[snrt][tdh] century$&amp;#039;)&lt;br /&gt;
		local currFrml = mw.ustring.match(currCat, &amp;#039;by year of (formal) description$&amp;#039;)&lt;br /&gt;
		local parentCent = nil --used with currYear&lt;br /&gt;
		local minYear = tonumber(conf[currGroup].minyear)&lt;br /&gt;
		if minYear == nil or &lt;br /&gt;
		  (minYear and (minYear &amp;lt;= 1700 or minYear &amp;gt;= 2000)) then&lt;br /&gt;
			minYear = 1758 --default to 1758 per ICZN Art. 5&lt;br /&gt;
		end&lt;br /&gt;
		if currYear then&lt;br /&gt;
			currYDCF = &amp;#039;year&amp;#039;&lt;br /&gt;
			if mw.ustring.match(currYear, &amp;#039;^%d%d00&amp;#039;) then --1900 in 19th century&lt;br /&gt;
				parentCent = mw.ustring.match(currYear, &amp;#039;^%d%d&amp;#039;)&lt;br /&gt;
			else --1901 in 20th century&lt;br /&gt;
				parentCent = 1 + mw.ustring.match(currYear, &amp;#039;^%d%d&amp;#039;)&lt;br /&gt;
			end&lt;br /&gt;
		elseif currDeca then&lt;br /&gt;
			currYDCF = &amp;#039;decade&amp;#039;&lt;br /&gt;
			bConfError = true&lt;br /&gt;
			trackingCats[2] = &amp;#039;[[Category:Described in year error|D]]&amp;#039; --invalid decade-parent (deprecated)&lt;br /&gt;
		elseif currCent then&lt;br /&gt;
			currYDCF = &amp;#039;century&amp;#039;&lt;br /&gt;
		elseif currFrml then&lt;br /&gt;
			currYDCF = &amp;#039;formal&amp;#039;&lt;br /&gt;
		else&lt;br /&gt;
			bConfError = true&lt;br /&gt;
			trackingCats[2] = &amp;#039;[[Category:Described in year error|N]]&amp;#039; --invalid category name&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		--conf error checkng (missing keys)&lt;br /&gt;
		--Numeric sortkeys are unfortunately grouped together under &amp;quot;0-9&amp;quot;.&lt;br /&gt;
		--Check phab T203355 (Magic word to force category number headings instead of 0-9).&lt;br /&gt;
		if bConfError == false then&lt;br /&gt;
			if conf[currGroup] == nil then&lt;br /&gt;
				bConfError = true&lt;br /&gt;
				trackingCats[2] = &amp;#039;[[Category:Described in year error|1]]&amp;#039; --group (Bacteria/Plants/etc.) key missing from conf&lt;br /&gt;
			elseif conf[currGroup][currYDCF] == nil then&lt;br /&gt;
				bConfError = true&lt;br /&gt;
				trackingCats[2] = &amp;#039;[[Category:Described in year error|2]]&amp;#039; --year/century/formal key missing&lt;br /&gt;
			else&lt;br /&gt;
				if conf[currGroup][currYDCF].description == nil then&lt;br /&gt;
					bConfError = true&lt;br /&gt;
					trackingCats[2] = &amp;#039;[[Category:Described in year error|3]]&amp;#039; --description key missing&lt;br /&gt;
				end&lt;br /&gt;
				if conf[currGroup][currYDCF].parent1 == nil then&lt;br /&gt;
					bConfError = true&lt;br /&gt;
					trackingCats[2] = &amp;#039;[[Category:Described in year error|4]]&amp;#039; --parent key missing&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		if bConfError == false then&lt;br /&gt;
			--produce portal&lt;br /&gt;
			if currGroup == &amp;#039;Fossil taxa&amp;#039; or currGroup == &amp;#039;Fossil parataxa&amp;#039; then&lt;br /&gt;
				portal = frame:expandTemplate{ title = &amp;#039;Portal&amp;#039;, args = { &amp;#039;Paleontology&amp;#039; } }&lt;br /&gt;
			end&lt;br /&gt;
			&lt;br /&gt;
			--produce description, evaluate %variables%&lt;br /&gt;
			description = conf[currGroup][currYDCF].description&lt;br /&gt;
			if mw.ustring.match(description, &amp;#039;%%year%%&amp;#039;) then&lt;br /&gt;
				if currYear then description = mw.ustring.gsub(description, &amp;#039;%%year%%&amp;#039;, currYear) --&amp;quot;2011&amp;quot;&lt;br /&gt;
				else description = mw.ustring.gsub(description, &amp;#039;%%year%%&amp;#039;, &amp;#039;this year&amp;#039;) end&lt;br /&gt;
			end&lt;br /&gt;
			if mw.ustring.match(description, &amp;#039;%%century%%&amp;#039;) then&lt;br /&gt;
				if currCent then description = mw.ustring.gsub(description, &amp;#039;%%century%%&amp;#039;, addOrd(currCent)) --&amp;quot;21st&amp;quot;&lt;br /&gt;
				else description = mw.ustring.gsub(description, &amp;#039;%%century%%&amp;#039;, &amp;#039;this century&amp;#039;) end&lt;br /&gt;
			end&lt;br /&gt;
			&lt;br /&gt;
			--produce cats &amp;amp; navs&lt;br /&gt;
			local iparent = 1&lt;br /&gt;
			local parenti = &amp;#039;parent&amp;#039;..iparent&lt;br /&gt;
			local sortkeyi = &amp;#039;sortkey&amp;#039;..iparent&lt;br /&gt;
			while conf[currGroup][currYDCF][parenti] do&lt;br /&gt;
				local parent = conf[currGroup][currYDCF][parenti]&lt;br /&gt;
				local sortkey = conf[currGroup][currYDCF][sortkeyi]&lt;br /&gt;
				&lt;br /&gt;
				--[[========================== Year ==========================]]&lt;br /&gt;
				if currYDCF == &amp;#039;year&amp;#039; then&lt;br /&gt;
					if nav == nil then&lt;br /&gt;
						local args = { [&amp;#039;min&amp;#039;] = minYear, [&amp;#039;skip-gaps&amp;#039;] = &amp;#039;yes&amp;#039; }&lt;br /&gt;
						if parentArg and currentTitle.namespace ~= 14 then&lt;br /&gt;
							args[&amp;#039;testcase&amp;#039;] = parentArg&lt;br /&gt;
						end&lt;br /&gt;
						nav = frame:expandTemplate{ title = &amp;#039;Category series navigation&amp;#039;, args = args }&lt;br /&gt;
					end&lt;br /&gt;
					if parent == &amp;#039;century&amp;#039; then&lt;br /&gt;
						if isNilOrEmpty(sortkey) then sortkey = currYear end --default to currYear&lt;br /&gt;
						categories[iparent] = &amp;#039;[[Category:&amp;#039;..currGroup..&amp;#039; described in the &amp;#039;..addOrd(parentCent)..&amp;#039; century|&amp;#039;..sortkey..&amp;#039;]]&amp;#039;&lt;br /&gt;
						&lt;br /&gt;
					elseif parent == &amp;#039;biology&amp;#039; then&lt;br /&gt;
						if isNilOrEmpty(sortkey) then sortkey = &amp;#039;&amp;#039; --default to none&lt;br /&gt;
						else sortkey = &amp;#039;|&amp;#039;..sortkey end&lt;br /&gt;
						if tonumber(currYear) &amp;lt; 1865 then&lt;br /&gt;
							categories[iparent] = &amp;#039;[[Category:&amp;#039;..currYear..&amp;#039; in science&amp;#039;..sortkey..&amp;#039;]]&amp;#039; --biology cat structure doesn&amp;#039;t exist pre-1865, as of 10/2018&lt;br /&gt;
						else&lt;br /&gt;
							categories[iparent] = &amp;#039;[[Category:&amp;#039;..currYear..&amp;#039; in biology&amp;#039;..sortkey..&amp;#039;]]&amp;#039; --if/when all biology cats exists, merge this elseif with &amp;#039;paleontology&amp;#039;&lt;br /&gt;
						end&lt;br /&gt;
						&lt;br /&gt;
					elseif parent == &amp;#039;paleontology&amp;#039; then&lt;br /&gt;
						if isNilOrEmpty(sortkey) then sortkey = &amp;#039;&amp;#039; --default to none&lt;br /&gt;
						else sortkey = &amp;#039;|&amp;#039;..sortkey end&lt;br /&gt;
						categories[iparent] = &amp;#039;[[Category:&amp;#039;..currYear..&amp;#039; in &amp;#039;..parent..sortkey..&amp;#039;]]&amp;#039;&lt;br /&gt;
						&lt;br /&gt;
					elseif parent == &amp;#039;environment&amp;#039; then&lt;br /&gt;
						if isNilOrEmpty(sortkey) then sortkey = &amp;#039;&amp;#039; --default to none&lt;br /&gt;
						else sortkey = &amp;#039;|&amp;#039;..sortkey end&lt;br /&gt;
						categories[iparent] = &amp;#039;[[Category:&amp;#039;..currYear..&amp;#039; in the environment&amp;#039;..sortkey..&amp;#039;]]&amp;#039;&lt;br /&gt;
						&lt;br /&gt;
					elseif mw.ustring.match(parent, &amp;#039;^%u[%l ]+&amp;#039;) then --e.g. Animals/Insects/Fossil taxa&lt;br /&gt;
						if isNilOrEmpty(sortkey) then sortkey = &amp;#039;&amp;#039; --default to none&lt;br /&gt;
						else sortkey = &amp;#039;|&amp;#039;..sortkey end&lt;br /&gt;
						categories[iparent] = &amp;#039;[[Category:&amp;#039;..parent..&amp;#039; described in &amp;#039;..currYear..sortkey..&amp;#039;]]&amp;#039;&lt;br /&gt;
						&lt;br /&gt;
					else&lt;br /&gt;
						trackingCats[2] = &amp;#039;[[Category:Described in year error|Y]]&amp;#039; --invalid year-parent&lt;br /&gt;
					end&lt;br /&gt;
					&lt;br /&gt;
				--[[======================== Century =========================]]&lt;br /&gt;
				elseif currYDCF == &amp;#039;century&amp;#039; then&lt;br /&gt;
					if nav == nil then&lt;br /&gt;
						local args = {}&lt;br /&gt;
						if parentArg and currentTitle.namespace ~= 14 then&lt;br /&gt;
							args[&amp;#039;testcase&amp;#039;] = parentArg&lt;br /&gt;
						end&lt;br /&gt;
						nav = frame:expandTemplate{ title = &amp;#039;Container category&amp;#039; } .. &lt;br /&gt;
							  frame:expandTemplate{ title = &amp;#039;Category series navigation&amp;#039;, args = args }&lt;br /&gt;
					end&lt;br /&gt;
					if parent == &amp;#039;formal&amp;#039; then&lt;br /&gt;
						if isNilOrEmpty(sortkey) then sortkey = addOrd(currCent) end --default to currCent&lt;br /&gt;
						categories[iparent] = &amp;#039;[[Category:&amp;#039;..currGroup..&amp;#039; by year of formal description|&amp;#039;..sortkey..&amp;#039;]]&amp;#039;&lt;br /&gt;
						&lt;br /&gt;
					elseif parent == &amp;#039;biology&amp;#039; then&lt;br /&gt;
						if isNilOrEmpty(sortkey) then sortkey = &amp;#039;&amp;#039; --default to none&lt;br /&gt;
						else sortkey = &amp;#039;|&amp;#039;..sortkey end&lt;br /&gt;
						if tonumber(currCent) &amp;lt; 19 then&lt;br /&gt;
							categories[iparent] = &amp;#039;[[Category:&amp;#039;..addOrd(currCent)..&amp;#039; century in science&amp;#039;..sortkey..&amp;#039;]]&amp;#039; --biology cat structure doesn&amp;#039;t exist pre-1865, as of 10/2018&lt;br /&gt;
						else&lt;br /&gt;
							categories[iparent] = &amp;#039;[[Category:&amp;#039;..addOrd(currCent)..&amp;#039; century in biology&amp;#039;..sortkey..&amp;#039;]]&amp;#039; --if/when all biology cats exists, merge this elseif with &amp;#039;paleontology&amp;#039;&lt;br /&gt;
						end&lt;br /&gt;
						&lt;br /&gt;
					elseif parent == &amp;#039;paleontology&amp;#039; then&lt;br /&gt;
						if isNilOrEmpty(sortkey) then sortkey = &amp;#039;&amp;#039; --default to none&lt;br /&gt;
						else sortkey = &amp;#039;|&amp;#039;..sortkey end&lt;br /&gt;
						categories[iparent] = &amp;#039;[[Category:&amp;#039;..addOrd(currCent)..&amp;#039; century in &amp;#039;..parent..sortkey..&amp;#039;]]&amp;#039;&lt;br /&gt;
						&lt;br /&gt;
					elseif parent == &amp;#039;environment&amp;#039; then&lt;br /&gt;
						if isNilOrEmpty(sortkey) then sortkey = &amp;#039;&amp;#039; --default to none&lt;br /&gt;
						else sortkey = &amp;#039;|&amp;#039;..sortkey end&lt;br /&gt;
						categories[iparent] = &amp;#039;[[Category:&amp;#039;..addOrd(currCent)..&amp;#039; century in the environment&amp;#039;..sortkey..&amp;#039;]]&amp;#039;&lt;br /&gt;
						&lt;br /&gt;
					elseif mw.ustring.match(parent, &amp;#039;^%u[%l ]+&amp;#039;) then --e.g. Animals/Insects/Fossil taxa&lt;br /&gt;
						if isNilOrEmpty(sortkey) then sortkey = &amp;#039;&amp;#039; --default to none&lt;br /&gt;
						else sortkey = &amp;#039;|&amp;#039;..sortkey end&lt;br /&gt;
						categories[iparent] = &amp;#039;[[Category:&amp;#039;..parent..&amp;#039; described in the &amp;#039;..addOrd(currCent)..&amp;#039; century&amp;#039;..sortkey..&amp;#039;]]&amp;#039;&lt;br /&gt;
						&lt;br /&gt;
					else&lt;br /&gt;
						trackingCats[2] = &amp;#039;[[Category:Described in year error|C]]&amp;#039; --invalid century-parent&lt;br /&gt;
					end&lt;br /&gt;
					&lt;br /&gt;
				--[[======================== Formal ==========================]]&lt;br /&gt;
				elseif currYDCF == &amp;#039;formal&amp;#039; then&lt;br /&gt;
					local formalParentsDefaultSortkey_Space = {&lt;br /&gt;
						[&amp;#039;Animals&amp;#039;] = true,&lt;br /&gt;
						[&amp;#039;Insects&amp;#039;] = true,&lt;br /&gt;
						[&amp;#039;Molluscs&amp;#039;] = true,&lt;br /&gt;
						[&amp;#039;Fungi&amp;#039;] = true,&lt;br /&gt;
					}&lt;br /&gt;
					local formalParentsDefaultSortkey_None = {&lt;br /&gt;
						[&amp;#039;Species&amp;#039;] = true,&lt;br /&gt;
						[&amp;#039;Taxa&amp;#039;] = true,&lt;br /&gt;
						[&amp;#039;Fossil taxa&amp;#039;] = true,&lt;br /&gt;
					}&lt;br /&gt;
					if nav == nil then&lt;br /&gt;
						nav = frame:expandTemplate{ title = &amp;#039;Container category&amp;#039; }&lt;br /&gt;
					end&lt;br /&gt;
					if parent == &amp;#039;Group&amp;#039; then&lt;br /&gt;
						if isNilOrEmpty(sortkey) then sortkey = &amp;#039; Year&amp;#039; end --default to &amp;quot; Year&amp;quot;&lt;br /&gt;
						categories[iparent] = &amp;#039;[[Category:&amp;#039;..currGroup..&amp;#039;|&amp;#039;..sortkey..&amp;#039;]]&amp;#039;&lt;br /&gt;
						&lt;br /&gt;
					elseif parent == &amp;#039;paleontology&amp;#039; then&lt;br /&gt;
						if isNilOrEmpty(sortkey) then sortkey = &amp;#039; &amp;#039; end --default to &amp;quot; &amp;quot;; special parent&lt;br /&gt;
						categories[iparent] = &amp;#039;[[Category:Paleontology by year|&amp;#039;..sortkey..&amp;#039;]]&amp;#039;&lt;br /&gt;
						&lt;br /&gt;
					elseif parent then --allow freeform formal-parents, as long as they exist&lt;br /&gt;
						if mw.title.new( parent, &amp;#039;Category&amp;#039; ).exists then&lt;br /&gt;
							if sortkey then&lt;br /&gt;
								categories[iparent] = &amp;#039;[[Category:&amp;#039;..parent..&amp;#039;|&amp;#039;..sortkey..&amp;#039;]]&amp;#039;&lt;br /&gt;
							else&lt;br /&gt;
								categories[iparent] = &amp;#039;[[Category:&amp;#039;..parent..&amp;#039;]]&amp;#039;&lt;br /&gt;
							end&lt;br /&gt;
						else&lt;br /&gt;
							trackingCats[2] = &amp;#039;[[Category:Described in year error|G]]&amp;#039; --invalid freeform formal-parent&lt;br /&gt;
						end&lt;br /&gt;
						&lt;br /&gt;
					elseif formalParentsDefaultSortkey_Space[parent] then&lt;br /&gt;
						if isNilOrEmpty(sortkey) then sortkey = &amp;#039; &amp;#039; end --default to &amp;quot; &amp;quot;; normal parent&lt;br /&gt;
						categories[iparent] = &amp;#039;[[Category:&amp;#039;..parent..&amp;#039; by year of formal description|&amp;#039;..sortkey..&amp;#039;]]&amp;#039;&lt;br /&gt;
						&lt;br /&gt;
					elseif formalParentsDefaultSortkey_None[parent] then&lt;br /&gt;
						if isNilOrEmpty(sortkey) then sortkey = &amp;#039;&amp;#039; --default to none; normal parent&lt;br /&gt;
						else sortkey = &amp;#039;|&amp;#039;..sortkey end&lt;br /&gt;
						categories[iparent] = &amp;#039;[[Category:&amp;#039;..parent..&amp;#039; by year of formal description&amp;#039;..sortkey..&amp;#039;]]&amp;#039;&lt;br /&gt;
						&lt;br /&gt;
					else&lt;br /&gt;
						trackingCats[2] = &amp;#039;[[Category:Described in year error|F]]&amp;#039; --invalid formal-parent&lt;br /&gt;
					end&lt;br /&gt;
					&lt;br /&gt;
				--[[========================= Error ==========================]]&lt;br /&gt;
				else&lt;br /&gt;
					trackingCats[2] = &amp;#039;[[Category:Described in year error|U]]&amp;#039; --unknown configuration&lt;br /&gt;
				end&lt;br /&gt;
				&lt;br /&gt;
				iparent = iparent + 1&lt;br /&gt;
				parenti = &amp;#039;parent&amp;#039;..iparent&lt;br /&gt;
				sortkeyi = &amp;#039;sortkey&amp;#039;..iparent&lt;br /&gt;
			end --while conf[currGroup][currYDCF][parenti] do&lt;br /&gt;
		end --if bConfError == false then&lt;br /&gt;
		&lt;br /&gt;
		--check for non-existent cats&lt;br /&gt;
		for _, category in pairs(categories) do&lt;br /&gt;
			local cat = mw.ustring.match(category, &amp;#039;%[%[Category:([%w%s]+)&amp;#039;)&lt;br /&gt;
			if mw.title.new(cat, 14).exists == false then&lt;br /&gt;
				trackingCats[1] = &amp;#039;[[Category:Described in year unknown category]]&amp;#039;&lt;br /&gt;
				break&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
	end --if currCat then&lt;br /&gt;
	&lt;br /&gt;
	--build header &amp;amp; rem surrounding whitespace&lt;br /&gt;
	local br = &amp;#039;&amp;lt;br /&amp;gt;&amp;#039;&lt;br /&gt;
	if nav then header = nav end&lt;br /&gt;
	if portal then header = header..&amp;#039;\n&amp;#039;..portal end&lt;br /&gt;
	if commons then header = header..&amp;#039;\n&amp;#039;..commons end&lt;br /&gt;
	if wikispecies then header = header..&amp;#039;\n&amp;#039;..wikispecies end&lt;br /&gt;
	if description and description ~= &amp;#039;&amp;#039; then&lt;br /&gt;
		header = header..description&lt;br /&gt;
	elseif portal or commons or wikispecies then &lt;br /&gt;
		header = mw.ustring.gsub(header, &amp;#039;&amp;lt;br ?/?&amp;gt;&amp;#039;, &amp;#039;&amp;#039;)&lt;br /&gt;
	end&lt;br /&gt;
	if toc then header = header..br..toc end&lt;br /&gt;
	header = mw.text.trim(header)&lt;br /&gt;
	header = mw.ustring.gsub(header, &amp;#039;^&amp;lt;br /&amp;gt;&amp;#039;, &amp;#039;&amp;#039;)&lt;br /&gt;
	header = mw.ustring.gsub(header, &amp;#039;&amp;lt;br /&amp;gt;$&amp;#039;, &amp;#039;&amp;#039;)&lt;br /&gt;
	&lt;br /&gt;
	--append header to outString&lt;br /&gt;
	if outString then outString = outString..header&lt;br /&gt;
	else outString = header end&lt;br /&gt;
	&lt;br /&gt;
	--append cats to outString&lt;br /&gt;
	if currentTitle.namespace == 14 then --category namespace&lt;br /&gt;
		if table.maxn(categories) &amp;gt; 0 then outString = outString..table.concat(categories) end&lt;br /&gt;
		outString = outString..table.concat(trackingCats)&lt;br /&gt;
	else&lt;br /&gt;
		if table.maxn(categories) &amp;gt; 0 then --might be 0 if there&amp;#039;s an error before setting cats&lt;br /&gt;
			outString = outString..br..mw.ustring.gsub(table.concat(categories, br), &amp;#039;%[%[&amp;#039;, &amp;#039;[[:&amp;#039;)&lt;br /&gt;
		end&lt;br /&gt;
		outString = outString..br..mw.ustring.gsub(table.concat(trackingCats, br), &amp;#039;%[%[&amp;#039;, &amp;#039;[[:&amp;#039;)&lt;br /&gt;
		outString = mw.ustring.gsub(outString, br..br, br) --produced by empty (&amp;#039;&amp;#039;) first/consecutive tracking cat/s&lt;br /&gt;
		outString = mw.ustring.gsub(outString, br..br, br) --jic (use while loop if #trackingCats &amp;gt;= 3 or 4)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return outString&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Fire</name></author>
	</entry>
</feed>