Module:Category described in year/sandbox: Difference between revisions

Content deleted Content added
m Way more
 
(126 intermediate revisions by 5 users not shown)
Line 1:
require('Module:No globalsstrict')
 
--[[==========================================================================]]
--case sensitive conf/map table
--[[ Local functions ]]
local conf = {
--[[==========================================================================]]
--[[
'Fish' is the default category tree: year -> century -> Species, no decades.
'Spiders' & 'Plants' use year -> decade -> century -> Species.
Any category group (i.e. Birds/Crustaceans/Molluscs/etc.) NOT explicitly outlined here in conf{}
will follow the 'Fish' tree for that group.
To create a customized tree, like 'Spiders' below, add it to the bottom of the conf{} table,
following the same general table format.
]]--
['tocmin'] = 401, --integer; minimum category size to place {{Category TOC}} on
['Fish'] = { --group
['min'] = 1758, --integer; lowest possible year displayed in nav bars; 0/nil defaults to 1758 per ICZN Art. 5
['year'] = { --[[Category:Fish described in 1901]]
['description'] = 'This category should only contain species-level articles.',
['parent1'] = 'century', --year/decade/century/formal, 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'] = '', --'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
['min'] = 1757, --integer; lowest possible year (and thus decade) displayed in nav bars; 0/nil defaults to 1758 per ICZN Art. 5
['year'] = { --[[Category:Spiders described in 1901]]
['description'] = '', --'Description tbd; year; This category should only contain species articles, etc....',
['parent1'] = 'decade', --[[Category:Spiders described in the 1900s]]
['parent2'] = 'Animals', --[[Category:Animals described in 1900]]
},
['decade'] = { --[[Category:Spiders described in the 1900s]]
['description'] = '', --'Description tbd; decade; container category, etc....',
['parent1'] = 'century', --[[Category:Spiders described in the 20th century]]
['parent2'] = 'Animals', --[[Category:Animals described in the 1900s]]
},
['century'] = { --[[Category:Spiders described in the 20th century]]
['description'] = '', --'Description tbd; century; container category, etc....',
['parent1'] = 'formal', --[[Category:Spiders by year of formal description]]
['parent2'] = 'Animals', --[[Category:Animals described in the 20th century]]
},
},
 
['Plants'] = { --group
['min'] = 1753, --integer; lowest possible year (and thus decade) displayed in nav bars; 0/nil defaults to 1758 per ICZN Art. 5
['year'] = { --[[Category:Plants described in 1901]]
['description'] = "This category includes plants that were ''first formally and validly described'' in %year% according to the rules of the [[International Code of Botanical Nomenclature]]. Use [[WP:RS|reliable sources]] like the [[International Plant Names Index]] to figure out the proper category. For examples see the [[Wikipedia:WikiProject Plants/Description in year categories|WikiProject Plants essay]] on this topic.", --taken from [[Category:Plants described in 1928]]
['parent1'] = 'decade', --[[Category:Plants described in the 1900s]]
['parent2'] = 'Species', --[[Category:Species described in 1900]]
},
['decade'] = { --[[Category:Plants described in the 1900s]]
['description'] = '', --'Description tbd; decade; container category, etc....',
['parent1'] = 'century', --[[Category:Plants described in the 20th century]]
['parent2'] = 'Species', --[[Category:Species described in the 1900s]]
},
['century'] = { --[[Category:Plants described in the 20th century]]
['description'] = '', --'Description tbd; century; container category, etc....',
['parent1'] = 'formal', --[[Category:Plants by year of formal description]]
['parent2'] = 'Species', --[[Category:Species described in the 20th century]]
},
},
}
 
local function addOrd( i ) --2012 -> 20th12th, etc.
if tonumber(i) then
local s = tostring(i)
local lastd tens = mw.ustringstring.match(s, '1%d$')
local ones = string.match(s, '%d$')
if lastd == '1' then return s..'st'
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'
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 commonsCatportal = nil --for {{Portal|...}}
local commons = nil --for {{Commons|...}}
local wikispecies = nil --for {{Wikispecies|...}}
local description = nil
local toc = nil
local categories = {}
local trackingCategoriestrackingCats = {
[1] = nil'', --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
local currCat = nil
local currQID = nil
if currentTitle.namespace == 14 then --Category:category namespace
currCat = currentTitle.text --without namespace nor interwiki prefixes
currQID = mw.wikibase.getEntityIdForCurrentPage()
else
--accept 1 unnamed category parameter if not in Category: space; required for testing/doc/etc purposes
local parentArg = frame:getParent().args[1]
if parentArg then
currCat = mw.ustring.gsub(parentArg, 'Category:', '')
currQID = mw.wikibase.getEntityIdForTitle('Category:' .. currCat)
else --currQID & currCat both nil
else
if currentTitle.fullText ~= 'Template:Category described in year' then --ignore self...
return --add err msg?
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 currCommonsWikicurrSpeciesWiki = currEntity.sitelinks.commonswikispecieswiki
if currCommonsWikicurrSpeciesWiki then
local commonsCatTitlecurrSpeciesWikiTitle = currEntity.sitelinks.commonswikicurrSpeciesWiki.title
if commonsCatTitlecurrSpeciesWikiTitle then
wikispecies = frame:expandTemplate{ title = 'Wikispecies', args = { currSpeciesWikiTitle } }
local args = { commonsCatTitle }
end end end end end
commonsCat = frame:expandTemplate{ title = 'Commons', args = args }
end
end
end
end
end
--[[======================================================================]]
--[[ Main ]]
--[[======================================================================]]
if currCat then
--determine current/related/adjacent cats' properties/vars/etc
--determine current/related/adjacent cats' properties/vars/etc.
local currGroup = mw.ustring.match(currCat, '^%w+') --Fish/Spiders/default/etc.
local currGroup = mw.ustring.match(currCat, '^([%w ]+) described in') --Bacteria/Plants/etc.
if conf[currGroup] == nil then conf[currGroup] = conf['Fish'] end --'Fish' == default
if isNilOrEmpty(currGroup) then currGroup = mw.ustring.match(currCat, '^([%w ]+) by year of formal description') end
local currYDC = nil --year/decade/century
if conf[currGroup] == nil then conf[currGroup] = conf['Default'] end --default to Default
local currYear = mw.ustring.match(currCat, 'in (%d%d%d%d)$')
local currYDCF = nil --possible future values: year/decade/century/formal
local currDeca = mw.ustring.match(currCat, 'the (%d%d%d%d)s$')
local currCentcurrYear = mw.ustring.match(currCat, 'thedescribed in (%d+%d%d%d)[snrt][tdh] century$')
local currDeca = mw.ustring.match(currCat, 'described in the (%d%d%d%d)s$') --deprecated
local parentDeca = nil --used with currYear (i.e. Spiders) & currDeca (i.e. Spiders)
local currCent = mw.ustring.match(currCat, 'described in the (%d+)[snrt][tdh] century$')
local parentCent = nil --used with currYear (i.e. Fish) & currDeca (i.e. Spiders)
local currFrml = mw.ustring.match(currCat, 'by year of (formal) description$')
local lastCent, nextCent = nil, nil --used with currYear (i.e. Fish) & currCent (i.e. Fish)
local minYearparentCent = tonumber(conf[currGroup].min)nil --used with currYear
iflocal (minYear == nil or tonumber(minYear and minYear <= 1700conf[currGroup].minyear)) then
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 156 ⟶ 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 description & toc
--Numeric sortkeys are unfortunately grouped together under "0-9".
description = conf[currGroup][currYDC].description
--Check phab T203355 (Magic word to force category number headings instead of 0-9).
if mw.ustring.match(description, '%%year%%') then
if bConfError == false then
if currYear then description = mw.ustring.gsub(description, '%%year%%', currYear)
if conf[currGroup] == nil then
else description = mw.ustring.gsub(description, '%%year%%', 'this year') end
bConfError = true
end
trackingCats[2] = '[[Category:Described in year error|1]]' --group (Bacteria/Plants/etc.) key missing from conf
if mw.site.stats.pagesInCategory(currCat, 'pages') >= conf['tocmin'] then --expensive
elseif conf[currGroup][currYDCF] == nil then
local args = { numerals = 'no' }
bConfError = true
toc = frame:expandTemplate{ title = 'Category TOC', args = args }
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 cats & navs
--produce portal
local iparent = 1
if currGroup == 'Fossil taxa' or currGroup == 'Fossil parataxa' then
local parenti = 'parent' .. iparent
portal = frame:expandTemplate{ title = 'Portal', args = { 'Paleontology' } }
while conf[currGroup][currYDC][parenti] do
end
local parent = conf[currGroup][currYDC][parenti]
--produce description, evaluate %variables%
if currYDC == 'year' then
description = conf[currGroup][currYDCF].description
if nav == nil then
if mw.ustring.match(description, '%%year%%') then
local args = { year = currYear, min = minYear, cat = currGroup .. ' described in' }
if currYear then description = mw.ustring.gsub(description, '%%year%%', currYear) --"2011"
nav = frame:expandTemplate{ title = 'Category in year', args = args }
else description = mw.ustring.gsub(description, '%%year%%', 'this year') end
end
end
if parent == 'decade' then
if mw.ustring.match(description, '%%century%%') then
categories[iparent] = '[[Category:' .. currGroup .. ' described in the ' .. parentDeca .. 's]]'
if currCent then description = mw.ustring.gsub(description, '%%century%%', addOrd(currCent)) --"21st"
elseif parent == 'century' then
else description = mw.ustring.gsub(description, '%%century%%', 'this century') end
categories[iparent] = '[[Category:' .. currGroup .. ' described in the ' .. addOrd(parentCent) .. ' century]]'
end
else --i.e. Animals; require capital first letter?
categories[iparent] = '[[Category:' .. parent .. ' described in ' .. currYear .. ']]'
--produce cats & navs
end
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 ==========================]]
elseif currYDC == 'decade' then
if navcurrYDCF == nil'year' then
if nav == nil then
nav = frame:expandTemplate{ title = 'Container category' }
local args = { decade = currDeca, ['min'] = minYear, cat['skip-gaps'] = currGroup .. ' described in theyes' }
if parentArg and currentTitle.namespace ~= 14 then
nav = frame:expandTemplate{ title = 'Category by decade', args = args }
args['testcase'] = parentArg
end
end
if parent == 'century' then
nav = frame:expandTemplate{ title = 'Category series navigation', args = args }
categories[iparent] = '[[Category:' .. currGroup .. ' described in the ' .. addOrd(parentCent) .. ' century]]'
end
else --i.e. Animals; require capital first letter?
if parent == 'century' then
categories[iparent] = '[[Category:' .. parent .. ' described in the ' .. currDeca .. 's]]'
if isNilOrEmpty(sortkey) then sortkey = currYear end --default to currYear
categories[iparent] = '[[Category:'..currGroup..' described in the '..addOrd(parentCent)..' century|'..sortkey..']]'
elseif parent == 'biology' then
if isNilOrEmpty(sortkey) then sortkey = '' --default to none
else sortkey = '|'..sortkey end
if tonumber(currYear) < 1865 then
categories[iparent] = '[[Category:'..currYear..' in science'..sortkey..']]' --biology cat structure doesn't exist pre-1865, as of 10/2018
else
categories[iparent] = '[[Category:'..currYear..' 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:'..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
elseif currYDC == 'century' then
parenti = 'parent'..iparent
if nav == nil then
sortkeyi = 'sortkey'..iparent
nav = frame:expandTemplate{ title = 'Container category' }
end --while conf[currGroup][currYDCF][parenti] do
local args = { currGroup .. ' described in the ' .. addOrd(lastCent) .. ' century',
end --if bConfError == false then
currGroup .. ' described in the ' .. addOrd(nextCent) .. ' century' }
nav = nav .. frame:expandTemplate{ title = 'Category pair', args = args }
end
if parent == 'formal' then
categories[iparent] = '[[Category:' .. currGroup .. ' by year of formal description|' .. addOrd(currCent) .. ']]'
else --i.e. Animals; require capital first letter?
categories[iparent] = '[[Category:' .. parent .. ' described in the ' .. addOrd(currCent) .. ' century]]'
end
end
iparent = iparent + 1
parenti = 'parent' .. iparent
end --end while conf[currGroup][currYDC][parenti]
--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
trackingCategoriestrackingCats[1] = '[[Category:Described in year unknown category]]'
break
end
end
end
--check for manual cats
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
--build header
local br = '<br />'
--TODO: test/see if a similar commons cat exists and, if so, include it in the header
local n = '\n'
if nav then header = nav end
if commonsCatportal then header = header .. '<br />' n.. commonsCatportal end
if description and description ~= ''commons then header = header .. '<br />' n.. descriptioncommons end
if tocwikispecies then header = header .. '<br />' n.. tocwikispecies 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:category namespace
outString = outString ..if table.concatmaxn(categories) ..> table.concat(trackingCategories)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 />' ..
outString = outString..br..mw.ustring.gsub(table.concat(categories, '<br />'), '%[%[', '[[:')
end
if table.maxn(trackingCategories) > 0 then
outString = outString ..br..mw.ustring.gsub(table.concat(trackingCats, '<br), />'%[%[', ..'[[:')
--ws cleanup
mw.ustring.gsub(table.concat(trackingCategories, '<br />'), '%[%[', '[[:')
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