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

模块:GFInfobox:修订间差异

来自OGAS数据中枢
弃权者留言 | 贡献
无编辑摘要
弃权者留言 | 贡献
无编辑摘要
 
(未显示同一用户的12个中间版本)
第1行: 第1行:
local p = {}
local p = {}


function p.main(frame)
local function cleanParam(s)
     local args = frame.args
    if not s then return nil end
     local html = mw.html.create('div')
    s = s:gsub('^[%s\n\r\t]+', ''):gsub('[%s\n\r\t]+$', '')
        :addClass('moe-infobox gf-infobox')
     if s == '' then return nil end
     s = s:gsub('^%s*<p[^>]*>', ''):gsub('</p>%s*$', '')
    return s
end
 
-- 递归展开模板和wikitext
local function expandWikitext(frame, text)
    if not text then return nil end
      
      
     -- 标题
     -- 先展开所有模板
     html:tag('div')
     local expanded = text
        :addClass('gf-title')
        :wikitext(args['标题'] or args['名字'] or mw.title.getCurrentTitle().subpageText)
      
      
     -- 图片
     -- 处理 {{ruby|文字|注音}} 模板
    local image = args['image']
     expanded = expanded:gsub('{{ruby|([^|]+)|([^}]+)}}', function(base, ruby)
     if image and image ~= '' then
        return frame:expandTemplate{ title = 'ruby', args = { base, ruby } }
        local imgContainer = html:tag('div')
     end)
            :addClass('gf-image-container')
        imgContainer:wikitext(string.format('[[File:%s|280px|class=infobox-image]]', image))
        if args['图片说明'] and args['图片说明'] ~= '' then
            imgContainer:wikitext('<br/>')
            imgContainer:wikitext(args['图片说明'])
        end
    else
        html:tag('div')
            :addClass('gf-image-container')
            :wikitext('啊嘞?!<br/>怎么回事<br/>这个妹子怎么没有头的样子……')
     end
      
      
     -- 基础资料
     -- 处理 {{黑幕|文字}} 模板
     html:tag('div')
     expanded = expanded:gsub('{{黑幕|([^}]+)}}', function(content)
         :addClass('gf-section')
         return frame:expandTemplate{ title = '黑幕', args = { content } }
        :wikitext('基础资料')
    end)
      
      
     -- 信息字段列表
     -- 处理 {{lang|语言|文字}} 模板(如果有)
    local fields = {
    expanded = expanded:gsub('{{lang|([^|]+)|([^}]+)}}', function(lang, text)
        {'本名', args['本名']},
         return frame:expandTemplate{ title = 'lang', args = { lang, text } }
        {'别名', args['别名']},
     end)
        {'发色', formatHairColor(args, frame)},
        {'瞳色', formatEyeColor(args, frame)},
        {'声优', formatVoiceActor(args)},
        {'萌点', args['萌点']},
        {'类型', formatWeaponType(args['类型'])},
        {'稀有度', formatRarity(args['稀有度'])},
        {'原产国', args['原产国']},
        {'研发者', args['研发者']},
         {'研发商', args['研发商']},
        {'研发日期', args['研发日期']},
        {'生产商', args['生产商']},
        {'生产日期', args['生产日期']},
        {'服役期间', args['服役期间']},
        {'出身地区', args['出身地区']},
        {'活动范围', args['活动范围']},
        {'所属团体', args['所属团体']},
        {'个人状态', args['个人状态']}
     }
      
      
     for _, field in ipairs(fields) do
     -- 如果有其他常用模板,可以继续添加
        local label, value = field[1], field[2]
        if value and value ~= '' then
            local row = html:tag('div'):addClass('gf-row')
            row:tag('div')
                :addClass('gf-label')
                :wikitext(label)
            row:tag('div')
                :addClass('gf-value')
                :wikitext(value)
        end
    end
      
      
    -- 亲属或相关人
     return expanded
    local related = args['相关人士']
    if related and related ~= '' then
        html:tag('div')
            :addClass('gf-section')
            :wikitext('亲属或相关人')
        html:tag('div')
            :addClass('gf-related')
            :wikitext(related)
    end
   
    -- 返回时去除首尾空白
     return tostring(html):gsub('^%s+', ''):gsub('%s+$', '')
end
end


-- 格式化发色
-- 安全展开不含用户输入的模板(如颜色模板)
function formatHairColor(args, frame)
local function expandSafe(frame, s)
    local multiColor = args['多种发色']
     if not s then return nil end
     if multiColor and multiColor ~= '' then
     return frame:preprocess(s)
        return multiColor
    end
      
    local hairColor = args['发色']
    if hairColor and hairColor ~= '' then
        return frame:preprocess('{{Hair_color|' .. hairColor .. '}}')
    end
   
    return nil
end
end


-- 格式化瞳色
function p.formatRarity(rarity)
function formatEyeColor(args, frame)
    if not rarity then return nil end
     local multiColor = args['多种瞳色']
     local colors = {
    if multiColor and multiColor ~= '' then
        [2] = '#777',
         return multiColor
        [3] = '#33566f',
    end
        [4] = '#7b813f',
      
         [5] = '#a7753b',
     local eyeColor = args['瞳色']
        [6] = '#ad4229',
     if eyeColor and eyeColor ~= '' then
     }
         return frame:preprocess('{{Eye_color|' .. eyeColor .. '}}')
     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
     end
   
     return rarity, false
     return nil
end
end


