Editing Module:Category handler

From MINR.ORG WIKI

Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then save the changes below to finish undoing the edit.
Latest revision Your text
Line 1: Line 1:
--------------------------------------------------------------------------------
+
-- Configuration data.
--                                                                            --
+
local cfg = {}
--                              CATEGORY HANDLER                              --
 
--                                                                            --
 
--      This module implements the {{category handler}} template in Lua,      --
 
--      with a few improvements: all namespaces and all namespace aliases    --
 
--      are supported, and namespace names are detected automatically for    --
 
--      the local wiki. This module requires [[Module:Namespace detect]]      --
 
--      and [[Module:Yesno]] to be available on the local wiki. It can be    --
 
--      configured for different wikis by altering the values in              --
 
--      [[Module:Category handler/config]], and pages can be blacklisted      --
 
--      from categorisation by using [[Module:Category handler/blacklist]].  --
 
--                                                                            --
 
--------------------------------------------------------------------------------
 
  
-- Load required modules
+
cfg.nocat = 'nocat'   
local yesno = require('Module:Yesno')
+
cfg.categories = 'categories'
 +
cfg.subpage = 'subpage'
 +
cfg.page = 'page'
 +
cfg.category2 = 'category2'
 +
cfg.all = 'all'
 +
cfg.main = 'main'
 +
cfg.other = 'other'
  
-- Lazily load things we don't always need
+
-- The categorisation blacklist. Pages that match Lua patterns in this
local mShared, mappings
+
-- list will not be categorised unless the appropriate options are set.
 +
-- If the namespace name has a space in, it must be written with an
 +
-- underscore, e.g. "Wikipedia_talk". Other parts of the title can have
 +
-- either underscores or spaces.
 +
cfg.blacklist = {
 +
    '^Main Page$', -- don't categorise the main page.
 +
   
 +
    -- Don't categorise the following pages or their subpages.
 +
    '^Wikipedia:Cascade%-protected items$',
 +
    '^Wikipedia:Cascade%-protected items/.*$',
 +
    '^User:UBX$', -- The userbox "template" space.
 +
    '^User:UBX/.*$',
 +
    '^User_talk:UBX$',
 +
    '^User_talk:UBX/.*$',
 +
   
 +
    -- Don't categorise subpages of these pages, but allow
 +
    -- categorisation of the base page.
 +
    '^Wikipedia:Template messages/.*$',
 +
   
 +
    '/[aA]rchive' -- Don't categorise archives.
 +
}
  
 +
-- Module start.
 
local p = {}
 
local p = {}
 +
local args = {}
  
--------------------------------------------------------------------------------
+
-- Get the page object. This will return the page object for the page
-- Helper functions
+
-- specified, or nil if there are errors in the title or if the
--------------------------------------------------------------------------------
+
-- expensive function count has been exceeded.
 
+
local function getPageObject()
local function trimWhitespace(s, removeBlanks)
+
    -- Get the title object for args.page if it is specified. Otherwise
if type(s) ~= 'string' then
+
    -- get the title object for the current page.
return s
+
    if args[cfg.page] then
end
+
        -- Get the page object, passing the function through pcall
s = s:match('^%s*(.-)%s*$')
+
        -- in case we are over the expensive function count limit.
if removeBlanks then
+
        local noError, pageObject = pcall(mw.title.new, args[cfg.page])
if s ~= '' then
+
        if not noError then
return s
+
            return nil
else
+
        else
return nil
+
            return pageObject
end
+
        end
else
+
    else
return s
+
        return mw.title.getCurrentTitle()
end
+
    end  
 
end
 
end
  
--------------------------------------------------------------------------------
+
-- Find whether we need to return a category or not.
-- CategoryHandler class
+
local function needsCategory( pageObject )
--------------------------------------------------------------------------------
+
    if not pageObject then return end
 
+
    if args[cfg.nocat] == 'true'
local CategoryHandler = {}
+
        or ( args[cfg.category2] and args[cfg.category2] ~= 'yes' )
CategoryHandler.__index = CategoryHandler
+
        or ( args[cfg.subpage] == 'no' and pageObject.isSubpage )
 
+
        or ( args[cfg.subpage] == 'only' and not pageObject.isSubpage ) then
function CategoryHandler.new(data, args)
+
        return false
local obj = setmetatable({ _data = data, _args = args }, CategoryHandler)
+
    else
+
        return true
-- Set the title object
+
    end
do
 
local pagename = obj:parameter('demopage')
 
local success, titleObj
 
if pagename then
 
success, titleObj = pcall(mw.title.new, pagename)
 
end
 
if success and titleObj then
 
obj.title = titleObj
 
if titleObj == mw.title.getCurrentTitle() then
 
