本模块用于根据指定页面所在的命名空间输出不同内容,是{{Namespace detect}}的Lua实现版本,自动支持所有命名空间名称及其别名。
{{#invoke: Namespace detect | main
| demopage = <!-- 要检测的页面(不填则用当前页面) -->
<!-- 命名空间返回值 -->
| main =
| talk =
| user =
| user_talk =
| 萌娘百科 =
| 萌娘百科_talk =
| file =
| file_talk =
| mediawiki =
| mediawiki_talk =
| template =
| template_talk =
| help =
| help_talk =
| category =
| category_talk =
| widget =
| widget_talk =
| timedtext =
| timedtext_talk =
| module =
| module_talk =
| other = <!-- 其他未指定命名空间 -->
| demospace = <!-- 强制按某命名空间检测(可填ID/名称/别名) -->
| subjectns = <!-- 讨论页按对应内容页命名空间处理(非空即开启) -->
| istalk = <!-- 讨论页保持该讨论命名空间(非空即开启) -->
}}
该模块会根据当前页面或指定的页面,判断所属命名空间,并返回与该命名空间匹配的参数值。
默认情况下,讨论页会归到条目讨论命名空间(即 talk 参数))
subjectns 和 istalk 都是开关参数,通常写成任意非空值即可。demospace 会覆盖实际页面命名空间判断。demopage 无法解析为有效标题,模块会返回 other(若未设置则返回空字符串)。| 参数 | 说明 | 备注 |
|---|---|---|
demopage
|
指定用于判断的页面标题 | 优先于当前页面 |
demospace
|
直接指定要视作的命名空间 | 可填写命名空间ID/名称/别名;优先级高于 demopage 的实际命名空间。
|
subjectns
|
布尔开关 | 若非空,就将讨论页按对应的页面命名空间处理 |
istalk
|
布尔开关 | 若非空,就在讨论页上保持当前命名空间 |
other
|
未命中任何命名空间时的备选值 | 没有匹配参数时使用 |
以及命名空间参数。
main、条目、條目与主模块会按命名空间的规范名称、本地化名称和别名匹配参数名。 参数名在进行比较前会做如下规范化:
_ 转为空格因此,像 user_talk、User talk、USER TALK 这类参数名都可以匹配同一个命名空间。
当页面本身属于讨论页时,处理顺序如下:
subjectns 非空,优先按对应页面命名空间处理。istalk 非空,保持当前命名空间。ns=1。这意味着:
User talk、Template talk 等页面,默认会落到 talk 的结果。istalk。subjectns。{{#invoke:Namespace detect|main
| demopage = <!-- 要检测的页面(不填则用当前页面) -->
| demospace = <!-- 强制按某命名空间检测(可填ID/名称/别名) -->
| subjectns = 1
| istalk = 1
| main = 主命名空间返回值
| T = 模板命名空间返回值
| 模块 = 模块命名空间返回值
| 說明 = 帮助命名空间返回值
| talk = 讨论命名空间返回值
| user_talk = User talk 命名空间返回值
…
| other = 其他命名空间返回值
}}
效果:
模块命名空间返回值
local p = {}
local lower = mw.ustring.lower
local trim = mw.text.trim
local getArgs = require('Module:Arguments').getArgs
local namespaceNameToId
local namespaceKeysCache = {}
-- 主命名空间的别名集合
local MAIN_NAMESPACE_ALIASES = {
"main",
"条目", -- 简体
"條目", -- 繁体
"主"
}
local function addUniqueKey(keys, seen, value)
if not value or value == '' then
return
end
value = lower(value)
if seen[value] then
return
end
seen[value] = true
table.insert(keys, value)
end
local function buildNamespaceNameIndex()
if namespaceNameToId then
return
end
namespaceNameToId = {}
for id, ns in pairs(mw.site.namespaces) do
if ns.name and ns.name ~= '' then
namespaceNameToId[lower(ns.name)] = id
end
if ns.canonicalName and ns.canonicalName ~= '' then
namespaceNameToId[lower(ns.canonicalName)] = id
end
for _, alias in ipairs(ns.aliases or {}) do
if alias and alias ~= '' then
namespaceNameToId[lower(alias)] = id
end
end
end
for _, alias in ipairs(MAIN_NAMESPACE_ALIASES) do
namespaceNameToId[alias] = 0
end
end
local function hasNamespaceParam(args, nsid)
local ns = mw.site.namespaces[nsid]
if not ns then
return false
end
if ns.name and args[lower(ns.name)] ~= nil then
return true
end
if ns.canonicalName and args[lower(ns.canonicalName)] ~= nil then
return true
end
for _, alias in ipairs(ns.aliases or {}) do
if args[lower(alias)] ~= nil then
return true
end
end
return false
end
-- 规范化参数名:小写 + 下划线转空格 + trim
local function normaliseKey(s)
if not s then return nil end
s = tostring(s)
s = lower(s)
s = s:gsub('_', ' ')
s = trim(s)
return s
end
-- 规范化整个参数表
local function normaliseArgs(args)
local out = {}
for k, v in pairs(args) do
if type(k) == 'number' then
out[k] = v
else
out[normaliseKey(k)] = v
end
end
return out
end
-- 解析 demopage 或当前页面
local function getTitle(args)
if args.demopage and args.demopage ~= '' then
return mw.title.new(args.demopage)
end
return mw.title.getCurrentTitle()
end
-- 解析 namespace id(核心逻辑)
local function resolveNamespace(title, args)
local nsid = title and title.namespace or nil
-- demospace 覆盖
if args.demospace and args.demospace ~= '' then
local demospaceName = args.demospace
-- 数字优先路径
local num = tonumber(demospaceName)
if num then
return num
end
-- 名称匹配(含 alias)
buildNamespaceNameIndex()
demospaceName = lower(demospaceName)
local resolvedId = namespaceNameToId[demospaceName]
if resolvedId ~= nil then
return resolvedId
end
end
-- talk / subjectns 处理
if title and title.isTalkPage then
-- 若显式提供了当前讨论命名空间参数,优先使用它
if hasNamespaceParam(args, nsid) then
return nsid
end
if args.subjectns and args.subjectns ~= '' then
local subject = mw.site.namespaces[nsid].subject
return subject and subject.id or nsid
end
-- 显式指定 istalk 时使用当前 ns
if args.istalk and args.istalk ~= '' then
return nsid
end
-- 二者皆空时默认归到 talk 命名空间(ns=1)
return 1
end
return nsid
end
-- 获取 namespace 可匹配 key 列表(含 alias)
local function getNamespaceKeys(nsid)
if namespaceKeysCache[nsid] then
return namespaceKeysCache[nsid]
end
local ns = mw.site.namespaces[nsid]
local keys = {}
local seen = {}
if ns then
addUniqueKey(keys, seen, ns.name)
if ns.canonicalName then
addUniqueKey(keys, seen, ns.canonicalName)
end
for _, alias in ipairs(ns.aliases or {}) do
addUniqueKey(keys, seen, alias)
end
end
-- 主命名空间
if nsid == 0 then
for _, alias in ipairs(MAIN_NAMESPACE_ALIASES) do
addUniqueKey(keys, seen, alias)
end
end
namespaceKeysCache[nsid] = keys
return keys
end
function p.main(frame)
local rawArgs = getArgs(frame, {
removeBlanks = false
})
local args = normaliseArgs(rawArgs)
local title = getTitle(args)
local nsid = resolveNamespace(title, args)
if nsid == nil then
return args.other or ''
end
local keys = getNamespaceKeys(nsid)
-- 按 namespace alias 顺序匹配参数
for _, key in ipairs(keys) do
if args[key] ~= nil then
return args[key]
end
end
-- fallback
return args.other or ''
end
return p