-- 格式化声优
function p.main(frame)
function formatVoiceActor(args)
    local parentFrame = frame:getParent()
     local multiVA = args['多位声优']
    local args = parentFrame.args
     if multiVA and multiVA ~= '' then
 
         return multiVA
     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
     end
      
 
     local voiceActor = args['声优']
    local hairColor = fmtColor(args['多种发色'] or args['发色'], 'Hair')
    if voiceActor and voiceActor ~= '' then
    local eyeColor  = fmtColor(args['多种瞳色'] or args['瞳色'], 'Eye')
         return string.format('[[%s]]', voiceActor)
    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
     end
   
    return nil
end


-- 格式化武器类型
    -- 获取字段值并展开其中的模板
function formatWeaponType(weaponType)
    local function getField(key)
    local weaponTypes = {
        local raw = cleanParam(args[key])
        ['手枪'] = '手枪',
         if not raw then return nil end
        ['冲锋枪'] = '冲锋枪',
         return expandWikitext(frame, raw)
        ['步枪'] = '步枪',
        ['突击步枪'] = '突击步枪',
         ['机枪'] = '机枪',
        ['霰弹枪'] = '霰弹枪'
    }
   
    if weaponType and weaponTypes[weaponType] then
         return weaponTypes[weaponType]
     end
     end
   
    return weaponType
end


-- 格式化稀有度
    ---------- 拼 wikitext + HTML 混合字符串 ----------
function formatRarity(rarity)
    local parts = {}
     if not rarity or rarity == '' then
    local function push(s) parts[#parts + 1] = s end
         return nil
 
    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 = getField('图片说明')
        if caption then
            push('<div style="font-size:0.9em;">' .. caption .. '</div>')
         end
     end
     end
      
     push('</div>')
     local rarityColors = {
 
         [2] = '#777777',
    push('<div class="gf-section">基础资料</div>')
         [3] = '#33566f',
    push('<div class="gf-table">')
         [4] = '#7b813f',  
 
         [5] = '#a7753b',
     local fields = {
         [6] = '#ad4229'
         { '本名',  getField('本名') },
        { '别名',  getField('别名') },
        { '发色',  hairColor },
        { '瞳色',  eyeColor },
        { '声优',  fmtVoice() },
        { '萌点',  getField('萌点') },
         { '类型',  getField('类型') },
         { '稀有度', rarity },
         { '团体',  getField('所属团体') },
         { '状态',  getField('个人状态') },
     }
     }
   
 
     -- 处理数字
     for _, field in ipairs(fields) do
    local num = tonumber(rarity)
         local label, value = field[1], field[2]
    if num then
         if value then
         local color = rarityColors[num]
             push('<div class="gf-row">')
         if color then
            push('<div class="gf-label">' .. label .. '</div>')
             return string.format('<span style="color:%s">%s</span>', color, string.rep('', num))
            push('<div class="gf-value">' .. value .. '</div>')
            push('</div>')
         end
         end
        return rarity
     end
     end
   
 
     -- 处理星星
     push('</div>') -- gf-table
     local starCount = 0
 
    rarity:gsub('', function() starCount = starCount + 1 end)
     local related = getField('相关人士')
     if starCount > 0 then
     if related then
         local color = rarityColors[starCount]
         push('<div class="gf-section">亲属或相关人</div>')
         if color then
         push('<div class="gf-related">' .. related .. '</div>')
            return string.format('<span style="color:%s">%s</span>', color, rarity)
        end
        return rarity
     end
     end
   
 
     -- 处理箭头
     push('</div>') -- gf-infobox
     return rarity:gsub('%s*→%s*', ' → '):gsub('%s*->%s*', ' ')
 
     return table.concat(parts, '\n')
end
end


return p
return p

2026年5月13日 (三) 09:56的最新版本

此模块的文档可以在模块: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

-- 递归展开模板和wikitext
local function expandWikitext(frame, text)
    if not text then return nil end
    
    -- 先展开所有模板
    local expanded = text
    
    -- 处理 {{ruby|文字|注音}} 模板
    expanded = expanded:gsub('{{ruby|([^|]+)|([^}]+)}}', function(base, ruby)
        return frame:expandTemplate{ title = 'ruby', args = { base, ruby } }
    end)
    
    -- 处理 {{黑幕|文字}} 模板
    expanded = expanded:gsub('{{黑幕|([^}]+)}}', function(content)
        return frame:expandTemplate{ title = '黑幕', args = { content } }
    end)
    
    -- 处理 {{lang|语言|文字}} 模板(如果有)
    expanded = expanded:gsub('{{lang|([^|]+)|([^}]+)}}', function(lang, text)
        return frame:expandTemplate{ title = 'lang', args = { lang, text } }
    end)
    
    -- 如果有其他常用模板,可以继续添加
    
    return expanded
end

-- 安全展开不含用户输入的模板(如颜色模板)
local function expandSafe(frame, s)
    if not s then return nil end
    return frame:preprocess(s)
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 getField(key)
        local raw = cleanParam(args[key])
        if not raw then return nil end
        return expandWikitext(frame, raw)
    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 = getField('图片说明')
        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 = {
        { '本名',   getField('本名') },
        { '别名',   getField('别名') },
        { '发色',   hairColor },
        { '瞳色',   eyeColor },
        { '声优',   fmtVoice() },
        { '萌点',   getField('萌点') },
        { '类型',   getField('类型') },
        { '稀有度', rarity },
        { '团体',   getField('所属团体') },
        { '状态',   getField('个人状态') },
    }

    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 = getField('相关人士')
    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