obj._usesCurrentTitle = true
 
end
 
else
 
obj.title = mw.title.getCurrentTitle()
 
obj._usesCurrentTitle = true
 
end
 
end
 
 
 
-- Set suppression parameter values
 
for _, key in ipairs{'nocat', 'categories'} do
 
local value = obj:parameter(key)
 
value = trimWhitespace(value, true)
 
obj['_' .. key] = yesno(value)
 
end
 
do
 
local subpage = obj:parameter('subpage')
 
local category2 = obj:parameter('category2')
 
if type(subpage) == 'string' then
 
subpage = mw.ustring.lower(subpage)
 
end
 
if type(category2) == 'string' then
 
subpage = mw.ustring.lower(category2)
 
end
 
obj._subpage = trimWhitespace(subpage, true)
 
obj._category2 = trimWhitespace(category2) -- don't remove blank values
 
end
 
return obj
 
 
end
 
end
  
function CategoryHandler:parameter(key)
+
-- Find whether we need to check the blacklist or not.
local parameterNames = self._data.parameters[key]
+
local function needsBlacklistCheck()
local pntype = type(parameterNames)
+
    if args[cfg.nocat] == 'false'
if pntype == 'string' or pntype == 'number' then
+
        or args[cfg.categories] == 'yes'
return self._args[parameterNames]
+
        or args[cfg.category2] == 'yes' then
elseif pntype == 'table' then
+
        return false
for _, name in ipairs(parameterNames) do
+
    else
local value = self._args[name]
+
        return true
if value ~= nil then
+
    end
return value
 
end
 
end
 
return nil
 
else
 
error(string.format(
 
'invalid config key "%s"',
 
tostring(key)
 
), 2)
 
end
 
 
end
 
end
  
function CategoryHandler:isSuppressedByArguments()
+
-- Searches the blacklist to find a match with the page object. The
return
+
-- string searched is the namespace plus the title, including subpages.
-- See if a category suppression argument has been set.
+
-- Returns true if there is a match, otherwise returns false.
self._nocat == true
+
local function findBlacklistMatch(pageObject)
or self._categories == false
+
    if not pageObject then return end
or (
+
   
self._category2
+
    -- Get the title to check.
and self._category2 ~= self._data.category2Yes
+
    local title = pageObject.nsText -- Get the namespace.
and self._category2 ~= self._data.category2Negative
+
    -- Append a colon if the namespace isn't the blank string.
)
+
    if #title > 0 then
 
+
        title = title .. ':' .. pageObject.text
-- Check whether we are on a subpage, and see if categories are
+
    else
-- suppressed based on our subpage status.
+
        title = pageObject.text
or self._subpage == self._data.subpageNo and self.title.isSubpage
+
    end
or self._subpage == self._data.subpageOnly and not self.title.isSubpage
+
   
 +
    -- Check the blacklist.
 +
    for i, pattern in ipairs( cfg.blacklist ) do
 +
        if mw.ustring.match( title, pattern ) then
 +
            return true
 +
        end
 +
    end
 +
    return false
 
end
 
end
  
function CategoryHandler:shouldSkipBlacklistCheck()
+
local function _main()
-- Check whether the category suppression arguments indicate we
+
    local pageObject = getPageObject()
-- should skip the blacklist check.
+
    if not needsCategory( pageObject ) then return end
return self._nocat == false
+
    if needsBlacklistCheck() then
or self._categories == true
+
        return findBlacklistMatch( pageObject )
or self._category2 == self._data.category2Yes
+
    end
 
end
 
end
  
function CategoryHandler:matchesBlacklist()
+
-- Process the arguments.
if self._usesCurrentTitle then
+
function p.main(frame)
return self._data.currentTitleMatchesBlacklist
+
    -- If called via #invoke, use the args passed into the invoking
else
+
    -- template, or the args passed to #invoke if any exist. Otherwise
mShared = mShared or require('Module:Category handler/shared')
+
    -- assume args are being passed directly in.
return mShared.matchesBlacklist(
+
    local origArgs
self.title.prefixedText,
+
    if frame == mw.getCurrentFrame() then
mw.loadData('Module:Category handler/blacklist')
+
        origArgs = frame:getParent().args
)
+
        for k, v in pairs( frame.args ) do
end
+
            origArgs = frame.args
end
+
            break
 
+
        end
function CategoryHandler:isSuppressed()
+
    else
-- Find if categories are suppressed by either the arguments or by
+
        origArgs = frame
-- matching the blacklist.
+
    end
return self:isSuppressedByArguments()
+
   
or not self:shouldSkipBlacklistCheck() and self:matchesBlacklist()
+
    -- The following don't need blank values preserved:
