--------------------------------------------------------------------------------
--                                                                            --
--      This meta-module which 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 yesno = require('Module:Yesno')
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)
	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)
	if title.isTalkPage then
		return lookUpNamespaceArg(args, cfg.talk)
	end
	for _, key in ipairs(getNamespaceArgKeys(title)) 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)
	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)
	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 capitalize(pageType)
	local first = mw.ustring.sub(pageType, 1, 1)
	local rest = mw.ustring.sub(pageType, 2)
	return mw.ustring.upper(first) .. rest
end

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

local function parseContent(title, args, optionsList)
	if title.namespace==828 and title.subpageText~='doc' -- don't detect modules
		or not title.exists -- can't check unless page exists
	then
		return nil
	end
	local content = title:getContent()
	if content == nil then
		return nil
	end
	local templates -- lazily evaluated
	for _, options in next, optionsList do
		local list, parameter, default, articleOnly = unpack(options, 1, 4)
		if not articleOnly or title.namespace==0 then -- only check for templates if we should...
			local out = lookUpNamespaceArg(args, parameter)
			if type(out) == "string" or (out ~= false and default) then -- ...and if we actually have anything to say about them
				if not templates then
					templates = {} -- do our delayed evaluation now that we are required to
					content = require('Module:Wikitext Parsing').PrepareText(content) -- disregard templates which do not have any affect
					for template in string.gmatch(content, "{{%s*([^|}]-)%s*[|}]") do
						templates[#templates+1] = capitalize(template)
					end
				end
				local wantedTemplates = mw.loadData('Module:Pagetype/' .. list)
				local templateFound = false
				for _, template in next, templates do
					if wantedTemplates[template] then
						templateFound = true
						break
					end
				end
				if templateFound then
					if type(out)=='string' then
						return out
					elseif out ~= false and default then
						return default
					end
				end
			end
		end
	end
end

-- Find pages which do not exist
local function nonExistent(title, args)
	local arg = lookUpNamespaceArg(args, cfg.ne)
	if arg == false then
		return nil
	end
	local exists = false
	if title.exists then -- not an article if it does not exist
		exists = true
	elseif title.namespace==8 and mw.message.new(title.text):exists() then
		exists = true
	elseif title.namespace==6 and title.fileExists then
		exists = true
	end
	if not exists then
		if type(arg) == 'string' then
			return arg
		else
			return cfg.naDefault
		end
	end
end

-- Get page types for mainspaces pages with an explicit class specified
local function getMainNamespaceClassPageType(title, args)
	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
	local arg = lookUpNamespaceArg(args, cfg.na)
	if arg == false then -- don't check for this class if it is specifically disallowed
		return nil
	end
	if cfg.naAliases[class] then
		if type(arg) == 'string' then
			return arg
		else
			return cfg.naDefault
		end
	else
		return nil
	end
end

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


-- Get page type not specified or detected by other means
local function getOtherPageType(title, args)
-- Whether the title is in the set of default active namespaces which are looked up in cfg.pagetypes.
	local isInDefaultActiveNamespace = false
	local defaultNamespacesKey = args[cfg.defaultns]
	if defaultNamespacesKey == cfg.defaultnsAll then
		isInDefaultActiveNamespace = true
	else
		local defaultNamespaces
		if defaultNamespacesKey == cfg.defaultnsExtended then
			defaultNamespaces = cfg.extendedNamespaces
		elseif defaultNamespacesKey == cfg.defaultnsNone then
			defaultNamespaces = {}
		else
			defaultNamespaces = cfg.defaultNamespaces
		end
		isInDefaultActiveNamespace = defaultNamespaces[title.namespace]
	end
	if isInDefaultActiveNamespace then
		return getExplicitPageType(title)
	else
		return getDefaultPageType(args)
	end
end

function p._main(args)
	local title
	if args.page then
		title = mw.title.new(args.page)
	else
		title = mw.title.getCurrentTitle()
	end
	if title and not yesno(args.talk, true) and args[cfg.defaultns] ~= cfg.defaultnsAll then
		title = title.subjectPageTitle
	end
	local pageType = detectRedirects(title, args)
		or nonExistent(title, args)
		or parseContent(title, args, {
			{'softredirect', cfg.softRedirect, cfg.softRedirectDefault},
			{'setindex', cfg.sia, cfg.siaDefault, true},
			{'disambiguation', cfg.dab, cfg.dabDefault, true},
			{'rfd', cfg.rfd, cfg.rfdDefault},
		})
		or (title.namespace == 0 and getMainNamespaceClassPageType(title, args))
		or getNamespaceArgPageType(title, args)
		or getOtherPageType(title, args)
	if yesno(args.plural, false) then
		pageType = pluralize(pageType)
	end
	if yesno(args.caps, false) then
		pageType = capitalize(pageType)
	end
	return pageType
end

function p.main(frame)
	local args = require('Module:Arguments').getArgs(frame)
	return p._main(args)
end

return p
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy