Module:Namespace detect

From CasperTech Wiki
Revision as of 13:07, 28 June 2013 by D1cd5b71-6209-4595-9bf0-771bf689ce00 (talk | contribs) (1 revision)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Documentation for this module may be created at Module:Namespace detect/doc

----------------------------------------------------------------------
--                                                                  --
--                        NAMESPACE DETECT                          --
--                                                                  --
--      This module implements the {{namespace detect}} 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. Function names   --
--      can be configured for different wikis by altering the       --
--      values in the "cfg" table.                                  --
--                                                                  --
----------------------------------------------------------------------

----------------------------------------------------------------------
--                      Configuration data                          --
--      Language-specific parameter names can be set here.          --
----------------------------------------------------------------------

local cfg = {}

-- The name for the parameter to display content for the main namespace:
cfg.main = 'main'

-- The name for the parameter to display content in talk namespaces:
cfg.talk = 'talk'

-- The name for the parameter to display content for "other" namespaces
-- (namespaces for which parameters have not been specified, or for when
-- cfg.demospace is set to cfg.other):
cfg.other = 'other'

-- The name for the parameter to set a demonstration namespace:
cfg.demospace = 'demospace'

-- The name for the parameter to set a specific page to compare:
cfg.page = 'page'

-- The header for the namespace column in the wikitable containing the 
-- list of possible subject-space parameters.
cfg.wikitableNamespaceHeader = 'Namespace'

-- The header for the wikitable containing the list of possible
-- subject-space parameters.
cfg.wikitableAliasesHeader = 'Aliases'

----------------------------------------------------------------------
--                     End configuration data                       --
----------------------------------------------------------------------

-- Specify variables available to the whole module
local p = {}
local args = {}

-- Get the page object. This will return the page object for the page
-- specified, or nil if there are errors in the title or if the
-- expensive function count has been exceeded.
local function getPageObject()
    -- Get the title object for args.page if it is specified. Otherwise
    -- get the title object for the current page.
    if args[cfg.page] then
        -- Get the page object, passing the function through pcall 
        -- in case we are over the expensive function count limit.
        local noError, pageObject = pcall(mw.title.new, args[cfg.page])
        if not noError then
            return nil
        else
            return pageObject
        end
    else
        return mw.title.getCurrentTitle()
    end    
end

-- Detects the namespace for a page object.
local function detectNamespace(pageObject)
    if pageObject.isTalkPage then
        -- Returns the value of cfg.talk or the local "Talk" namespace name. 
        return cfg.talk or mw.site.namespaces[1].name
    else
        return pageObject.nsText
    end
end

-- Gets the namespace name to compare to the arguments. The returned value
-- is lower-case.
local function getNamespace()
    local ret
    if args[cfg.demospace] then
        -- Handle "demospace = main" properly.
        if mw.ustring.lower( args[cfg.demospace] ) == cfg.main then
            ret = mw.site.namespaces[0].name
        else
            ret = args[cfg.demospace]
        end
    else
        local pageObject = getPageObject()
        if pageObject then
            ret = detectNamespace( getPageObject() )
        else
            return nil -- return nil if the page object doesn't exist.
        end
    end
    return mw.ustring.lower(ret)
end

-- Compare the namespace found with the parameters that have been
-- specified, and return content of the appropriate parameter.
local function compare()
    local namespace = getNamespace()
    
    -- First, compare mainspace parameters.
    if namespace == mw.site.namespaces[0].name and args[cfg.main] then
        return args[cfg.main]
    end
    
    -- Next, compare parameters for non-main namespaces.
    for nsid, ns in pairs( mw.site.namespaces ) do
        local nsname = mw.ustring.lower( ns.name )
        local canonicalName = mw.ustring.lower( ns.canonicalName )
        -- Check the namespace, and ignore main namespace values.
        if nsid ~= 0 and nsname == namespace then
            -- Check local namespace name.
            if args[nsname] then
                return args[nsname]
            -- Check canonical namespace name.
            elseif args[canonicalName] then
                return args[canonicalName]
            else
                -- Check alias names.
                for _, alias in ipairs( ns.aliases ) do
                    local aliasArg = args[ mw.ustring.lower( alias ) ]
                    if aliasArg then
                        return aliasArg
                    end
                end
            end
        end
    end
    
    -- Finally, return parameters for other namespaces. This happens if
    -- there was no text specified for the namespace that was detected
    -- or if the demospace parameter is not a valid namespace. Note that
    -- the parameter for the detected namespace must be completely
    -- absent for this to happen, not merely blank.
    if args[cfg.other] then
        return args[cfg.other]
    end
end

-- Process the arguments.
function p.main(frame)
    -- If called via #invoke, use the args passed into the invoking
    -- template, or the args passed to #invoke if any exist. Otherwise
    -- assume args are being passed directly in.
    local origArgs
    if frame == mw.getCurrentFrame() then
        origArgs = frame:getParent().args
        for k, v in pairs( frame.args ) do
            origArgs = frame.args
            break
        end
    else
        origArgs = frame
    end
    
    -- Trim whitespace and remove blank arguments for demospace and 
    -- page parameters.
    for k, v in pairs(origArgs) do
        v = mw.text.trim(v) -- Trim whitespace.
        if k == cfg.demospace or k == cfg.page then
            if v ~= '' then
                args[k] = v
            end
        else
            args[k] = v
        end
    end
    
    return compare()
end

-- Create a wikitable of all possible namespace parameters.
function p.table()
    -- Start the wikitable.
    local ret = '{| class="wikitable"'
        .. '\n|-'
        .. '\n! ' .. cfg.wikitableNamespaceHeader
        .. '\n! ' .. cfg.wikitableAliasesHeader
    
    -- Generate the row for the main namespace.
    ret = ret .. '\n|-'
        .. '\n| ' .. cfg.main
        .. '\n|'
    
    -- Generate the other wikitable rows.
    for nsid, ns in pairs( mw.site.subjectNamespaces ) do
        if nsid ~= 0 then -- Ignore the main namespace, as it is set in cfg.
            local name = '<code>' .. mw.ustring.lower( ns.name ) .. '</code>'
            local aliases = {}
            if ns.canonicalName ~= ns.name then
                table.insert( aliases, '<code>' .. mw.ustring.lower( ns.canonicalName ) .. '</code>' )
            end
            for _, v in ipairs( ns.aliases ) do
                table.insert( aliases, '<code>' .. mw.ustring.lower(v) .. '</code>' )
            end
            ret = ret .. '\n|-'
                .. '\n| ' .. name
                .. '\n| ' .. table.concat( aliases, ', ' )
        end
    end
    
    -- End the wikitable.
    ret = ret .. '\n|-'
        .. '\n|}'
    
    return ret
end

return p