Module:Category described in year/sandbox explained

require('strict')

----Local functions --

local function addOrd(i) --12 -> 12th, etc. if tonumber(i) then local s = tostring(i) local tens = string.match(s, '1%d$') local ones = string.match(s, '%d$') if tens then return s..'th' elseif ones

'1' then return s..'st' elseif ones

'2' then return s..'nd' elseif ones

'3' then return s..'rd' elseif ones ~= nil then return s..'th' end end return end

local function isNilOrEmpty(thing) return (thing

nil or thing

)end

local p =

----External function --

function p.autodetect(frame) local conf = require('Module:Category described in year/conf/sandbox') --configuration module local commonsLink = require('Module:Commons link') local currentTitle = mw.title.getCurrentTitle local parentArg = frame:getParent.args[1] --accept 1 unnamed category parameter if not in category namespace; required for testing/doc/etc. purposes local header = ' ' --header template(s), nav bar, and category description text; whitespace-initialized for convenience local nav = nil local portal = nil --for local commons = nil --for local wikispecies = nil --for local description = nil local toc = nil local categories = local trackingCats = local outString = nil local bConfError = false --prelim namespace/title determination local currCat = nil local currQID = nil if currentTitle.namespace

14 then --category namespace currCat = currentTitle.text --without namespace nor interwiki prefixes currQID = mw.wikibase.getEntityIdForCurrentPage else if parentArg then currCat = mw.ustring.gsub(parentArg, 'Category:', ) currQID = mw.wikibase.getEntityIdForTitle('Category:'..currCat) else --currQID & currCat both nil if currentTitle.fullText ~= 'Template:Category described in year' then --ignore self... trackingCats[2] = '' --missing a category parameter outside category namespace end end end --find commons & wikispecies link(s); produce and/or template(s) if currQID then if commonsLink._hasGallery(currQID) or commonsLink._hasCategory(currQID) then commons = frame:expandTemplate end local currEntity = mw.wikibase.getEntity(currQID) if currEntity then --check "Other sites" sitelinks for Wikispecies local currSiteLinks = currEntity.sitelinks if currSiteLinks then local currSpeciesWiki = currEntity.sitelinks.specieswiki if currSpeciesWiki then local currSpeciesWikiTitle = currSpeciesWiki.title if currSpeciesWikiTitle then wikispecies = frame:expandTemplate end end end end end -- --Main -- if currCat then --determine current/related/adjacent cats' properties/vars/etc. local currGroup = mw.ustring.match(currCat, '^([%w ]+) described in') --Bacteria/Plants/etc. if isNilOrEmpty(currGroup) then currGroup = mw.ustring.match(currCat, '^([%w ]+) by year of formal description') end if conf[currGroup]

nil then conf[currGroup] = conf['Default'] end --default to Default local currYDCF = nil --possible future values: year/decade/century/formal local currYear = mw.ustring.match(currCat, 'described in (%d%d%d%d)$') local currDeca = mw.ustring.match(currCat, 'described in the (%d%d%d%d)s$') --deprecated local currCent = mw.ustring.match(currCat, 'described in the (%d+)[snrt][tdh] century$') local currFrml = mw.ustring.match(currCat, 'by year of (formal) description$') local parentCent = nil --used with currYear local minYear = tonumber(conf[currGroup].minyear) if minYear

nil or (minYear and (minYear <= 1700 or minYear >= 2000)) then minYear = 1758 --default to 1758 per ICZN Art. 5 end if currYear then currYDCF = 'year' if mw.ustring.match(currYear, '^%d%d00') then --1900 in 19th century parentCent = mw.ustring.match(currYear, '^%d%d') else --1901 in 20th century parentCent = 1 + mw.ustring.match(currYear, '^%d%d') end elseif currDeca then currYDCF = 'decade' bConfError = true trackingCats[2] = '' --invalid decade-parent (deprecated) elseif currCent then currYDCF = 'century' elseif currFrml then currYDCF = 'formal' else bConfError = true trackingCats[2] = '' --invalid category name end --conf error checkng (missing keys) --Numeric sortkeys are unfortunately grouped together under "0-9". --Check phab T203355 (Magic word to force category number headings instead of 0-9). if bConfError

false then if conf[currGroup]

nil then bConfError = true trackingCats[2] = '' --group (Bacteria/Plants/etc.) key missing from conf elseif conf[currGroup][currYDCF]

nil then bConfError = true trackingCats[2] = '' --year/century/formal key missing else if conf[currGroup][currYDCF].description

nil then bConfError = true trackingCats[2] = '' --description key missing end if conf[currGroup][currYDCF].parent1

nil then bConfError = true trackingCats[2] = '' --parent key missing end end end if bConfError

false then --produce portal if currGroup

'Fossil taxa' or currGroup

'Fossil parataxa' then portal = frame:expandTemplate end --produce description, evaluate %variables% description = conf[currGroup][currYDCF].description if mw.ustring.match(description, '%%year%%') then if currYear then description = mw.ustring.gsub(description, '%%year%%', currYear) --"2011" else description = mw.ustring.gsub(description, '%%year%%', 'this year') end end if mw.ustring.match(description, '%%century%%') then if currCent then description = mw.ustring.gsub(description, '%%century%%', addOrd(currCent)) --"21st" else description = mw.ustring.gsub(description, '%%century%%', 'this century') end end --produce cats & navs local iparent = 1 local parenti = 'parent'..iparent local sortkeyi = 'sortkey'..iparent while conf[currGroup][currYDCF][parenti] do local parent = conf[currGroup][currYDCF][parenti] local sortkey = conf[currGroup][currYDCF][sortkeyi] --

