Documentation for this module may be created at Module:Geological time/doc
require('strict')
local getArgs = require('Module:Arguments').getArgs
local p = {}
-- Determine whether a query string matches a stored timespan string
-- Arguments:
-- s: query string
-- sub: standard name of timespan
-- Returns:
-- false if there is no match
-- prefix and suffix of match, otherwise
local function matches(s, sub)
local sLen = mw.ustring.len(s)
local subLen = mw.ustring.len(sub)
if subLen > sLen then
return false
end
local lowerS = mw.ustring.lower(s)
local lowerSub = mw.ustring.lower(sub)
local startOffset, endOffset = mw.ustring.find(lowerS,lowerSub,1,true)
if not startOffset then
return false
end
return (mw.ustring.sub(s,1,startOffset-1) or ""), (mw.ustring.sub(s,endOffset+1) or "")
end
-- Create list of strings to search corresponding to a standard timespan
-- Some timespans are disambiguated: first search for the dabbed title, then
-- the base title. Otherwise just search for the standard timespan string
-- Argument:
-- span = value in timespan lists (above)
-- Returns:
-- list of strings to search in query string
local function searchStringList(span)
if type(span) == "table" then
return {span.base.." "..span.dab, span.base}
end
return {span}
end
-- When an adjacent time span is found, this function returns the
-- corresponding basename for the page.
-- Arguments:
-- span: adjacent entry from table, above
-- prefix: prefix of query string before match
-- suffix: remainder of original query string beyond match
-- Returns:
-- page title
--
-- If the adjacent time span is dabbed, then return the dab if the suffix
-- is empty. If the suffix is non-empty (e.g., "life"), append it to the base
-- name of the span (e.g., "Oxfordian") --> "Oxfordian life"
local function matchedString(span, prefix, suffix)
if type(span) == "table" then
if prefix == "" and suffix == "" then
return span.base.." "..span.dab
end
return prefix..span.base..suffix
end
return prefix..span..suffix
end
-- Function to find the page titles of time spans adjacent to a query string
-- Arguments:
-- s: query string to search for
local function find(s)
-- lazy load list of geological timespans,
local data = mw.loadData('Module:Geological time/data')
-- Search from most-specific to least, to catch "Cambrian Series 2" before "Cambrian"
for _, level in ipairs({'age', 'epoch', 'series', 'period', 'era', 'eon'}) do
local list = data[level]
local listLen = data.listLen[level]
for i, span in ipairs(list) do
-- Each timespan might have more than one search string
for _, searchString in ipairs(searchStringList(span)) do
local prefix, suffix = matches(s, searchString)
if suffix then
local prevSpan = i > 1 and matchedString(list[i-1], prefix, suffix)
local nextSpan = i < listLen and matchedString(list[i+1], prefix, suffix)
-- return first match found
return {prev=prevSpan, next=nextSpan}
end
end
end
end
return nil
end
-- Lua entry point to generate see also hatnote for geological time spans adjanct in time
-- Arguments:
-- args[1]: name of page to generate adjacency (current page if None)
-- Returns:
-- See also previous and next, formatted as a hatnote
function p._seeAlso(args)
local title = args[1] and mw.title.new(args[1]) or mw.title.getCurrentTitle()
local basetext = title.baseText
local namespace = title.namespace
local adjacent = find(basetext)
if not adjacent then
local warning = require('Module:If preview')._warning
local warn = warning({"Cannot find geological time frame in "..basetext})
if mw.title.getCurrentTitle().nsText ~= "Template" then
warn = warn.."[[Category:Missing geological time frame]]"
end
return warn
end
local prevTitle = adjacent.prev and mw.title.new(adjacent.prev, namespace)
local nextTitle = adjacent.next and mw.title.new(adjacent.next, namespace)
local catPair = require('Module:Category pair')._pair
return catPair(prevTitle, nextTitle)
end
-- Function to find timespan before argument
function p._before(s)
local findOut = s and find(tostring(s))
return findOut and findOut.prev
end
-- Function to find timespan after argument
function p._after(s)
local findOut = s and find(tostring(s))
return findOut and findOut.next
end
-- Template entry points
function p.seeAlso(frame)
local args = getArgs(frame)
return p._seeAlso(args)
end
function p.before(frame)
local args = getArgs(frame)
return p._before(args[1]) or ""
end
function p.after(frame)
local args = getArgs(frame)
return p._after(args[1]) or ""
end
return p