跳转到内容

Module:Namespace

勤求古训,博采众方
local p = {}
local data = mw.loadData('Module:Namespace/data')
local mLan = require('Module:Lan2')

local function Error(msg)
    return mError.error { '[[Module:Namespace]]错误:' .. msg }
end

local function ifempty(ret, val)
    return ret ~= '' and ret or val
end

local function inArray(str, arr)
    for i, v in ipairs(arr) do
        if str == v then
            return v
        end
    end
    return nil
end

function p._lan(args, lang)
    return mLan.main(args,
        ifempty(lang and lang:lower(), mw.getCurrentFrame():callParserFunction { name = 'int', args = { 'Lang' } }), {
        ['def'] = { 'en' }
    })
end

function p._isNamespace(id)
    id = tostring(id)
    local PNS, _PNSIsTalk = p._isPseudoNamespace(id)
    return
        PNS
        or mw.site.namespaces[tonumber(id) or id:lower()] and mw.site.namespaces[tonumber(id) or id:lower()].id
        or nil
end

function p.namespace(frame)
    local args
    if frame == mw.getCurrentFrame() then
        -- 我们通过 #invoke 被调用。参数从模板页面传递到模块,
        -- 所以使用传递到模板中的参数。
        if not getArgs then
            getArgs = require('Module:Arguments').getArgs
        end
        args = getArgs(frame, { parentFirst = true })
    else
        -- 我们从另一个模块或调试控制台被调用,所以假设
        -- 参数是直接传入的。
        args = frame
        if type(args) ~= type({}) then args = { frame } end
    end
    id = tostring(args.namespace or args[1])
    local PNS, _PNSIsTalk = p._isPseudoNamespace()
    return (PNS or mw.title.getCurrentTitle().namespace) == p._isNamespace(id) and (args['then'] or args[2]) or (args['else'] or args[3])
end

local MsgCallFunc = {
    ['NamespacesDisplay'] = (function(nsid)
        return data.Namespace[tostring(nsid)]
    end),
    ['NamespacesConversionDisplay'] = (function(nsid)
        return data.Namespace[tostring(nsid) .. '-display'] or data.Namespace[tostring(nsid)]
    end),
}

function p._PseudoNamespaceDisplay(lang, ns, isTalk)
    if not inArray(ns, data['PseudoNamespace']['list']) then
        error('输入伪命名空间错误。')
    end

    local display = p._lan(data.PseudoNamespace.messages[isTalk and 'talk' or 'main'], lang)
    display = mw.ustring.gsub(display, '$1', p._lan(data.PseudoNamespace[ns], lang))
    return display
end

for key, func in pairs(MsgCallFunc) do
    p['_' .. key] = function(lang, ns)
        if type(lang) == 'table' then
            ns = lang[2]
            lang = lang[1]
        end
        local PNS, PNSIsTalk
        local lang = lang
        local nsid
        if ns then
            if ns == '' then
                nsid = -3
            else
                local nsid_info = mw.site.namespaces[tonumber(ns)] or mw.site.namespaces[ns]
                if not nsid_info then
                    PNS, PNSIsTalk = p._isPseudoNamespace(ns, false)
                    nsid = -3
                else
                    nsid = nsid_info.id
                end
            end
        else
            local title = mw.title.getCurrentTitle()
            nsid = title.namespace
            if nsid == 0 or nsid == 1 then
                PNS, PNSIsTalk = p._isPseudoNamespace(title, true)
            end
        end
        if PNS then
            return p._PseudoNamespaceDisplay(lang, PNS, PNSIsTalk)
        elseif nsid < -2 then
            error('输入命名空间错误。')
        end
        return p._lan(MsgCallFunc[key](nsid), lang)
    end

    p[key] = function(frame)
        local args = require('Module:Arguments').getArgs(frame, {
            valueFunc = function(key, value)
                if key == 2 then
                    return type(value) == 'string' and mw.text.trim(value) or value
                elseif value then
                    value = mw.text.trim(value)
                    if value ~= '' then
                        return value
                    end
                end
                return nil
            end
        })
        local status, wt = pcall(p['_' .. key], args)
        if status then
            return wt
        end
        return tostring(mw.html.create('span'):attr('style', 'color:red;'):wikitext(
            p._lan({
                ['en'] = 'Input namespace error',
                ['zh-hans'] = '输入命名空间错误',
                ['zh-hant'] = '输入命名空间错误'
            }, lang)
        ):done())
    end
end

function p._isPseudoNamespace(ns, isPage)
    if not ns then
        ns = mw.title.getCurrentTitle()
        isPage = true
    elseif ns == '' then
        return nil, false
    end

    local success, titleObj
    if type(ns) == type('') then
        if not ns:match(':') then
            ns = ns .. ':'
        end
        success, titleObj = pcall(mw.title.new, ns)
        if not success or not titleObj or not titleObj:inNamespaces(0, 1) then
            return nil, false
        end
        
        local split = mw.text.split(titleObj.text, ':')
        if not isPage and (#split > 2 or (split[2] ~= '' and split[2] ~= nil)) then
            -- isPage = false 时仅允许:
            -- 1. PNS
            -- 2. PNS:
            return nil, false
        end
        ns = split[1] -- 移除冒号后的东西
    elseif type(ns) == type({}) and type(ns.text) == type('') and isPage then
        -- 如果传入页面对象,则 isPage 必然要是 true
        if not ns:inNamespaces(0, 1) then
            return nil, false
        end

        ns = mw.text.split(ns.text, ':')[1] -- 移除冒号后的东西
    else
        error(string.format(
            'bad argument #1 to \'_isPseudoNamespace[isPage=%s]\' (%s expected, got %s)',
            isPage and 'true' or 'false',
            isPage and 'string or mw.title object' or 'string',
            type(ns)
        ))
    end
    if inArray(ns, data['PseudoNamespace']['list']) then
        return ns, titleObj.namespace == 1
    end
    return nil, false
end

function p.ispseudo(frame)
    local arg = require('Module:Arguments').getArgs(frame)['1']
    local PNS, _isTalk = p._isPseudoNamespace(arg, true)
    return PNS or ''
end

p._PNSArray = data['PseudoNamespace']['list']

return p