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

模块:Documentation

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

第135行Lua错误:message: type error in message cfg.main-div-class (string expected, got 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}}.

-- Get required modules.
local getArgs = require('Module:Arguments').getArgs

-- Get the config table.
local cfg = mw.loadData('Module:Documentation/config')

local p = {}

-- Often-used functions.
local ugsub = mw.ustring.gsub
local format = mw.ustring.format

----------------------------------------------------------------------------
-- Helper functions
--
-- These are defined as local functions, but are made available in the p
-- table for testing purposes.
----------------------------------------------------------------------------
local function message(cfgKey, valArray, expectType)
    --[[
    -- Gets a message from the cfg table and formats it if appropriate.
    --]]
    local msg = cfg[cfgKey]
    expectType = expectType or 'string'
    if type(msg) ~= expectType then
        error('message: type error in message cfg.' .. cfgKey .. ' (' ..
              expectType .. ' expected, got ' .. type(msg) .. ')', 2)
    end
    if not valArray then
        return msg
    end

    local function getMessageVal(match)
        match = tonumber(match)
        return valArray[match] or error('message: no value found for key $' .. match .. ' in message cfg.' .. cfgKey, 4)
    end

    return ugsub(msg, '$([1-9][0-9]*)', getMessageVal)
end

p.message = message

local function makeWikilink(page, display)
    if display then
        return format('[[%s|%s]]', page, display)
    else
        return format('[[%s]]', page)
    end
end

p.makeWikilink = makeWikilink

local function makeCategoryLink(cat, sort)
    local catns = mw.site.namespaces[14].name
    return makeWikilink(catns .. ':' .. cat, sort)
end

p.makeCategoryLink = makeCategoryLink

local function makeUrlLink(url, display)
    return format('[%s %s]', url, display)
end

p.makeUrlLink = makeUrlLink

