Module:Pagetype: Difference between revisions

From Wikipedia, the free encyclopedia
Content deleted Content added
non-existent pages are not articles, plus some code simplification
add detection of non-existent pages, some code simplication
Line 6: Line 6:
-- --
-- --
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------

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


-- Load required modules.
-- Load required modules.
local getArgs = require('Module:Arguments').getArgs
local yesno = require('Module:Yesno')
local yesno = require('Module:Yesno')
local p = {}
local p = {}
Line 31: Line 29:


-- Get argument keys for a title's namespace
-- Get argument keys for a title's namespace
local function getNamespaceArgKeys(title, cfg)
local function getNamespaceArgKeys(title)
local nsInfo = mw.site.namespaces[title.namespace]
local nsInfo = mw.site.namespaces[title.namespace]
local customAliases = cfg.customNamespaceAliases[title.namespace] or {}
local customAliases = cfg.customNamespaceAliases[title.namespace] or {}
Line 47: Line 45:


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


-- Look up a page type specific to the title's namespace
-- Look up a page type specific to the title's namespace
local function getExplicitPageType(title, cfg)
local function getExplicitPageType(title)
if title.isTalkPage then
if title.isTalkPage then
return cfg.talkDefault
return cfg.talkDefault
Line 70: Line 68:


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


local function pluralize(pageType, cfg)
local function pluralize(pageType)
if cfg.irregularPlurals[pageType] then
if cfg.irregularPlurals[pageType] then
return cfg.irregularPlurals[pageType]
return cfg.irregularPlurals[pageType]
Line 153: Line 151:
end
end


-- Find pages which do not exist
-- Get page types for mainspaces pages with an explicit class specified
local function getMainNamespaceClassPageType(title, args, cfg)
local function nonExistent(title, args)
local arg = lookUpNamespaceArg(args, cfg.ne)
if arg == false then
return nil
end
if not title.exists then -- not an article if it does not exist
if not title.exists then -- not an article if it does not exist
if type(arg) == 'string' then
return cfg.naDefault
return arg
else
return cfg.naDefault
end
end
end
end

-- Get page types for mainspaces pages with an explicit class specified
local function getMainNamespaceClassPageType(title, args)
local class = args[1]
local class = args[1]
if type(class) == 'string' then -- Put in lower case so e.g. "na" and "NA" will both match
if type(class) == 'string' then -- Put in lower case so e.g. "na" and "NA" will both match
Line 178: Line 188:


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


-- Get page type not specified or detected by other means
-- Get page type not specified or detected by other means
local function getOtherPageType(title, args, cfg)
local function getOtherPageType(title, args)
-- Whether the title is in the set of default active namespaces which are looked up in cfg.pagetypes.
-- Whether the title is in the set of default active namespaces which are looked up in cfg.pagetypes.
local isInDefaultActiveNamespace = false
local isInDefaultActiveNamespace = false
Line 215: Line 225:
end
end
if isInDefaultActiveNamespace then
if isInDefaultActiveNamespace then
return getExplicitPageType(title, cfg)
return getExplicitPageType(title)
else
else
return getDefaultPageType(args, cfg)
return getDefaultPageType(args)
end
end
end
end


local function getPageType(title, args, cfg)
function p._main(args)
return (
detectRedirects(title, args, cfg)
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, cfg))
or getNamespaceArgPageType(title, args, cfg)
or getOtherPageType(title, args, cfg)
)
end

-- Get the Scribunto title object to fetch the page type of
local function getTitle(args, cfg)
local title
local title
if args.page then
if args.page then
title = mw.title.new(args.page)
title = mw.title.new(args.page)
if not title then
return nil
end
else
else
title = mw.title.getCurrentTitle()
title = mw.title.getCurrentTitle()
end
end
if not yesno(args.talk, true) and args[cfg.defaultns] ~= cfg.defaultnsAll then
if title and not yesno(args.talk, true) and args[cfg.defaultns] ~= cfg.defaultnsAll then
return title.subjectPageTitle
title = title.subjectPageTitle
else
return title
end
end
local pageType = detectRedirects(title, args)
end
or nonExistent(title, args)

or parseContent(title, args, {
function p._main(args)
{'softredirect', cfg.softRedirect, cfg.softRedirectDefault},
local title = getTitle(args, cfg)
{'setindex', cfg.sia, cfg.siaDefault, true},
local pageType = getPageType(title, args, cfg)
{'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
if yesno(args.plural, false) then
pageType = pluralize(pageType, cfg)
pageType = pluralize(pageType)
end
end
if yesno(args.caps, false) then
if yesno(args.caps, false) then
Line 267: Line 262:


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

Revision as of 12:25, 16 May 2024

--------------------------------------------------------------------------------
--                                                                            --
--      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
	if not title.exists then -- not an article if it does not exist
		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