2023年政策修订增补工作正在进行中,欢迎参与!
Module:Sandbox/杨哲思/navbox
跳转到导航
跳转到搜索
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