置顶公告:【置顶】关于临时开启评论区所有功能的公告(2022.10.22) | 【置顶】关于本站Widget恢复使用的公告
  • 你好~!欢迎来到萌娘百科镜像站!如需查看或编辑,请联系本站管理员注册账号。
  • 本镜像站和其他萌娘百科的镜像站无关,请注意分别。

Module:Sandbox/杨哲思/navbox

贴贴♀百科,万娘皆可贴的百科全书!转载请标注来源页面的网页链接,并声明引自贴贴百科。内容不可商用。
跳到导航 跳到搜索
Template-info.svg 模块文档  [创建] [刷新]



local navbar = require 'module:navbar'._navbar

local hcreate = mw.html.create

local luaon = require 'module:Luaon'

local function index(t,paras)
    local result = t
    for i, k in ipairs(paras) do
        if not result then return nil end
        result = result[k]
    end
    return result
end

local function newindex(t,value,paras)
    local num = #paras
    local current = t
    for i,k in ipairs(paras) do
        if i == num then
            if type(current[k])~='table' then
                current[k] = value
            end
            return type(value)=='table' and current[k] or t
        else
            if type(current[k]) ~= 'table' then
                current[k] = {}
            end
            current = current[k]
        end
    end
end




local function getkeys(key,...)
    local t = {}
    for each in key:gmatch('[^%-]') do
        local num = tonumber(each)
        if not num then return nil end
        table.insert(t,num)
        table.insert(t,'list')
        table.insert(t,'content')
    end
    
    t[#t], t[#t-1] = nil -- Anyway no nil is ok
    
    for _,append in ipairs {...} do
        table.insert(t,append)
    end
    
    
    return t
end




local zes = {}
local navbox = {}

function zes.new(paras)
    local obj = {}
    local paras = paras or {}
    
    obj.args = paras.args or {}
    obj.data = paras.data or {}
    obj.level = paras.level or 0
    obj.isChild = obj.level > 0
    obj.root = paras.root
    obj.rootself = paras.rootself or obj
    return setmetatable(obj,{__index = navbox})
end

local suffixes = {
    content = true,
    style = true,
    class = true
}



function navbox:checkItem(k, v, data)
    
    data = data or self.data
    
    
    
    if type(k) ~= 'string' then return end
    
    if k == 'name' then
        data.name = v
        return
    end
    
    
    local suffix = k:match('^list(%l+[%l%d%-%.]*)')
    if suffix and not suffixes[suffix] then
        self:checkItem(suffix,v,newindex(data,{},'list'))
        return
    end
    
    for _, prefix in ipairs {
        'list','group','odd','even','title','body','single'
    } do
        if k:find '%d' then break end
        local suffix = k:match('^'..prefix..'(%l*)$')
        if suffix then
            if suffix == '' then suffix = 'content' end
            newindex(data,v,{prefix,suffix})
            return
        end
    end
    
    
    local prefix, key, suffix = k:match '^([a-z]+)([0-9%.%-]+)([a-z]*)$'
	--2021.6.14:floatable
	-- 对于group和list,以及其他的类型,采取不同的数据加工方式
	local isCell = (prefix=='group' or prefix=='list' or prefix=='single')
    if suffix=='' then suffix='content' end
    
    
	-- 这里的prefix可以是group,list
	-- 这里的suffix可以是空白、class或style
	-- 这里的key可以是1、2、3或1-2、1-4这样的数字或多重数字。
    if not (suffix and suffixes[suffix]) then
        key, suffix = k:match '^list([%d%-%.]+)(%l+[%l%d%-%.]*)'
    end
    
    
	if not key then return end
	
    
    if not getkeys(key) then return end
    
    local keys1,keys2,keys3 =
    getkeys(key,'list','content'),
    getkeys(key,prefix,suffix),
    getkeys(key,'list','content',prefix,suffix)
    
	
    if not prefix then
        self:checkItem(suffix,v,newindex(data,{},keys1))
        return
    elseif isCell then
        newindex(data,v,keys2)
        return
    else 
        newindex(data,v,keys3)
        return
    end
    
    
end


function navbox:process()
    local args = self.args
    
    for k,v in pairs(args) do
        local key = k:match '^data(%d+)$'
        if key then
            local keys = getkeys(key,'list','content')
            if not keys then break end
            local data = luaon.decode(v)
            
            newindex(self.data,data,keys)
        end
    end
    
    
    
    
    for k,v in pairs(args) do
        v = mw.text.trim(v)
        if v ~= '' then 
            self:checkItem(k,v)
        end
    end
    
    return self
end 


function navbox:renderTitle(tArgs)   
    local navbar = tArgs.navbar or ''
    local content = tArgs.content
    if not content then return end
    
    local style = tArgs.style
    local class = tArgs.class
    
    
    
    local root = self.root
    
    local row = root:tag 'tr':addClass('newstyle_navbox-row')
    
    row
        :tag ('th'):addClass 'newstyle_navbox-title'
            :attr('colspan',2)
            :wikitext(navbar)
            :wikitext(content)
            :addClass(class)
            :cssText(style)
    
    
end

function navbox:renderSingle(sArgs)
    local content = sArgs.content
    if not content then return end
    
    local rootdata = self.rootself.data
    
    local root = self.root
    
    local row = root:tag 'tr':addClass 'newstyle_navbox-row'
    
    row
        :tag 'td' :addClass 'newstyle_navbox-single'
            :attr('colspan',2)
            :wikitext(content)
            :addClass(index(rootdata,{'single','class'}))
            :cssText(index(rootdata,{'single','style'}))
            :addClass(sArgs.class)
            :cssText(sArgs.style)
       
    
end

function navbox:renderRow(gArgs,lArgs)
    
    if not lArgs.content then return end
    
    local rootself = self.rootself
    local rootdata = rootself.data
    local root = self.root
    
    local row = root:tag 'tr':addClass('newstyle_navbox-row')
    
    local group
    
    if gArgs.content then
        group = row:tag 'th' :addClass 'newstyle_navbox-group'
            :wikitext(gArgs.content)
            :addClass(index(rootdata,{'group','class'}))
            :cssText(index(rootdata,{'group','style'}))
        
    end
    
    local list = row:tag 'td':addClass 'newstyle_navbox-list'
    local subroot
    if type(lArgs.content)=='table' then
        list:addClass 'newstyle_navbox-list-with-subgroup'
        subroot = list:tag 'table' :addClass 'newstyle_navbox'
        
        local subObj = zes.new {
            root=subroot,
            level=self.level+1,
            data=lArgs.content,
            rootself=self
        }
        subObj:render()
    elseif type(lArgs.content)=='string' then
        list:wikitext(lArgs.content)
            :addClass(index(rootdata,{'list','class'}))
            :cssText(index(rootdata,{'list','style'}))
        
    end
    
    if not group then
        list:attr('colspan',2)
            :addClass 'newstyle_navbox-list-without-group'
    else
        group:addClass(gArgs.class)
            :cssText(gArgs.style)
    end
    
    if rootself.isEven and not subroot then
        list:addClass 'newstyle_navbox-list-even'
            :addClass(index(rootdata,{'even','class'}))
            :cssText(index(rootdata,{'even','style'}))
        
    elseif not subroot then
        list:addClass 'newstyle_navbox-list-odd'
            :addClass(index(rootdata,{'odd','class'}))
            :cssText(index(rootdata,{'odd','style'}))
        
    end
    
    if not subroot then
        rootself.isEven = not isEven
    end
    
    list:addClass(lArgs.class)
        :cssText(lArgs.style)
    
end

function navbox:render()
    
    
    self.root = self.root or hcreate 'table':addClass 'newstyle_navbox hlist'
    
    local root = self.root
    
    if self.level>0 then
        root:addClass 'newstyle_navbox-subgroup'
    end
    
    root:addClass('newstyle_navbox-level-'..self.level)
    
    
    local data = self.data
    
    root:addClass(index(data,{'body','class'}))
    	:cssText(index(data,{'body','style'}))
    
    local navbarEle
    
    if data.name then
        navbarEle = navbar {
            title=data.name,
            mini=1
        }
    end
    
    self:renderTitle {
        content = index(data,{'title','content'}),
        style = index(data,{'title','style'}),
        class = index(data,{'title','class'}),
        navbar = navbarEle
    }
    
    
    local keys = {}
    for k, v in pairs(data) do
        if type(k)=='number' then
            table.insert(keys,k)
        end
    end
    
    table.sort(keys)
    
    for i,k in ipairs(keys) do
        local v = data[k]
        
        if index(v,{'single','content'}) then
            self:renderSingle(v.single)
        else
            self:renderRow((v.group or {}),v.list)
        end
    end
    
    return root
end


function zes._navbox(args)
    return zes.new {args=args}:process():render()
end

function zes.luaon(frame)
    local obj = zes.new {args=frame.args}
    obj:process()
    return luaon.encode(obj.data)
end

function zes.direct(frame) return zes._navbox(frame.args) end

function zes.navbox(frame) return zes._navbox(frame:getParent().args) end

return zes