Module:Pagetype

--                                                                           -- --                                PAGETYPE                                    -- --                                                                           -- --      This is a meta-module intended to replace  and similar    -- --     templates. It automatically detects namespaces, and allows for a     -- --     great deal of customisation. It can easily be ported to other        -- --     wikis by changing the values in the Module:Pagetype/config. -- --                                                                           --

-- Load config. local cfg = mw.loadData('Module:Pagetype/config')

-- Load required modules. local getArgs = require('Module:Arguments').getArgs local yesno = require('Module:Yesno') local mDisambiguation = require('Module:Disambiguation')

local p = {}

-- Look up a namespace argument in the args table. local function lookUpNamespaceArg(args, key) local arg = args[key] -- Convert "yes", "1" etc. to true, "no", "0" etc. to false, and leave -- other values the same. return yesno(arg, arg) end

-- Append multiple values to an array local function appendMultiple(target, source) for _, value in ipairs(source) do		table.insert(target, value) end end

-- Get argument keys for a title's namespace local function getNamespaceArgKeys(title, cfg) local nsInfo = mw.site.namespaces[title.namespace] local customAliases = cfg.customNamespaceAliases[title.namespace] or {} local keys = {} if nsInfo.name ~= '' then table.insert(keys, nsInfo.name) end if nsInfo.canonicalName ~= nsInfo.name and nsInfo.canonicalName ~= '' then table.insert(keys, nsInfo.canonicalName) end appendMultiple(keys, nsInfo.aliases) appendMultiple(keys, customAliases) return keys end

-- Get the argument for a title's namespace, if it was specified in the args -- table. local function getNamespaceArg(title, args, cfg) if title.isTalkPage then return lookUpNamespaceArg(args, cfg.talk) end for _, key in ipairs(getNamespaceArgKeys(title, cfg)) do		local arg = lookUpNamespaceArg(args, mw.ustring.lower(key)) if arg ~= nil then return arg end end return nil end

-- Look up a page type specific to the title's namespace local function getExplicitPageType(title, cfg) if title.isTalkPage then return cfg.talkDefault else return cfg.pagetypes[title.namespace] end end

-- Get a default page type that is not specific to the title's namespace local function getDefaultPageType(args, cfg) local other = lookUpNamespaceArg(args, cfg.other) if type(other) == 'string' then return other else return cfg.otherDefault end end

local function detectRedirects(title, args) local redirect = lookUpNamespaceArg(args, cfg.redirect) if redirect == false then -- Don't detect redirects if they have been specifically disallowed. return nil end

-- Allow custom values for redirects. if not title.isRedirect then return nil elseif type(redirect) == 'string' then return redirect else return cfg.redirectDefault end end

local function detectDisambiguationPages(title, args, cfg) if title.namespace ~= 0 then -- Only detect disambiguation pages in mainspace return nil end

local dab = lookUpNamespaceArg(args, cfg.dab) if dab == false then -- Don't detect disambiguation pages if explicitly disallowed return nil end

if not mDisambiguation.isDisambiguation(title:getContent) then return nil elseif type(dab) == 'string' then return dab else return cfg.dabDefault end end

-- Gets the pagetype from a class specified from the first positional -- parameter. local function getPageTypeFromClass(args, class, key, aliasTable, default) local arg = lookUpNamespaceArg(args, key) if arg == false then -- Don't check for this class if it is specifically disallowed. return nil end if aliasTable[class] then if type(arg) == 'string' then return arg else return default end end return nil end

-- Get page types for mainspaces pages with an explicit class specified local function getMainNamespaceClassPageType(title, args, cfg) if title.namespace ~= 0 then return nil end local class = args[1] if type(class) == 'string' then -- Put in lower case so e.g. "na" and "NA" will both match. class = mw.ustring.lower(class) end return getPageTypeFromClass(		args,		class,		cfg.na,		cfg.naAliases,		cfg.naDefault	) end

-- Get page type specified by an explicit namespace argument. local function getNamespaceArgPageType(title, args, cfg) local namespaceArg = getNamespaceArg(title, args, cfg) if namespaceArg == true then -- Namespace has been explicitly enabled, so return the default for -- this namespace return getExplicitPageType(title, cfg) elseif namespaceArg == false then -- Namespace has been explicitly disabled return getDefaultPageType(args, cfg) elseif namespaceArg then -- This namespaces uses custom text return namespaceArg else return nil end end

-- Whether the title is in the set of default active namespaces which are -- looked up in cfg.pagetypes. local function isInDefaultActiveNamespace(title, args, cfg) local defaultNamespacesKey = args[cfg.defaultns] if defaultNamespacesKey == cfg.defaultnsAll then return true end

local defaultNamespaces if defaultNamespacesKey == cfg.defaultnsExtended then defaultNamespaces = cfg.extendedNamespaces elseif defaultNamespacesKey == cfg.defaultnsNone then defaultNamespaces = {} else defaultNamespaces = cfg.defaultNamespaces end return defaultNamespaces[title.namespace] or false end

-- Get page type not specified or detected by other means local function getOtherPageType(title, args, cfg) if isInDefaultActiveNamespace(title, args, cfg) then return getExplicitPageType(title, cfg) else return getDefaultPageType(args, cfg) end end

local function getPageType(title, args, cfg) return (		detectRedirects(title, args, cfg)		or detectDisambiguationPages(title, args, cfg)		or getMainNamespaceClassPageType(title, args, cfg)		or getNamespaceArgPageType(title, args, cfg)		or getOtherPageType(title, args, cfg)	) end

local function shouldUseSubjectTitle(args, cfg) return not yesno(args.talk, true) and args[cfg.defaultns] ~= cfg.defaultnsAll end

-- Get the Scribunto title object to fetch the page type of local function getTitle(args, cfg) local title if args.page then title = mw.title.new(args.page) if not title then return nil end else title = mw.title.getCurrentTitle end

if shouldUseSubjectTitle(args, cfg) then return title.subjectPageTitle else return title end end

local function pluralize(pageType, cfg) if cfg.irregularPlurals[pageType] then return cfg.irregularPlurals[pageType] else return pageType .. cfg.plural -- often 's'	end end

local function capitalize(pageType) local first = mw.ustring.sub(pageType, 1, 1) local rest = mw.ustring.sub(pageType, 2) return mw.ustring.upper(first) .. rest end

function p._main(args) local title = getTitle(args, cfg) local pageType = getPageType(title, args, cfg) if yesno(args.plural, false) then pageType = pluralize(pageType, cfg) end if yesno(args.caps, false) then pageType = capitalize(pageType) end return pageType end

function p.main(frame) local args = getArgs(frame) return p._main(args) end

return p