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

模块:GFInfobox:修订间差异

来自OGAS数据中枢
弃权者留言 | 贡献
无编辑摘要
弃权者留言 | 贡献
无编辑摘要
第9行: 第9行:
end
end


-- 只用于不含用户输入模板的字段(颜色、稀有度等由 Lua 自己构造的模板调用)
-- 安全展开不含用户输入的模板(如颜色模板)
local function expandSafe(frame, s)
local function expandSafe(frame, s)
     if not s then return nil end
     if not s then return nil end
     return frame:preprocess(s)
     return frame:preprocess(s)
end
-- 展开可能含用户输入模板的字段(如 ruby、黑幕等)
local function expandField(frame, key)
    local text = cleanParam(frame:getParent().args[key])
    if not text then return nil end
    return frame:preprocess(text)
end
end


第31行: 第38行:
             colors[math.floor(num)],
             colors[math.floor(num)],
             string.rep('★', math.floor(num))
             string.rep('★', math.floor(num))
         ), false -- false = 已经是 HTML,不需要 MediaWiki 再展开
         ), false
     end
     end
     return rarity, false
     return rarity, false
第45行: 第52行:


     -- 颜色字段:由 Lua 构造模板调用字符串,用 preprocess 展开,安全
     -- 颜色字段:由 Lua 构造模板调用字符串,用 preprocess 展开,安全
     local function fmtColor(raw, cType)
     local function fmtColor(rawColor, cType)
         raw = cleanParam(raw)
         rawColor = cleanParam(rawColor)
         if not raw then return nil end
         if not rawColor then return nil end
         return expandSafe(frame, '{{' .. cType .. '_color|' .. raw .. '}}')
         return expandSafe(frame, '{{' .. cType .. '_color|' .. rawColor .. '}}')
     end
     end


