Module:Category described in year: Difference between revisions

Content deleted Content added
+Spiders tree (uses decades), add header & nav template(s) from current spider cats
 
(105 intermediate revisions by 8 users not shown)
Line 1:
require('Module:No globalsstrict')
 
--[[==========================================================================]]
--case sensitive conf/map table
--[[ Local functions ]]
local map = {
--[[==========================================================================]]
['Fish'] = { --group
['year'] = { --[[Category:Fish described in 1901]]
['description'] = 'tbd; year; This category should only contain species articles, etc....',
['parent1'] = 'century', --year/decade/century, i.e. 'century' for [[Category:Fish described in the 20th century]]
['parent2'] = 'Animals', --[[Category:Animals described in the 20th century]]
},
['century'] = { --[[Category:Fish described in the 20th century]]
['description'] = 'tbd; century; container category, etc....',
['parent1'] = 'formal', --[[Category:Fish by year of formal description]]
['parent2'] = 'Animals', --[[Category:Animals described in the 20th century]]
},
},
['Spiders'] = { --group
['year'] = {
['description'] = 'tbd; year; This category should only contain species articles, etc....',
['parent1'] = 'decade',
['parent2'] = 'Animals',
},
['decade'] = {
['description'] = 'tbd; decade; container category, etc....',
['parent1'] = 'century',
['parent2'] = 'Animals',
},
['century'] = {
['description'] = 'tbd; century; container category, etc....',
['parent1'] = 'formal',
['parent2'] = 'Animals',
},
},
}
 