end
+
    -- nocat
 
+
    -- categories
function CategoryHandler:getNamespaceParameters()
+
    -- subpage
if self._usesCurrentTitle then
+
    -- page
return self._data.currentTitleNamespaceParameters
+
    -- positional parameters (1-10)
else
+
   
if not mappings then
+
    -- The following *do* need blank values preserved
mShared = mShared or require('Module:Category handler/shared')
+
    -- category2
mappings = mShared.getParamMappings(true) -- gets mappings with mw.loadData
+
    -- all
end
+
    -- other
return mShared.getNamespaceParameters(
+
    -- main
self.title,
+
    -- all the namespace parameters
mappings
 
)
 
end
 
end
 
 
 
function CategoryHandler:namespaceParametersExist()
 
-- Find whether any namespace parameters have been specified.
 
-- We use the order "all" --> namespace params --> "other" as this is what
 
-- the old template did.
 
if self:parameter('all') then
 
return true
 
end
 
if not mappings then
 
mShared = mShared or require('Module:Category handler/shared')
 
mappings = mShared.getParamMappings(true) -- gets mappings with mw.loadData
 
end
 
for ns, params in pairs(mappings) do
 
for i, param in ipairs(params) do
 
if self._args[param] then
 
return true
 
end
 
end
 
end
 
if self:parameter('other') then
 
return true
 
end
 
return false
 
end
 
 
 
function CategoryHandler:getCategories()
 
local params = self:getNamespaceParameters()
 
local nsCategory
 
for i, param in ipairs(params) do
 
local value = self._args[param]
 
if value ~= nil then
 
nsCategory = value
 
break
 
end
 
end
 
if nsCategory ~= nil or self:namespaceParametersExist() then
 
-- Namespace parameters exist - advanced usage.
 
if nsCategory == nil then
 
nsCategory = self:parameter('other')
 
end
 
local ret = {self:parameter('all')}
 
local numParam = tonumber(nsCategory)
 
if numParam and numParam >= 1 and math.floor(numParam) == numParam then
 
-- nsCategory is an integer
 
ret[#ret + 1] = self._args[numParam]
 
else
 
ret[#ret + 1] = nsCategory
 
end
 
if #ret < 1 then
 
return nil
 
else
 
return table.concat(ret)
 
end
 
elseif self._data.defaultNamespaces[self.title.namespace] then
 
-- Namespace parameters don't exist, simple usage.
 
return self._args[1]
 
end
 
return nil
 
end
 
 
 
--------------------------------------------------------------------------------
 
-- Exports
 
--------------------------------------------------------------------------------
 
 
 
local p = {}
 
 
 
function p._exportClasses()
 
-- Used for testing purposes.
 
return {
 
CategoryHandler = CategoryHandler
 
}
 
end
 
 
 
function p._main(args, data)
 
data = data or mw.loadData('Module:Category handler/data')
 
local handler = CategoryHandler.new(data, args)
 
if handler:isSuppressed() then
 
return nil
 
end
 
return handler:getCategories()
 
end
 
  
function p.main(frame, data)
+
    -- Trim whitespace and remove blank arguments for the following args:
data = data or mw.loadData('Module:Category handler/data')
+
    -- 1, 2, 3 etc., "nocat", "categories", "subpage", and "page".
local args = require('Module:Arguments').getArgs(frame, {
+
    for k, v in pairs(origArgs) do
wrappers = data.wrappers,
+
        v = mw.text.trim(v) -- Trim whitespace.
valueFunc = function (k, v)
+
        if type(k) == 'number'
v = trimWhitespace(v)
+
            or k == cfg.nocat
if type(k) == 'number' then
+
            or k == cfg.categories
if v ~= '' then
+
            or k == cfg.subpage
return v
+
            or k == cfg.page then
else
+
            if v ~= '' then
return nil
+
                args[k] = v
end
+
            end
else
+
        else
return v
+
            args[k] = v
end
+
        end
end
+
    end
})
+
   
return p._main(args, data)
+
    -- Lower-case "nocat", "categories", "category2", and "subpage".
 +
    local lowercase = { cfg.nocat, cfg.categories, cfg.category2, cfg.subpage }
 +
    for _, v in ipairs( lowercase ) do
 +
        if args[v] then
 +
            args[v] = mw.ustring.lower( args[v] )
 +
        end
 +
    end
 +
   
 +
    return _main()
 
end
 
end
  
 
return p
 
return p

Please note that all contributions to MINR.ORG WIKI may be edited, altered, or removed by other contributors. If you do not want your writing to be edited mercilessly, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource (see MINR.ORG WIKI:Copyrights for details). Do not submit copyrighted work without permission!

Cancel Editing help (opens in new window)