local function makeToolbar(...)
    local ret = {}
    local lim = select('#', ...)
    if lim < 1 then
        return nil
    end
    for i = 1, lim do
        ret[#ret + 1] = select(i, ...)
    end
    -- 'documentation-toolbar'
    return format(
        '<span class="%s">(%s)</span>',
        message('start-box-link-classes'),
        table.concat(ret, ' &#124; ')
    )
end

p.makeToolbar = makeToolbar

----------------------------------------------------------------------------
-- Argument processing
----------------------------------------------------------------------------
local function makeInvokeFunc(funcName)
    return function (frame)
        local args = getArgs(frame, {
            valueFunc = function (key, value)
                if type(value) == 'string' then
                    value = value:match('^%s*(.-)%s*$') -- Remove whitespace.
                    if key == 'heading' or value ~= '' then
                        return value
                    else
                        return nil
                    end
                else
                    return value
                end
            end
        })
        return p[funcName](args)
    end
end

----------------------------------------------------------------------------
-- Entry points
----------------------------------------------------------------------------
function p.nonexistent(frame)
    -- Preserve existing nonexistent behavior (testcases notice)
    if mw.title.getCurrentTitle().subpageText == 'testcases' then
        return frame:expandTemplate{title = 'module test cases notice'}
    else
        return p.main(frame)
    end
end

p.main = makeInvokeFunc('_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))
        -- Sandbox notice removed by customization.
        :tag('div')
            :addClass(message('main-div-class'))
            :newline()
            :wikitext(p._startBox(args, env))
            :wikitext(p._content(args, env))
            :tag('div')
                :addClass(message('clear'))
                :done()
            :newline()
            :done()
        :wikitext(p._endBox(args, env))
    return mw.getCurrentFrame():extensionTag(
        'templatestyles', '', {src=cfg['templatestyles-scr']}
    ) .. tostring(root)
end

----------------------------------------------------------------------------
-- Environment settings
----------------------------------------------------------------------------
function p.getEnvironment(args)
    local env, envFuncs = {}, {}
    setmetatable(env, {
        __index = function (t, key)
            local envFunc = envFuncs[key]
            if envFunc then
                local success, val = pcall(envFunc)
                if success then
                    env[key] = val -- Memoise.
                    return val
                end
            end
            return nil
        end
    })

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

    function envFuncs.templateTitle()
        local subjectSpace = env.subjectSpace
        local title = env.title
        local subpage = title.subpageText
        if subpage == message('sandbox-subpage')
           or subpage == message('testcases-subpage')
           or (subpage == message('doc-subpage') and mw.title.getCurrentTitle().namespace == env.docSpace)
        then
            return mw.title.makeTitle(subjectSpace, title.baseText)
        else
            return mw.title.makeTitle(subjectSpace, title.text)
        end
    end

    function envFuncs.docTitle()
        local title = env.title
        local docname = args[1]
        local docpage
        if docname then
            docpage = docname
        else
            docpage = env.docpageBase .. '/' .. message('doc-subpage')
        end
        return mw.title.new(docpage)
    end

    function envFuncs.sandboxTitle()
        return mw.title.new(env.docpageBase .. '/' .. message('sandbox-subpage'))
    end

    function envFuncs.testcasesTitle()
        return mw.title.new(env.docpageBase .. '/' .. message('testcases-subpage'))
    end

    function envFuncs.protectionLevels()
        return env.title.protectionLevels
    end

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

    function envFuncs.docSpace()
        local subjectSpace = env.subjectSpace
        if subjectSpace == 0 or subjectSpace == 6 or subjectSpace == 8 or subjectSpace == 14 then
            return subjectSpace + 1
        else
            return subjectSpace
        end
    end

    function envFuncs.docpageBase()
        local templateTitle = env.templateTitle
        local docSpace = env.docSpace
        local docSpaceText = mw.site.namespaces[docSpace].name
        return docSpaceText .. ':' .. templateTitle.text
    end

    function envFuncs.compareUrl()
        local templateTitle = env.templateTitle
        local sandboxTitle = env.sandboxTitle
        if templateTitle.exists and sandboxTitle.exists then
            local compareUrl = mw.uri.canonicalUrl(
                'Special:ComparePages',
                { page1 = templateTitle.prefixedText, page2 = sandboxTitle.prefixedText }
            )
            return tostring(compareUrl)
        else
            return nil
        end
    end

    return env
end

----------------------------------------------------------------------------
-- Auxiliary templates
----------------------------------------------------------------------------
p.getModuleWikitext = makeInvokeFunc('_getModuleWikitext')

function p._getModuleWikitext(args, env)
    local currentTitle = mw.title.getCurrentTitle()
    if currentTitle.contentModel ~= 'Scribunto' then return end
    pcall(require, currentTitle.prefixedText) -- attempt to load module
    local moduleWikitext = package.loaded["Module:Module wikitext"]
    if moduleWikitext then
        return moduleWikitext.main()
    end
end

-- Sandbox notice completely removed.
function p.sandboxNotice(args, env)
    return nil
end

function p.protectionTemplate(env)
    local protectionLevels = env.protectionLevels
    if not protectionLevels then
        return nil
    end
    local editProt = protectionLevels.edit and protectionLevels.edit[1]
    local moveProt = protectionLevels.move and protectionLevels.move[1]
    if editProt then
        return require('Module:Protection banner')._main{
            message('protection-reason-edit'), small = true
        }
    elseif moveProt and moveProt ~= 'autoconfirmed' then
        return require('Module:Protection banner')._main{
            action = 'move', small = true
        }
    else
        return nil
    end
end

----------------------------------------------------------------------------
-- Start box
----------------------------------------------------------------------------
p.startBox = makeInvokeFunc('_startBox')

function p._startBox(args, env)
    env = env or p.getEnvironment(args)
    local links
    local content = args.content
    if not content or args[1] then
        local linksData = p.makeStartBoxLinksData(args, env)
        if linksData then
            links = p.renderStartBoxLinks(linksData)
        end
    end
    local data = p.makeStartBoxData(args, env, links)
    if data then
        return p.renderStartBox(data)
    else
        return nil
    end
end

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

    -- Create link if /doc doesn't exist.
    local preload = args.preload
    if not preload then
        if subjectSpace == 828 then -- Module namespace
            preload = message('module-preload')
        else
            preload = message('docpage-preload')
        end
    end

    return {
        title = title,
        docTitle = docTitle,
        viewLinkDisplay = message('view-link-display'),
        editLinkDisplay = message('edit-link-display'),
        historyLinkDisplay = message('history-link-display'),
        purgeLinkDisplay = message('purge-link-display'),
        preload = preload,
        createLinkDisplay = message('create-link-display')
    }
end

function p.renderStartBoxLinks(data)
    local docTitle = data.docTitle
    local purgeLink = makeWikilink("Special:Purge/" .. data.title.prefixedText, data.purgeLinkDisplay)
    if docTitle.exists then
        local viewLink = makeWikilink(docTitle.prefixedText, data.viewLinkDisplay)
        local editLink = makeWikilink("Special:EditPage/" .. docTitle.prefixedText, data.editLinkDisplay)
        local historyLink = makeWikilink("Special:PageHistory/" .. docTitle.prefixedText, data.historyLinkDisplay)
        return "&#91;" .. viewLink .. "&#93; &#91;" .. editLink .. "&#93; &#91;" .. historyLink .. "&#93; &#91;" .. purgeLink .. "&#93;"
    else
        local createLink = makeUrlLink(docTitle:canonicalUrl{action = 'edit', preload = data.preload}, data.createLinkDisplay)
        return "&#91;" .. createLink .. "&#93; &#91;" .. purgeLink .. "&#93;"
    end
end

function p.makeStartBoxData(args, env, links)
    local subjectSpace = env.subjectSpace
    if not subjectSpace then
        subjectSpace = 2
    end
    local data = {}

    -- Heading
    local heading = args.heading
    if heading == '' then
        return nil
    end
    if heading then
        data.heading = heading
    elseif subjectSpace == 10 then -- Template namespace
        data.heading = message('documentation-icon-wikitext') .. ' ' .. message('template-namespace-heading')
    elseif subjectSpace == 828 then -- Module namespace
        data.heading = message('documentation-icon-wikitext') .. ' ' .. message('module-namespace-heading')
    elseif subjectSpace == 6 then -- File namespace
        data.heading = message('file-namespace-heading')
    else
        data.heading = message('other-namespaces-heading')
    end

    -- Heading CSS
    local headingStyle = args['heading-style']
    if headingStyle then
        data.headingStyleText = headingStyle
    else
        data.headingClass = message('heading-div-class')
    end

    if links then
        data.linksClass = message('start-box-linkclasses')
        data.links = links
    end

    return data
end

function p.renderStartBox(data)
    local sbox = mw.html.create('div')
    sbox
        :addClass(message('header-div-class'))
        :newline()
        :tag('span')
            :addClass(data.headingClass)
            :attr('id', 'documentation-heading')
            :cssText(data.headingStyleText)
            :wikitext(data.heading)
    local links = data.links
    if links then
        sbox:tag('span')
            :addClass(data.linksClass)
            :attr('id', data.linksId)
            :wikitext(links)
    end
    return tostring(sbox)
end

----------------------------------------------------------------------------
-- Documentation content
----------------------------------------------------------------------------
p.content = makeInvokeFunc('_content')

function p._content(args, env)
    env = env or p.getEnvironment(args)
    local docTitle = env.docTitle
    local content = args.content
    if not content and docTitle and docTitle.exists then
        content = args._content or mw.getCurrentFrame():expandTemplate{title = docTitle.prefixedText}
    end
    return '\n' .. (content or '') .. '\n'
end

p.contentTitle = makeInvokeFunc('_contentTitle')

function p._contentTitle(args, env)
    env = env or p.getEnvironment(args)
    local docTitle = env.docTitle
    if not args.content and docTitle and docTitle.exists then
        return docTitle.prefixedText
    else
        return ''
    end
end

----------------------------------------------------------------------------
-- End box
----------------------------------------------------------------------------
p.endBox = makeInvokeFunc('_endBox')

function p._endBox(args, env)
    env = env or p.getEnvironment(args)
    local subjectSpace = env.subjectSpace
    local docTitle = env.docTitle
    if not subjectSpace or not docTitle then
        return nil
    end

    local linkBox = args['link box']
    if linkBox == 'off'
            or not (docTitle.exists or subjectSpace == 2 or subjectSpace == 828 or subjectSpace == 10)
    then
        return nil
    end

    -- Removed transclusion, experiment, category, and subpages prompts.
    local text = ''

    local box = mw.html.create('div')
    box:attr('role', 'note')
        :addClass(message('footer-div-class'))
        :addClass('plainlinks')
        :wikitext(text)
        :done()

    return '\n' .. tostring(box)
end

function p.addTrackingCategories(env)
    local title = env.title
    local subjectSpace = env.subjectSpace
    if not title or not subjectSpace then
        return nil
    end
    local subpage = title.subpageText
    if message('display-strange-usage-category', nil, 'boolean')
            and (
                    subpage == message('doc-subpage')
                    or (subjectSpace ~= 828 and subpage == message('testcases-subpage'))
            )
    then
        return makeCategoryLink(message('strange-usage-category'))
    end
    return ''
end

return p