local function addOrd( i ) --2012 -> 20th12th, etc.
if i and tonumber(i) then
local s = tostring(i)
local lastd tens = mw.ustringstring.match(s, '1%d$')
iflocal lastdones == '1' then return string.match(s, .. 'st%d$')
elseifif tens lastd == '2' then return s .. 'ndth'
elseif lastdones == '31' then return s .. 'rdst'
elseif lastdones ~== nil'2' then return s .. 'thnd'
elseif ones == '3' then return s..'rd'
else return '' end
elseif ones ~= nil then return s..'th'
else
end
return ''
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/config' ) --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 {{Portal|...}}
local commons = nil --for {{Commons|...}}
local wikispecies = nil --for {{Wikispecies|...}}
local description = nil
local toc = nil
local header = ' ' --header template(s), nav bar, and category description text
local categories = {}
local trackingCats = {
[1] = '', --placeholder for [[Category:Described in year unknown category]]
[2] = '', --placeholder for [[Category:Described in year error]]
[3] = '', --placeholder for [[Category:Described in year with manual category]]
}
local outString = nil
local bConfError = false
--prelim namespace/title determination
if currentTitle.namespace == 14 then --Category:
local currCat = nil
--determine current/related/adjacent cats' properties
local currQID = nil
local currCat = currentTitle.text --without namespace nor interwiki prefixes
if currentTitle.namespace == 14 then --category namespace
local currGroup = mw.ustring.match(currCat, '^%w+') --Fish/Spiders/etc.
currCat = currentTitle.text --without namespace nor interwiki prefixes
local currYDC = '' --placeholder for year/decade/century
currQID = mw.wikibase.getEntityIdForCurrentPage()
local currYear = mw.ustring.match(currCat, 'in (%d%d%d%d)$')
else
local currDeca = mw.ustring.match(currCat, 'the (%d%d%d%d)s$')
if parentArg then
local currCent = mw.ustring.match(currCat, 'the (%d+)[snrt][tdh] century')
currCat = mw.ustring.gsub(parentArg, 'Category:', '')
local parentCent = nil --used with currYear (i.e. Fish) & currDeca (i.e. Spiders)
currQID = mw.wikibase.getEntityIdForTitle('Category:'..currCat)
local parentDeca = nil --used with currYear (i.e. Spiders) & currDeca (i.e. Spiders)
else --currQID & currCat both nil
local lastCent, nextCent = nil, nil --used with currYear (i.e. Fish) & currCent (i.e. Fish)
if currentTitle.fullText ~= 'Template:Category described in year' then --ignore self...
trackingCats[2] = '[[Category:Described in year error|P]]' --missing a category parameter outside category namespace
end
end
end
--find commons & wikispecies link(s); produce {{Commons and category}} and/or {{Wikispecies}} template(s)
if currQID then
if commonsLink._hasGallery(currQID) or commonsLink._hasCategory(currQID) then
commons = frame:expandTemplate{ title = 'Commons and category', args = { qid=currQID }}
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{ title = 'Wikispecies', args = { currSpeciesWikiTitle } }
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
currYDCcurrYDCF = 'year'
parentDeca = mw.ustring.match(currYear, '^(%d%d%d)%d$') .. '0'
if mw.ustring.match(currYear, '^%d%d00') then --1900 in 19th century
parentCent = mw.ustring.match(currYear, '^%d%d')
Line 77 ⟶ 113:
parentCent = 1 + mw.ustring.match(currYear, '^%d%d')
end
lastCent = parentCent - 1
nextCent = parentCent + 1
elseif currDeca then
currYDCcurrYDCF = 'decade'
bConfError = true
parentDeca = mw.ustring.match(currDeca, '^(%d%d%d)%d$') .. '0'
trackingCats[2] = '[[Category:Described in year error|D]]' --invalid decade-parent (deprecated)
parentCent = mw.ustring.match(parentDeca, '^%d%d') + 1
elseif currCent then
currYDCcurrYDCF = 'century'
elseif currFrml then
lastCent = currCent - 1
nextCentcurrYDCF = currCent + 1'formal'
else
bConfError = true
return '' --add err msg?
trackingCats[2] = '[[Category:Described in year error|N]]' --invalid category name
end
--conf error checkng (missing keys)
--produce cats & navs
--Numeric sortkeys are unfortunately grouped together under "0-9".
local iparent = 1
--Check phab T203355 (Magic word to force category number headings instead of 0-9).
local parenti = 'parent' .. iparent
if bConfError == false then
while currYDC and map[currGroup][currYDC][parenti] do
if conf[currGroup] == nil then
local parent = map[currGroup][currYDC][parenti]
bConfError = true
trackingCats[2] = '[[Category:Described in year error|1]]' --group (Bacteria/Plants/etc.) key missing from conf
elseif conf[currGroup][currYDCF] == nil then
bConfError = true
trackingCats[2] = '[[Category:Described in year error|2]]' --year/century/formal key missing
else
if conf[currGroup][currYDCF].description == nil then
bConfError = true
trackingCats[2] = '[[Category:Described in year error|3]]' --description key missing
end
if conf[currGroup][currYDCF].parent1 == nil then
bConfError = true
trackingCats[2] = '[[Category:Described in year error|4]]' --parent key missing
end
end
end
if bConfError == false then
--produce portal
if currGroup == 'Fossil taxa' or currGroup == 'Fossil parataxa' then
portal = frame:expandTemplate{ title = 'Portal', args = { 'Paleontology' } }
end
if--produce description, ==evaluate nil then%variables%
description = mapconf[currGroup][currYDCcurrYDCF].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
if currYDC == 'year' then
iflocal naviparent == nil then1
local parenti = 'parent'..iparent
local args = { year = currYear, cat = currGroup .. ' described in' }
local sortkeyi = 'sortkey'..iparent
nav = frame:expandTemplate{ title = 'Category in year', args = args }
while conf[currGroup][currYDCF][parenti] do
end
iflocal parent == 'decade' thenconf[currGroup][currYDCF][parenti]
local sortkey = conf[currGroup][currYDCF][sortkeyi]
categories[iparent] = '[[:Category:' .. currGroup .. ' described in the ' .. parentDeca .. 's]]'
elseif parent == 'century' then
--[[========================== Year ==========================]]
categories[iparent] = '[[:Category:' .. currGroup .. ' described in the ' .. addOrd(parentCent) .. ' century]]'
if currYDCF == 'year' then
else --i.e. Animals; require capital first letter?
if nav == nil then
categories[iparent] = '[[:Category:' .. parent .. ' described in ' .. currYear .. ']]'
local args = { ['min'] = minYear, ['skip-gaps'] = 'yes' }
end
if parentArg and currentTitle.namespace ~= 14 then
elseif currYDC == 'decade' then
args['testcase'] = parentArg
if nav == nil then
end
local args = { decade = currDeca, cat = currGroup .. ' described in the' }
nav = frame:expandTemplate{ title = 'Category byseries decadenavigation', args = args }
end
if parent == 'century' then
if isNilOrEmpty(sortkey) then sortkey = currYear end --default to currYear
categories[iparent] = '[[:Category:' .. currGroup .. ' described in the ' .. addOrd(parentCent) .. ' century]]'
categories[iparent] = '[[Category:'..currGroup..' described in the '..addOrd(parentCent)..' century|'..sortkey..']]'
else --i.e. Animals; require capital first letter?
categories[iparent] = '[[:Category:' .. parent .. ' described in the ' .. currDeca .. 's]]'
elseif parent == 'biology' then
end
if isNilOrEmpty(sortkey) then sortkey = '' --default to none
elseif currYDC == 'century' then
if else navsortkey == nil'|'..sortkey thenend
if tonumber(currYear) < 1865 then
nav = frame:expandTemplate{ title = 'Container category' }
categories[iparent] = '[[Category:'..currYear..' in science'..sortkey..']]' --biology cat structure doesn't exist pre-1865, as of 10/2018
local args = { currGroup .. ' described in the ' .. addOrd(lastCent) .. ' century',
else
currGroup .. ' described in the ' .. addOrd(nextCent) .. ' century' }
categories[iparent] = '[[Category:'..currYear..' in biology'..sortkey..']]' --if/when all biology cats exists, merge this elseif with 'paleontology'
nav = nav .. frame:expandTemplate{ title = 'Category pair', args = args }
end
if parent == 'formal' then
elseif parent == 'paleontology' then
categories[iparent] = '[[:Category:' .. currGroup .. ' by year of formal description|' .. addOrd(currCent) .. ']]'
if isNilOrEmpty(sortkey) then sortkey = '' --default to none
else --i.e. Animals; require capital first letter?
else sortkey = '|'..sortkey end
categories[iparent] = '[[:Category:' .. parent .. ' described in the ' .. addOrd(currCent) .. ' century]]'
categories[iparent] = '[[Category:'..currYear..' in '..parent..sortkey..']]'
elseif parent == 'environment' then
if isNilOrEmpty(sortkey) then sortkey = '' --default to none
else sortkey = '|'..sortkey end
categories[iparent] = '[[Category:'..currYear..' in the environment'..sortkey..']]'
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] = '[[Category:'..parent..' described in '..currYear..sortkey..']]'
else
trackingCats[2] = '[[Category:Described in year error|Y]]' --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{ title = 'Container category' } ..
frame:expandTemplate{ title = 'Category series navigation', args = args }
end
if parent == 'formal' then
if isNilOrEmpty(sortkey) then sortkey = addOrd(currCent) end --default to currCent
categories[iparent] = '[[Category:'..currGroup..' by year of formal description|'..sortkey..']]'
elseif parent == 'biology' then
if isNilOrEmpty(sortkey) then sortkey = '' --default to none
else sortkey = '|'..sortkey end
if tonumber(currCent) < 19 then
categories[iparent] = '[[Category:'..addOrd(currCent)..' century in science'..sortkey..']]' --biology cat structure doesn't exist pre-1865, as of 10/2018
else
categories[iparent] = '[[Category:'..addOrd(currCent)..' century in biology'..sortkey..']]' --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] = '[[Category:'..addOrd(currCent)..' century in '..parent..sortkey..']]'
elseif parent == 'environment' then
if isNilOrEmpty(sortkey) then sortkey = '' --default to none
else sortkey = '|'..sortkey end
categories[iparent] = '[[Category:'..addOrd(currCent)..' century in the environment'..sortkey..']]'
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] = '[[Category:'..parent..' described in the '..addOrd(currCent)..' century'..sortkey..']]'
else
trackingCats[2] = '[[Category:Described in year error|C]]' --invalid century-parent
end
--[[======================== Formal ==========================]]
elseif currYDCF == 'formal' then
local formalParentsDefaultSortkey_Space = {
['Animals'] = true,
['Insects'] = true,
['Molluscs'] = true,
['Fungi'] = true,
}
local formalParentsDefaultSortkey_None = {
['Species'] = true,
['Taxa'] = true,
['Fossil taxa'] = true,
}
if nav == nil then
nav = frame:expandTemplate{ title = 'Container category' }
end
if parent == 'Group' then
if isNilOrEmpty(sortkey) then sortkey = ' Year' end --default to " Year"
categories[iparent] = '[[Category:'..currGroup..'|'..sortkey..']]'
elseif parent == 'paleontology' then
if isNilOrEmpty(sortkey) then sortkey = ' ' end --default to " "; special parent
categories[iparent] = '[[Category:Paleontology by year|'..sortkey..']]'
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] = '[[Category:'..parent..'|'..sortkey..']]'
else
categories[iparent] = '[[Category:'..parent..']]'
end
else
trackingCats[2] = '[[Category:Described in year error|G]]' --invalid freeform formal-parent
end
elseif formalParentsDefaultSortkey_Space[parent] then
if isNilOrEmpty(sortkey) then sortkey = ' ' end --default to " "; normal parent
categories[iparent] = '[[Category:'..parent..' by year of formal description|'..sortkey..']]'
elseif formalParentsDefaultSortkey_None[parent] then
if isNilOrEmpty(sortkey) then sortkey = '' --default to none; normal parent
else sortkey = '|'..sortkey end
categories[iparent] = '[[Category:'..parent..' by year of formal description'..sortkey..']]'
else
trackingCats[2] = '[[Category:Described in year error|F]]' --invalid formal-parent
end
--[[========================= Error ==========================]]
else
trackingCats[2] = '[[Category:Described in year error|U]]' --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] = '[[Category:Described in year unknown category]]'
break
end
iparent = iparent + 1
parenti = 'parent' .. iparent
end
 