= Year

=

if currYDCF

'year' then if nav

nil then local args = if parentArg and currentTitle.namespace ~= 14 then args['testcase'] = parentArg end nav = frame:expandTemplate end if parent

'century' then if isNilOrEmpty(sortkey) then sortkey = currYear end --default to currYear categories[iparent] = '' elseif parent

'biology' then if isNilOrEmpty(sortkey) then sortkey = --default to none else sortkey = '|'..sortkey end if tonumber(currYear) < 1865 then categories[iparent] = '' --biology cat structure doesn't exist pre-1865, as of 10/2018 else categories[iparent] = '' --if/when all biology cats exists, merge this elseif with 'paleontology' end elseif parent

'paleontology' then if isNilOrEmpty(sortkey) then sortkey = --default to none else sortkey = '|'..sortkey end categories[iparent] = '' elseif parent

'environment' then if isNilOrEmpty(sortkey) then sortkey = --default to none else sortkey = '|'..sortkey end categories[iparent] = '' elseif mw.ustring.match(parent, '^%u[%l ]+') then --e.g. Animals/Insects/Fossil taxa if isNilOrEmpty(sortkey) then sortkey = --default to none else sortkey = '|'..sortkey end categories[iparent] = '' else trackingCats[2] = '' --invalid year-parent end --

Century

elseif currYDCF

'century' then if nav

nil then local args = if parentArg and currentTitle.namespace ~= 14 then args['testcase'] = parentArg end nav = frame:expandTemplate .. frame:expandTemplate end if parent

'formal' then if isNilOrEmpty(sortkey) then sortkey = addOrd(currCent) end --default to currCent categories[iparent] = '' elseif parent

'biology' then if isNilOrEmpty(sortkey) then sortkey = --default to none else sortkey = '|'..sortkey end if tonumber(currCent) < 19 then categories[iparent] = '' --biology cat structure doesn't exist pre-1865, as of 10/2018 else categories[iparent] = '' --if/when all biology cats exists, merge this elseif with 'paleontology' end elseif parent

'paleontology' then if isNilOrEmpty(sortkey) then sortkey = --default to none else sortkey = '|'..sortkey end categories[iparent] = '' elseif parent

'environment' then if isNilOrEmpty(sortkey) then sortkey = --default to none else sortkey = '|'..sortkey end categories[iparent] = '' elseif mw.ustring.match(parent, '^%u[%l ]+') then --e.g. Animals/Insects/Fossil taxa if isNilOrEmpty(sortkey) then sortkey = --default to none else sortkey = '|'..sortkey end categories[iparent] = '' else trackingCats[2] = '' --invalid century-parent end --

Formal

=
elseif currYDCF

'formal' then local formalParentsDefaultSortkey_Space = local formalParentsDefaultSortkey_None = if nav

nil then nav = frame:expandTemplate end if parent

'Group' then if isNilOrEmpty(sortkey) then sortkey = ' Year' end --default to " Year" categories[iparent] = '' elseif parent

'paleontology' then if isNilOrEmpty(sortkey) then sortkey = ' ' end --default to " "; special parent categories[iparent] = '' elseif parent then --allow freeform formal-parents, as long as they exist if mw.title.new(parent, 'Category').exists then if sortkey then categories[iparent] = '' else categories[iparent] = '' end else trackingCats[2] = '' --invalid freeform formal-parent end elseif formalParentsDefaultSortkey_Space[parent] then if isNilOrEmpty(sortkey) then sortkey = ' ' end --default to " "; normal parent categories[iparent] = '' elseif formalParentsDefaultSortkey_None[parent] then if isNilOrEmpty(sortkey) then sortkey = --default to none; normal parent else sortkey = '|'..sortkey end categories[iparent] = '' else trackingCats[2] = '' --invalid formal-parent end --
Error

=

else trackingCats[2] = '' --unknown configuration end iparent = iparent + 1 parenti = 'parent'..iparent sortkeyi = 'sortkey'..iparent end --while conf[currGroup][currYDCF][parenti] do end --if bConfError

false then --check for non-existent cats for _, category in pairs(categories) do local cat = mw.ustring.match(category, '%[%[Category:([%w%s]+)') if mw.title.new(cat, 14).exists

false then trackingCats[1] = '' break end end end --if currCat then --build header local br = '
' local n = '\n' if nav then header = nav end if portal then header = header..n..portal end if commons then header = header..n..commons end if wikispecies then header = header..n..wikispecies end if description and description ~= then header = header..description elseif portal or commons or wikispecies then header = mw.ustring.gsub(header, br, ) end if toc then header = header..br..toc end --rem surrounding whitespace header = mw.text.trim(header) header = mw.ustring.gsub(header, '^'..br, ) header = mw.ustring.gsub(header, br..'$', ) --append header to outString if outString then outString = outString..header else outString = header end --append cats to outString if currentTitle.namespace

14 then --category namespace if table.maxn(categories) > 0 then outString = outString..table.concat(categories) end outString = outString..table.concat(trackingCats) else if table.maxn(categories) > 0 then --might be 0 if there's an error before setting cats outString = outString..br..mw.ustring.gsub(table.concat(categories, br), '%[%[', '[[:') end outString = outString..br..mw.ustring.gsub(table.concat(trackingCats, br), '%[%[', '[[:') outString = mw.ustring.gsub(outString, br..br, br) --produced by empty ('') first/consecutive tracking cat/s outString = mw.ustring.gsub(outString, br..br, br) --jic (use while loop if #trackingCats >= 3 or 4) end return outString end return p]