打开/关闭菜单
打开/关闭外观设置菜单
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。

模块:Documentation

来自电棍ottowiki
OctoberSama留言 | 贡献2025年6月17日 (二) 22:15的版本

第231行Lua错误:message: cfg 键 doc-link-display 类型错误(需要 string,得到 nil)

--源代码来自维基百科:https://zh.wikipedia.org/w/index.php?title=Module:Documentation&oldid=87749641
--该部分代码使用CC BY-SA 4.0许可证 (https://creativecommons.org/licenses/by-sa/4.0/)
-- This module implements {{documentation}}.

-- 依赖模块
local getArgs = require('Module:Arguments').getArgs

-- 配置表
local cfg = mw.loadData('Module:Documentation/config')

local p = {}

-- 常用函数
local ugsub = mw.ustring.gsub
local format = mw.ustring.format

-- 获取配置消息并做 $1、$2 替换
local function message(key, vals, expectType)
    local msg = cfg[key]
    expectType = expectType or "string"
    if type(msg) ~= expectType then
        error("message: cfg 键 " .. key .. " 类型错误(需要 " .. expectType .. ",得到 " .. type(msg) .. ")", 2)
    end
    if not vals then return msg end
    local function repl(n)
        n = tonumber(n)
        return vals[n] or error("message: 无法找到 $"..n.." 对应的值,cfg 键 "..key, 4)
    end
    return ugsub(msg, "%$([1-9][0-9]*)", repl)
end

-- 生成维基链接
local function makeWikilink(page, display)
    if display then
        return format("[[%s|%s]]", page, display)
    else
        return format("[[%s]]", page)
    end
end

-- 生成外部 URL 链接
local function makeUrlLink(url, display)
    return format("[%s %s]", url, display)
end

-- 生成工具栏格式 (小号)
local function makeToolbar(...)
    local parts = {}
    for i = 1, select("#", ...) do
        parts[#parts+1] = select(i, ...)
    end
    if #parts == 0 then return "" end
    return "(" .. table.concat(parts, " | ") .. ")"
end

-- 入口:处理 frame.args 并调用 _main
local function makeInvoke(fn)
    return function(frame)
        local args = getArgs(frame, {
            valueFunc = function(k, v)
                if type(v)=="string" then
                    v = v:match("^%s*(.-)%s*$")
                    if k=="heading" or v~="" then return v end
                    return nil
                end
                return v
            end
        })
        return p[fn](args)
    end
end

function p.nonexistent(frame)
    if mw.title.getCurrentTitle().subpageText == "testcases" then
        return frame:expandTemplate{ title = "module test cases notice" }
    else
        return p.main(frame)
    end
end

p.main = makeInvoke("_main")

function p._main(args)
    local env = p.getEnvironment(args)
    local root = mw.html.create()
    root
        :wikitext(p._getModuleWikitext(args, env))
        :wikitext(p.protectionTemplate(env))
        :tag("div")
            :addClass(message("container"))
            :newline()
            :wikitext(p._startBox(args, env))
            :wikitext(p._content(args, env))
            :tag("div")
                :addClass(message("clear"))
                :done()
            :done()
        :wikitext(p._endBox(args, env))
        :wikitext(p.addTrackingCategories(env))
    return tostring(root)
end

-- 环境信息
function p.getEnvironment(args)
    local env, funcs = {}, {}
    setmetatable(env, {
        __index = function(t, k)
            if funcs[k] then
                local ok, v = pcall(funcs[k])
                if ok then
                    env[k] = v
                    return v
                end
            end
        end
    })

    funcs.title = function()
        if args.page then
            return mw.title.new(args.page)
        else
            return mw.title.getCurrentTitle()
        end
    end

    funcs.subjectSpace = function()
        return mw.site.namespaces[env.title.namespace].subject.id
    end

    funcs.templateTitle = function()
        local title = env.title
        return mw.title.makeTitle(env.subjectSpace, title.baseText or title.text)
    end

    funcs.docTitle = function()
        local base = env.templateTitle.prefixedText
        local sub = args[1] or (base .. "/" .. message("doc-subpage"))
        return mw.title.new(sub)
    end

    funcs.protectionLevels = function()
        return env.title.protectionLevels
    end

    return env
end

-- 生成上方标题和工具链接
p.startBox = makeInvoke("_startBox")
function p._startBox(args, env)
    -- icon + “模块文档”等标题
    local heading = ""
    local space = env.subjectSpace
    if space == 828 then
        heading = message("documentation-icon-wikitext") .. " " .. message("module-namespace-heading")
    elseif space == 10 then
        heading = message("documentation-icon-wikitext") .. " " .. message("template-namespace-heading")
    else
        heading = message("documentation-icon-wikitext") .. " " .. message("other-namespaces-heading")
    end

    -- 开始构建 start box
    local linksData = p.makeStartBoxLinksData(args, env)
    local links = linksData and p.renderStartBoxLinks(linksData) or ""
    return '<div class="' .. message("start-box-class") .. '">'
        .. '<span class="' .. message("main-div-heading-class") .. '">' .. heading .. '</span>'
        .. '<span class="' .. message("start-box-link-classes") .. '">' .. links .. '</span>'
        .. '</div>'
end

function p.makeStartBoxLinksData(args, env)
    local title = env.templateTitle
    local doc = env.docTitle
    if not title or not doc then return nil end

    local purge = makeWikilink("Special:Purge/" .. title.prefixedText, message("purge-link-display"))
    if doc.exists then
        local view = makeWikilink(doc.prefixedText, message("view-link-display"))
        local edit = makeWikilink("Special:EditPage/" .. doc.prefixedText, message("edit-link-display"))
        local hist = makeWikilink("Special:PageHistory/" .. doc.prefixedText, message("history-link-display"))
        return { view=view, edit=edit, history=hist, purge=purge }
    else
        local url = doc:canonicalUrl{ action="edit", preload=message("module-preload") }
        local create = makeUrlLink(url, message("create-link-display"))
        return { create=create, purge=purge }
    end
end

function p.renderStartBoxLinks(data)
    if data.create then
        return makeToolbar(data.create, data.purge)
    else
        return makeToolbar(data.view, data.edit, data.history, data.purge)
    end
end

-- 文档主体内容
p.content = makeInvoke("_content")
function p._content(args, env)
    local doc = env.docTitle
    local content = args.content
    if not content and doc and doc.exists then
        content = mw.getCurrentFrame():expandTemplate{ title = doc.prefixedText }
    end
    return "\n" .. (content or "") .. "\n"
end

-- 末尾仅保留分类提示
p.endBox = makeInvoke("_endBox")
function p._endBox(args, env)
    local space = env.subjectSpace
    local doc = env.docTitle
    if not space or not doc then return nil end

    -- 只在模板、模块或用户空间且不是内联文档时显示分类提示
    if doc.exists or space==2 or space==10 or space==828 then
        if not args.content and not args[1] then
            local catBlurb = p.makeCategoriesBlurb(args, env)
            if catBlurb and catBlurb ~= "" then
                return '<div role="note" class="' .. message("end-box-class")
                    .. ' ' .. message("end-box-plainlinks") .. '">' .. catBlurb .. '</div>'
            end
        end
    end
    return nil
end

function p.makeCategoriesBlurb(args, env)
    local doc = env.docTitle
    if not doc then return nil end
    local link = makeWikilink(doc.prefixedText, message("doc-link-display"))
    return message("add-categories-blurb", { link })
end

-- 跟踪分类
function p.addTrackingCategories(env)
    local title = env.title
    local space = env.subjectSpace
    if not title or not space then return "" end
    local sub = title.subpageText
    if message("display-strange-usage-category", nil, "boolean")
       and ( sub == message("doc-subpage")
             or (space~=828 and sub==message("testcases-subpage")) )
    then
        return makeWikilink(mw.site.namespaces[14].name .. ":" .. message("strange-usage-category"))
    end
    return ""
end

-- 获取模块自身 wikitext(保持原版逻辑)
function p._getModuleWikitext(args, env)
    local t = mw.title.getCurrentTitle()
    if t.contentModel ~= "Scribunto" then return end
    pcall(require, t.prefixedText)
    local mwtext = package.loaded["Module:Module wikitext"]
    if mwtext then return mwtext.main() end
end

-- 保护图标(保持原版)
function p.protectionTemplate(env)
    local prot = env.protectionLevels
    if not prot then return nil end
    if prot.edit and prot.edit[1] then
        return require("Module:Protection banner")._main{ message = message("protection-reason-edit"), small = true }
    end
    return nil
end

return p