elseif currentTitle.namespace == 10 then --Module:/Template: sandbox/testcases/doc
--check for manual cats
end
if currentTitle.namespace == 14 then --category namespace
local currContent = mw.title.makeTitle( 'Category', currCat or '' ):getContent()
local mancat = mw.ustring.match(currContent or '', '%[%[%s*Category')
if mancat then trackingCats[3] = '[[Category:Described in year with manual category]]' end
end
end --if currCat then
--producebuild header
local br = '<br />'
local n = '\n'
if nav then header = nav end
if descriptionportal then header = header .. '\n\n' .. descriptionportal 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 string.sub(currentTitle.subpageText,1,9) == 'testcases' then
if currentTitle.namespace == 14 then --category namespace
outString = outString .. mw.text.nowiki(table.concat(categories)) .. '<br />'
if table.maxn(categories) > 0 then
elseif currentTitle.namespace == 14 then --Category:
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 = outString..br..mw.ustring.gsub(table.concat(categories, br), '%[%[', '[[:')
end
outString = outString..br..mw.ustring.gsub(table.concat(trackingCats, br), '%[%[', '[[:')
--ws cleanup
while string.match(outString, br..br) do --rem dup brs produced by empty ('') first/consecutive tracking cat/s
outString = string.gsub(outString, br..br, br)
end
end