第55行: 第62行:
     local rarity    = p.formatRarity(cleanParam(args['稀有度']))
     local rarity    = p.formatRarity(cleanParam(args['稀有度']))


     ---------- 策略:含用户输入的字段,原样输出 wikitext ----------
     -- 声优字段
    -- MediaWiki 拿到 Lua 模块返回的字符串后,会对其中的 wikitext 语法
    -- (包括 {{模板}}、[[链接]] 等)做完整的二次解析,
    -- 因此直接把原始参数值嵌入 HTML 字符串返回,
    -- MediaWiki 渲染时会正确展开 {{ruby}} 等模板,不需要 Lua 自己 preprocess。
    -- 注意:这要求这些字段的值不含恶意 HTML,wiki 本身的权限体系负责这一点。
 
    local function raw(key)
        return cleanParam(args[key])  -- 直接返回原始 wikitext,不展开
    end
 
    -- 声优字段:纯文字加链接,不太可能含 ruby,但保险起见也走 raw
     local function fmtVoice()
     local function fmtVoice()
         local v = cleanParam(args['多位声优'] or args['声优'])
         local v = cleanParam(args['多位声优'] or args['声优'])
         if not v then return nil end
         if not v then return nil end
        -- 若已含链接语法则原样返回,否则套链接
         if v:find('%[%[') then return v end
         if v:find('%[%[') then return v end
         return '[[' .. v .. ']]'
         return '[[' .. v .. ']]'
    end
    -- 分类:需要展开的字段(可能含模板)
    local function raw(key)
        return expandField(frame, key)
    end
    -- 分类:纯文本字段(不含用户输入模板)
    local function rawPlain(key)
        return cleanParam(args[key])
     end
     end


     ---------- 拼 wikitext + HTML 混合字符串 ----------
     ---------- 拼 wikitext + HTML 混合字符串 ----------
    -- Lua 模块的返回值会被 MediaWiki 当作 wikitext 再解析一次,
    -- 所以可以在 HTML 属性/标签里直接夹杂 {{ruby}} 这样的 wikitext,
    -- MediaWiki 会先展开模板,再把结果嵌入 DOM。
     local parts = {}
     local parts = {}
     local function push(s) parts[#parts + 1] = s end
     local function push(s) parts[#parts + 1] = s end

2026年5月13日 (三) 09:53的版本

此模块的文档可以在模块:GFInfobox/doc创建

local p = {}

local function cleanParam(s)
    if not s then return nil end
    s = s:gsub('^[%s\n\r\t]+', ''):gsub('[%s\n\r\t]+$', '')
    if s == '' then return nil end
    s = s:gsub('^%s*<p[^>]*>', ''):gsub('</p>%s*$', '')
    return s
end

-- 安全展开不含用户输入的模板(如颜色模板)
local function expandSafe(frame, s)
    if not s then return nil end
    return frame:preprocess(s)
end

-- 展开可能含用户输入模板的字段(如 ruby、黑幕等)
local function expandField(frame, key)
    local text = cleanParam(frame:getParent().args[key])
    if not text then return nil end
    return frame:preprocess(text)
end

function p.formatRarity(rarity)
    if not rarity then return nil end
    local colors = {
        [2] = '#777',
        [3] = '#33566f',
        [4] = '#7b813f',
        [5] = '#a7753b',
        [6] = '#ad4229',
    }
    local num = tonumber(rarity)
        or (rarity:find('★') and select(2, rarity:gsub('★', '★')))
    if num and colors[math.floor(num)] then
        return string.format(
            '<span style="color:%s">%s</span>',
            colors[math.floor(num)],
            string.rep('★', math.floor(num))
        ), false
    end
    return rarity, false
end

function p.main(frame)
    local parentFrame = frame:getParent()
    local args = parentFrame.args

    local name = cleanParam(args['标题'])
        or cleanParam(args['名字'])
        or mw.title.getCurrentTitle().subpageText

    -- 颜色字段:由 Lua 构造模板调用字符串,用 preprocess 展开,安全
    local function fmtColor(rawColor, cType)
        rawColor = cleanParam(rawColor)
        if not rawColor then return nil end
        return expandSafe(frame, '{{' .. cType .. '_color|' .. rawColor .. '}}')
    end

    local hairColor = fmtColor(args['多种发色'] or args['发色'], 'Hair')
    local eyeColor  = fmtColor(args['多种瞳色'] or args['瞳色'], 'Eye')
    local rarity    = p.formatRarity(cleanParam(args['稀有度']))

    -- 声优字段
    local function fmtVoice()
        local v = cleanParam(args['多位声优'] or args['声优'])
        if not v then return nil end
        if v:find('%[%[') then return v end
        return '[[' .. v .. ']]'
    end

    -- 分类:需要展开的字段(可能含模板)
    local function raw(key)
        return expandField(frame, key)
    end

    -- 分类:纯文本字段(不含用户输入模板)
    local function rawPlain(key)
        return cleanParam(args[key])
    end

    ---------- 拼 wikitext + HTML 混合字符串 ----------
    local parts = {}
    local function push(s) parts[#parts + 1] = s end

    push('<div class="gf-infobox">')
    push('<div class="gf-title">' .. name .. '</div>')

    local image = cleanParam(args['image'])
    push('<div class="gf-image-container">')
    if image then
        push('[[File:' .. image .. '|280px]]')
        local caption = raw('图片说明')
        if caption then
            push('<div style="font-size:0.9em;">' .. caption .. '</div>')
        end
    end
    push('</div>')

    push('<div class="gf-section">基础资料</div>')
    push('<div class="gf-table">')

    local fields = {
        { '本名',   raw('本名') },
        { '别名',   raw('别名') },
        { '发色',   hairColor },
        { '瞳色',   eyeColor },
        { '声优',   fmtVoice() },
        { '萌点',   raw('萌点') },
        { '类型',   raw('类型') },
        { '稀有度', rarity },
        { '团体',   raw('所属团体') },
        { '状态',   raw('个人状态') },
    }

    for _, field in ipairs(fields) do
        local label, value = field[1], field[2]
        if value then
            push('<div class="gf-row">')
            push('<div class="gf-label">' .. label .. '</div>')
            push('<div class="gf-value">' .. value .. '</div>')
            push('</div>')
        end
    end

    push('</div>') -- gf-table

    local related = raw('相关人士')
    if related then
        push('<div class="gf-section">亲属或相关人</div>')
        push('<div class="gf-related">' .. related .. '</div>')
    end

    push('</div>') -- gf-infobox

    return table.concat(parts, '\n')
end

return p