跳转到内容

模块:NavboxV2/sandbox

本页使用了标题或全文手工转换
维基百科,自由的百科全书
文档图示 模块文档[查看] [编辑] [历史] [清除缓存]

这是{{NavboxV2}}的Lua实现代码。

简介

[编辑]

合并了{{Navbox}}相关的一系列模板。融合了{{Navbox}}的行式、{{Navbox subgroup}}的子代模块包含、{{Navbox with columns}}的列式,{{Navbox with collapsible groups}})的折叠行式。

改写自模块:Navbox(oldid=42280913)。

设计用途

[编辑]

Category:引用模板后大小超过限制的页面中,有相当一部分页面是由于{{Navbox}}模板超载导致。

  • 根据WP:模板限制中“嵌套展开”的说法,相同页面的多次嵌套调用是会被分次统计的(例如:页面A嵌入页面B,页面B嵌入页面C,页面C相对页面A统计到的展开字节数是被计算了2次)。而现在Navbox的子代块、列式,折叠行式的实现都是基于Navbox行式的模板调用或类似样式结构迭代,这样就符合内部多次调用Navbox的条件,页面很容易会超过模版展开后大小的限制。
  • 其次,实际上Lua的运行限制条件相当宽裕,50MB的内存限制,10秒的运行时限制,很多页面实际使用只在十分之一左右或以下,可以被大量压榨性能。

所以将Navbox所有的实现全部以Lua实现,希望能腾出解释器运行量到Lua运行量,降低解析器触发展开后大小限制的可能。

效果

[编辑]
在对于包含一层子Navbox的情况,展开后大小下降最多有50~60%左右。

对比例子

[编辑]
项目 {{Navbox}}系列,参考基准 本模板
Template:哈利波特 Special:固定链接/60036259 User:Cwek/工作室2/Navbox/T:哈利波特
Template:广州 Special:固定链接/60035252 User:Cwek/工作室2/Navbox/T:广州
Template:广州地铁车站 Special:固定链接/59586101 User:Cwek/工作室2/Navbox/T:广州地铁
Template:粤港澳大湾区公共交通 Special:固定链接/59654656 User:Cwek/工作室2/Navbox/T:粤港澳大湾区公共交通
Template:JR东日本的车辆 Special:固定链接/61531803 Special:固定链接/62385808
Template:中华人民共和国广播电视付费频道 Special:固定链接/77500465 Special:固定链接/77504799

参数

[编辑]

与{{Navbox}}系列模板基本兼容。但新增部分参数填入:

  • type:Navbox的类型,对应值为vertical(对应{{Navbox}})、horizontal(对应{{Navbox with columns}})、vertical_collapsible(对应{{Navbox with collapsible groups}}),默认值为vertical
  • border:Navbox的隐藏参数,用于控制Navbox的边框机制,来使子Navbox能被嵌入到父Navbox的值字段(例如listcol等)中,实际对应{{Navbox subgroup}}或{{Navbox|child}}的实现机制。对应值为childsubgroup任一个。
在本模板添加子Navbox层时,必须传入这两个参数,这是本模板区分是否存在子Navbox层的依赖。本模板首层Navbox层无需添加border,按需添加type
  • removeGroupPadding:用于区别{{Navbox|child}}和{{Navbox subgroup}},后者在Groupn字段的单元格增加一组padding的配置,适用于子Navbox层。任意值,存在则可,为移除该padding配置(对应{{Navbox|child}})。

方便复制的代码:

| <list/content>-type = vertical | horizontal | vertical_collapsible
| <list/content>-border = child| subgroup 
| <list/content>-removeGroupPadding = 1

自{{Navbox}}系列模板转换

[编辑]

将原有嵌入{{Navbox}}系列模板的值字段listn(其他类同)改为listn-,并作为相应嵌套子Navbox模板的参数的前缀来加入,使这些模板嵌套转换为扁平化的一层模板参数。

例子
{{Navbox}}系列 本模板
{{Navbox
|name = Navbox/doc
|state = expanded
|image = {{{image}}}
|imageleft = {{{imageleft}}}
|title = {{{title}}}
|above = {{{above}}}
|group1 = {{{group1}}}
|list1 = {{Navbox subgroup
 | title = {{{list1-title}}}
 | above = {{{list1-above}}}
 | below = {{{list1-below}}}
 | imageleft = {{{list1-imageleft}}}
 | image = {{{list1-image}}}
 | group1 = {{{list1-group1}}}
 | list1  = {{{list1-list1}}}
 | group2 = {{{list1-group2}}}
 | list2  = {{{list1-list2}}}
}}
|group2 = {{{group2}}}
|list2 = {{Navbox subgroup
| group1 = {{{list2-group1}}}
| list1  = {{{list2-list1}}}
| group2 = {{{list2-group2}}}
| list2  = {{{list2-list2}}}
}}
|below = {{{below}}}
}}
{{NavboxV2
|name = Navbox/doc
|state = expanded
|image = {{{image}}}
|imageleft = {{{imageleft}}}
|title = {{{title}}}
|above = {{{above}}}
<!--  list1 -->
|group1 = {{{group1}}}
<!-- list1-sub-->
|list1-type =vertical <!--作为list1的子Navbox层,全部相应参数加上对应前缀“list1-”,下同,如此类推 -->
|list1-border=child
|list1-title = {{{list1-title}}}
|list1-above = {{{list1-above}}}
|list1-below = {{{list1-below}}}
|list1-imageleft = {{{list1-imageleft}}}
|list1-image = {{{list1-image}}}
|list1-group1 = {{{list1-group1}}}
|list1-list1  = {{{list1-list1}}}
|list1-group2 = {{{list1-group2}}}
|list1-list2  = {{{list1-list2}}}
<!--  list2 -->
|group2 = {{{group2}}}
<!-- list2-sub-->
|list2-type =vertical <!--作为list2的子Navbox层,全部相应参数加上对应前缀“list2-”,下同,如此类推 -->
|list2-border=child
|list2-group1 = {{{list2-group1}}}
|list2-list1  = {{{list2-list1}}}
|list2-group2 = {{{list2-group2}}}
|list2-list2  = {{{list2-list2}}}
<!--end-->
|below = {{{below}}}
}}

转换注意

[编辑]

由于{{Navbox}}系列的实现较为复杂和涉及自我嵌套,本模板的实现也为此做了对应兼容性调整,可能会出现一些参数被过度透传(可能在样式控制部分,原因是原有设计通过控制参数传入来隔离,而本设计为了使参数扁平化,导致部分这些参数无法隔离)。而且模板参数非常依赖命名规律,在转换替换前,请进行testcase检查,确认转换后能与原来的样式、功能基本一致,才应用转换。如果出现问题,请保留案例并联系本模板维护编辑协助处理,或者放弃

虽然可以在值字段(例如listcol等)重新嵌入{{Navbox}}系列模板,但这和原有做法一样,失去了本模板降低解析器限制的作用,不建议这样做。

--
-- This module implements {{NavboxV2}}
--
local p = {}

local NavboxContext = require('Module:NavboxV2/NavboxContext')
local getArgs -- lazily initialized
local DEBUG = false
--p.NavboxContext = NavboxContext

-- 全局性参数锚
local args

-- 常量定义 (Constant Define)
local Limit = {
    vertical = 35,
    horizontal = {col = 20, list = 10}, --原Navbox with columns为6个list,放宽至10
    vertical_collapsible = 20,
    child = 10
}

-- 模板类型名
local NavType = {
    V = "vertical" -- 垂直,list
    ,
    H = "horizontal" -- 水平,col
    ,
    VC = "vertical_collapsible" -- 折叠垂直
}

-- 模板名,用于参数获得的限定
local MainTemplateName = 'Template:NavboxV2'

-- Navbar存在标记
local haveNavBarMarker = false

-- 部分判断样式的参数
local listsCheck = {
	plainlist_t = {
		patterns = {
			'^plainlist$',
			'%splainlist$',
			'^plainlist%s',
			'%splainlist%s'
		},
		found = false,
		styles = 'Plainlist/styles.css'
	},
	hlist_t = {
		patterns = {
			'^hlist$',
			'%shlist$',
			'^hlist%s',
			'%shlist%s'
		},
		found = false,
		styles = 'Hlist/styles.css'
	}
}

---------------------------------------------------------------
--
-- 工具箱方法 (Util Function)
--

local addNewline = function(s)
    if mw.ustring.match(s,'^[*:;#]') or mw.ustring.match(s,'^{|') then
        return '\n' .. s .. '\n'
    else
        return s
    end
end

---数组除重
local removeDump = function(arr)
    local _t1, _t2 = {}, {}
    for _, val in pairs(arr) do _t1[val] = true end
    for key, _ in pairs(_t1) do table.insert(_t2, key) end
    return _t2
end

function tableToString(_table)
    local outputs = {}
    if _table == nil then
        table.insert(outputs, '<nil>')
    elseif type(_table) == 'table' then
        for k, v in pairs(_table) do
            local output
            if type(v) == 'table' then
                output = tableToString(v)
            else
                output = tostring(v)
            end
            table.insert(outputs, tostring(k) .. "=" .. output)
        end
    end
    return '{' .. table.concat(outputs, ",") .. '}'
end

function debugLog(...)
    if DEBUG then
        if #arg == 1 then
            mw.log(tostring(arg[1]))
            --mw.log("--------------------")
        else
            for k, v in pairs(arg) do
                local pass = false or tostring(k) == 'n'
                if not pass then
                    local _v = v
                    if type(v) == 'table' then
                        _v = tableToString(v)
                    end
                    mw.log(tostring(_v))
                end
            end
        end
    end
end

---------------------------------------------------------------
--
-- 功能性方法 (Functional Function)
--

---获得有效的类型
local getValidType = function(input, defVal)
    return (NavType.V == input or NavType.H == input or NavType.VC == input) and input or defVal
end

---检查border判断是不是子Navbox
local borderIsChild = function(border)
    return (border == 'subgroup' or border == 'child')
end

-- 前缀生成
local makePrefix = function(oldPrefix, thisLevel)
	return oldPrefix == "" and thisLevel or (oldPrefix .. '-' .. thisLevel)
end

---获得参数
local getArg = function(_prefix, _argKey, defVal, context, _contextKey)
    local contextKey = _contextKey or _argKey
    if context and contextKey and context[contextKey] then
        -- debugLog('getArg By Context',contextKey)
        return context[contextKey]
    else
        local prefix = _prefix ~= nil and _prefix or ""
        local key = (_argKey == nil and _prefix ~= nil) and _prefix or _argKey
        local argsKey = makePrefix(prefix, key)
        -- debugLog('getArg By InputArg',argsKey)
        return args[argsKey] or defVal
    end
end

---子Navbox参数组判断
local checkHaveChild = function(prefix, valuekey)
    return (
    	getValidType(getArg(prefix, valuekey .. '-type'), nil) and
    	borderIsChild(getArg(prefix, valuekey .. '-border'))
	) == true
end

---获得listnum
local getListnum = function(prefix, limit, contentEqList)
    debugLog("getListnum", {['prefix'] = prefix, ['limit'] = limit})
    
    prefix = mw.ustring.gsub(prefix,'(-)', '%%-')
    local middle = (prefix == "" and "" or "%-")
    local listKeyMatch , contentKeyMatch=
	        '^' .. prefix .. middle .. 'list(%d+)',
	        '^' .. prefix .. middle .. 'content(%d+)' 
    local 
    	listKeyMatchEnd, listKeyMatchSub, 
		contentKeyMatchEnd, contentKeyMatchSub =
			listKeyMatch .. '$' , listKeyMatch .. '%-' ,
			contentKeyMatch .. '$' , contentKeyMatch .. '%-'
	local listnums = {}
	
    for k, v in pairs(args) do
        k = '' .. k
        -- debugLog("getListnum,k=",k)
        
        local listnum =
        (
            mw.ustring.match(k, listKeyMatchEnd) or
            mw.ustring.match(k, listKeyMatchSub)
        ) or
        (
            contentEqList and ( -- VerticalCollapsibleTable 的 Content适配
            mw.ustring.match(k, contentKeyMatchEnd) or
            mw.ustring.match(k, contentKeyMatchSub)
            ) or nil
        )
        if listnum and tonumber(listnum) <= limit then
    		listnum = tonumber(listnum)
            table.insert(listnums, listnum)
        end
    end
    
    listnums = removeDump(listnums)
    table.sort(listnums)
    
    debugLog('getListnum End',{['listnums']=tableToString(listnums)})
    return listnums
end

---参数检查和摇匀
function p.shakeArgs(prefix, level, _type)
    local _
    local list_limit = 0
    _type = _type or getArg(prefix, "type")

    _ = getArg(prefix, "title")
    _ = getArg(prefix, "above")

    if _type == NavType.H then
        list_limit = Limit.horizontal.list

        for i = 1, Limit.horizontal.col do
            _ = getArg(prefix, "col" .. tostring(i) .. "header")
            --[[if checkHaveChild(prefix, "col" .. tostring(i) .. "header") then
                p.shakeArgs(makePrefix(prefix,"col" .. tostring(i) .. "header" ), level + 1)
            end ]]

            _ = getArg(prefix, "col" .. tostring(i))
            if checkHaveChild(prefix, "col" .. tostring(i)) then
                p.shakeArgs(makePrefix(prefix, "col" .. tostring(i)), level + 1)
            end

            _ = getArg(prefix, "col" .. tostring(i) .. "footer")
            --[[if checkHaveChild(prefix, "col" .. tostring(i) .. "footer") then
                p.shakeArgs(makePrefix(prefix, "col" .. tostring(i) .."footer" ), level + 1)
            end ]]
        end
    elseif _type == NavType.V then
        list_limit = Limit.vertical
    elseif _type == NavType.VC then
        list_limit = Limit.vertical_collapsible
    end
    for i = 1, list_limit do
        _ = getArg(prefix, "group" .. tostring(i))
        _ = getArg(prefix, "list" .. tostring(i))

        if checkHaveChild(prefix, "list" .. tostring(i)) then
            p.shakeArgs(makePrefix(prefix, "list" .. tostring(i)), level + 1)
        end
        if checkHaveChild(prefix, "content" .. tostring(i)) then
            p.shakeArgs(makePrefix(prefix, "content" .. tostring(i)), level + 1)
        end
    end

    _ = getArg(prefix, "below")
end

-- 检查是否关闭展开折叠按钮
local function hasCollapsibleToggle(context)
    local prefix = context.prefix
    local state = getArg(prefix, "state", nil, context)

    if state == 'off' or state == 'plain' then
        return false
    else
        return true
    end
end

-- 检查是否使用过Navbar
local function hasNavBar(context,pass)
    if pass then return haveNavBarMarker end

    local prefix = context.prefix
    local navbar, name =
        getArg(prefix, "navbar", nil, context),
        getArg(prefix, "name")
    local parentTitle = mw.getCurrentFrame():getParent():getTitle()

    if navbar == 'off' or navbar == 'plain' or 
    (
        (not name) and
        parentTitle:gsub('/sandbox$', '') == MainTemplateName
    ) then
        return false
    else    
        haveNavBarMarker = true --用来启动模版样式标记
        return true
    end
end

-- 从CSS中提取出颜色
local function extractColor(cssstr)
    -- return nil because navbar takes its argument into mw.html which handles
    -- nil gracefully, removing the associated style attribute
    return mw.ustring.match(';' .. cssstr .. ';', '.*;%s*([Cc][Oo][Ll][Oo][Rr]%s*:%s*.-)%s*;') or nil
end

-- 检测class是否存在需要list
local function has_list_class(args_to_check)
	for _, list in pairs(listsCheck) do
		if not list.found then
			for _, arg in pairs(args_to_check) do
				for _, pattern in ipairs(list.patterns) do
					if mw.ustring.find(arg or '', pattern) then
						list.found = true
						break
					end
				end
				if list.found then break end
			end
		end
	end
end
---------------------------------------------------------------
--
--  元素渲染方法 (Element Render)
--

---创建表头
local function createNavTableHeader(context)
    debugLog('render TableHeader', context)
    local prefix = context.prefix
    local state, title, border = 
    		getArg(prefix, "state", nil, context),
			getArg(prefix, "title"),
			getArg(prefix, "border", nil, context)
    debugLog('render TableHeader args', {
        ['prefix'] = prefix,
        ['state'] = state,
        ['title'] = title,
        ['border'] = border
    })

    local bodyclass = getArg(prefix, "bodyclass", nil, context)
	has_list_class({bodyclass})
	
    local rootTable =
        mw.html.create('table')
            :attr('cellspacing', 0)
            :addClass('nowraplinks')
            :addClass(bodyclass)
            :css('border-spacing', 0)

    if title and hasCollapsibleToggle(context) then
        if state == 'collapsed' then state = 'mw-collapsed' end -- mw-collapsible 对应 展开模式
        rootTable
            :addClass('mw-collapsible')
            :addClass(state or 'autocollapse')
    end

    if borderIsChild(border) or border == 'none' then
        rootTable
            :addClass('navbox-subgroup')
            :cssText(getArg(prefix,"bodystyle", nil,context))
            :cssText(getArg(prefix, "style", nil, context))
    else -- regular navobx - bodystyle and style will be applied to the wrapper table
        rootTable
            :addClass('navbox-inner')
            :css('background', 'transparent')
            :css('color', 'inherit')
    end

    rootTable:cssText(getArg(prefix, "innerstyle"))

    debugLog('render TableHeader End')
    return rootTable
end

---创建三键导航
local function renderNavBar(titleCell, context)
    debugLog('render Navbar')
    
    if hasNavBar(context) then
        local navbarFunc = require('Module:Navbar')._navbar
        titleCell
            :wikitext(navbarFunc {
                name,
                mini = 1,
                fontstyle = extractColor(
                    table.concat({
                        getArg(prefix, 'basestyle', nil, context) or '',
                        getArg(prefix, 'titlestyle', nil, context) or ''
                    }, ';')
                )
            })
    end

    debugLog('render Navbar End')
end

---标题行
local function renderTitleRow(rootTable, context)
    local prefix = context.prefix
    local title = getArg(prefix, "title", nil, context)
    if not title then return end
    debugLog('render TitleRow', {
        ['prefix'] = prefix,
        ['title'] = title
    },context)
    local basestyle = getArg(prefix, "basestyle", nil, context)
    local titleRow = rootTable:tag('tr')

    local titlegroup = getArg(prefix, "titlegroup")
    local needTitleGroup = titlegroup and (not context.notNeedTitlegroup)
    if needTitleGroup then
        if hasCollapsibleToggle(context) then titleRow:addClass('collapsible-title') end
        titleRow
            :tag('th')
                :attr('scope', 'row')
                :addClass('navbox-group')
                :addClass(getArg(prefix, "titlegroupclass"))
                :cssText(basestyle)
                :cssText(getArg(prefix, "groupstyle", nil, context))
                :cssText(getArg(prefix,"titlegroupstyle"))
                :wikitext(titlegroup)
    end

    local titleCell = titleRow:tag('th'):attr('scope', 'col')
    local titleColspan = context.totalColspan
    if needTitleGroup then
        titleCell
            :css('border-left', '2px solid #fdfdfd')
            :css('width', '100%')

        titleColspan = titleColspan - 1
    elseif hasCollapsibleToggle(context) then
        titleCell
            :addClass('collapsible-title')
    end
    titleCell
        :cssText(basestyle)
        :cssText(getArg(prefix, "titlestyle", nil, context))
        :addClass('navbox-title')
        :attr('colspan',titleColspan)

    renderNavBar(titleCell, context)

    titleCell
        :tag('div')
            :addClass(getArg(prefix, "titleclass", nil, context))
            :css('font-size', '110%')
            :css('margin', '0 5em')
            :wikitext(addNewline(title))

    debugLog('render TitleRow End')
end

---上行
local function renderAboveRow(rootTable, context)
    local prefix = context.prefix
    local above = getArg(prefix, "above")
    if not above then return end
    debugLog('render AboveRow', {['prefix'] = prefix}, context)

    local Colspan = context.totalColspan
    local AboveRow = rootTable:tag('tr')
    AboveRow
        :tag('td')
            :addClass('navbox-abovebelow')
            :addClass(getArg(prefix,"aboveclass"))
            :cssText(getArg(prefix, "basestyle"))
            :cssText(getArg(prefix,"abovestyle"))
            :attr('colspan', Colspan)
            :tag('div')
                :wikitext(addNewline(above))

    debugLog('render AboveRow End')
end

---下行
local function renderBelowRow(rootTable, context)
    local prefix = context.prefix
    local below = getArg(prefix, "below")
    if not below then return end
    debugLog('render BelowRow', {['prefix'] = prefix}, context)

    local Colspan = context.totalColspan
    local BelowRow = rootTable:tag('tr')
    BelowRow
        :tag('td')
            :addClass('navbox-abovebelow')
            :addClass(getArg(prefix,"belowclass"))
            :cssText(getArg(prefix, "basestyle"))
            :cssText(getArg(prefix,"belowstyle"))
            :attr('colspan', Colspan)
            :tag('div')
                :wikitext(addNewline(below))

    debugLog('render BelowRow End')
end

---------------------------------------------------------------

-- 数据列的方法生成器
local function _renderColRow_FunctionBuilder(rootTable, context, nodeFunc)
    debugLog("_renderColRow_FunctionBuilder builded", {['context'] = context})
    return function(listCellDivToWrite, divNotClose)
        debugLog(debug.traceback('FunctionInrenderColRow'),
                 {['context'] = context, ['divNotClose'] = divNotClose})

        if not divNotClose then
            listCellDivToWrite:done() -- div end
            :node(rootTable and
                nodeFunc(rootTable, context) or
                nodeFunc(context)
            )
            :tag('div'):done()
        else
            listCellDivToWrite:node(nodeFunc(rootTable, context))
        end
    end
end

---数据行,统一的实现
---TODO: 更新odd/even检测代码
local function _renderListRow(rootTable, context, OtherListFunction)

    local prefix, level = context.prefix, context.level
    local listnum = context.listnum or 1
    local index = context.listindex or listnum
    --local isFirst, isOdd = (listnum == 1), (listnum % 2) == 1
    local isFirst, isOdd = (index == 1), (index % 2) == 1
    local ImageRowspan = context.totalRowspan + (context['imageCellCompensate'] or 0)
    local notNeedImage, notNeedGroup = context.notNeedImage, context.notNeedGroup
    debugLog('ValueRow Implement', {
        ['prefix'] = prefix,
        ['listnum'] = listnum,
        ['ImageRowspan'] = ImageRowspan,
        ['HaveOtherListFunction'] = tostring(not not OtherListFunction),
        ['notNeedImage'] = notNeedImage,
        ['notNeedGroup'] = notNeedGroup
    }, context)
    
    local listRow = rootTable:tag('tr')
    local groupCell, listCell

    -- image
    local imageLeft, image, insertImage =
        getArg(prefix, "imageleft", nil, context),
        getArg(prefix, "image", nil, context),
        false
    -- CollapsibleListRow 适配
    if context.notImageLeftCell then imageLeft = nil end
    if context.notImageCell then image = nil end
    if isFirst and (not notNeedImage) then
        if imageLeft then
            debugLog('imageLeftRow', {['imageLeft'] = imageLeft})
            listRow
                :tag('td')
                    :addClass('noviewer')
                    :addClass('navbox-image')
                    :addClass(getArg(prefix, "imageclass", nil, context))
                    :css('width', '1px') -- Minimize width
                    :css('padding', '0px 2px 0px 0px')
                    :cssText(getArg(prefix,"imageleftstyle",nil, context))
                    :attr('rowspan', ImageRowspan)
                        :tag('div')
                            :wikitext(addNewline(imageLeft))
                        :done() -- div done
                    :done() -- td done
        end
        if image then insertImage = true end
    end

    -- group start
	local needGroup, haveGroupWidth = false, false
	do 
	    local group, groupwidth =
	        getArg(prefix,"group" ..listnum,nil,context),
	        nil
	    if group and not notNeedGroup then needGroup = true end 
	    if group then groupwidth = getArg(prefix,"groupwidth") end
	    if groupwidth then haveGroupWidth = true end 
	    debugLog("_renderListRow().group_part",{['group']=group,['groupwidth']=groupwidth})
	            
	    if needGroup then
	        debugLog('groupTh', {['group'] = group})
	        groupCell = listRow
	            :tag('th')
	                :attr('scope', 'row')
	                :addClass('navbox-group')
	                :addClass(getArg(prefix, "groupclass", nil, context))
	                :cssText(getArg(prefix, "basestyle"))
	                :css('width', groupwidth or "1%" ) -- If groupwidth not specified, minimize width
	                :cssText(getArg(prefix, "groupstyle"))
	                :cssText(getArg(prefix,'group' ..listnum ..'style'))
	                :wikitext(group)
	    end
    end
	-- group end
	
    -- list start
    do
    	local listHaveChild = checkHaveChild(prefix, 'list' .. listnum)
    	local contentHaveChild = context.contentEqList and checkHaveChild(prefix, 'content' .. listnum)
    	
        listCell = listRow:tag('td')
        if needGroup then
            listCell:addClass('navbox-list-with-group')
        else
            listCell:attr('colspan', 2)
        end

        if not haveGroupWidth then listCell:css('width', '100%') end

		-- TODO 更新odd/even检测代码
        local evenOdd = getArg(prefix, "evenodd")
        evenOdd = (
            evenOdd == 'swap' and
            (isOdd and 'even' or 'odd') or
            (isOdd and (evenOdd or 'odd') or (evenOdd or 'even'))
        )
        local evenOddStyle = (isOdd and getArg(prefix, "evenstyle")) or getArg(prefix, "oddstyle")
        if context.lockEvenOdd then -- CollapsibleListRow 适配
            evenOdd = 'odd'
        end
        if context.noEvenOddStyle then -- CollapsibleListRow 适配
            evenOddStyle = ''
        end

        local list1padding = (notNeedGroup) and
                            getArg(prefix, "list1padding", nil, context) or
                            '0em 0.25em'
        local listNpadding = (isFirst and list1padding) or
                            (getArg(prefix, "listpadding", nil, context) or
                            '0em 0.25em')
        local listNstyle = -- ((not notNeedGroup))
                            (isFirst and getArg(prefix, 'list1style', '', context)) or
                            getArg(prefix, 'list' .. listnum .. 'style', '')
        local liststyle = getArg(prefix, "liststyle", '', context)
		local listclass = getArg(prefix, "listclass", nil , context)
		has_list_class({listclass})
		
        listCell
            :css('padding', '0px')
            :cssText(liststyle)
            :cssText(evenOddStyle)
            :cssText(listNstyle)
            :addClass('navbox-list')
            :addClass('navbox-' ..evenOdd)
            :addClass(listclass)
            
        local tempdiv = listCell:tag('div'):css('padding', listNpadding)
        if OtherListFunction then
            debugLog('ValueRow OtherListFunction', {
                ['otherListFunctionDivNotClose'] = context.otherListFunctionDivNotClose
            })
            OtherListFunction(tempdiv, context.otherListFunctionDivNotClose)
        elseif (listHaveChild or contentHaveChild) and level <= Limit.child then
            local listKeyName = contentHaveChild and 'content' or 'list'
			local childPrefix= makePrefix(prefix, listKeyName ..listnum)
            local childContext = NavboxContext.new(
                    childPrefix,
                    level + 1,
                    getValidType(getArg(childPrefix,'type'),NavType.V)
            )

            debugLog('ValueRow NewChild', childContext)
            tempdiv
                :done() -- div end
                :node(p.renderNavTable(childContext))
                :tag('div'):done()
        else
            local list_str = getArg(prefix, 'list' .. listnum, '')
            local content_str = getArg(prefix, 'content' .. listnum, '') -- VerticalCollapsibleTable 的 Content适配
            if not context.contentEqList then 
            	content_str = ''
        	end
            debugLog('ValueRow listnum', {['listnum'] = listnum})
            tempdiv:wikitext(addNewline(table.concat({list_str,content_str})))
        end
    end
    -- list end

    if insertImage then
        debugLog('imageRow', {['image'] = image})
        listRow
            :tag('td')
                :addClass('noviewer')
                :addClass('navbox-image')
                :addClass(getArg(prefix,"imageclass",nil, context))
                :css('width', '1px')  -- Minimize width
                :css('padding', '0px 0px 0px 2px')
                :cssText(getArg(prefix, "imagestyle", nil, context))
                :attr('rowspan',ImageRowspan)
                :tag('div')
                    :wikitext(addNewline(image))
    end
    debugLog('ValueRow Implement End')
end

---数据行,垂直式的具体实现
local function renderListRow(rootTable, context)
    debugLog('render ListRow', context)
    _renderListRow(rootTable, context)
    debugLog('render ListRow End')
end

---------------------------------------------------------------

---数据列,水平式的具体实现 (ColRow)
local function _renderColRow(rootTable, context)
    local prefix, level = context.prefix, context.level
    local fullwidth = getArg(prefix, "fullwidth")
    local col1header, col1, col1footer =
        getArg(prefix, 'col1header'),
        getArg(prefix, 'col1'),
        getArg(prefix, 'col1footer')
    debugLog('ColRow Implement', {['prefix'] = prefix}, context)
    -- new table root
    rootTable = mw.html.create('table')
    rootTable
        :addClass("navbox-columns-table")
        :attr("cellspacing", "0")
        :cssText("text-align:left;")
        :cssText((col1header or fullwidth) and "width:100%;" or
            "width:auto;margin-left:auto;margin-right:auto;")
        :cssText(getArg(prefix,"coltablestyle"))

    local headerTR, colbodyTR, footerTR = nil, nil, nil

    -- header
    if col1header then

        debugLog('ColRow Header', {})
        headerTR = rootTable:tag('tr')
        for colnum = 1, Limit.horizontal.col do
            debugLog('ColRow Header', colnum)
            local isFirst, isOdd = colnum == 1, (colnum % 2) == 1
            local colheaderkey = 'col' .. colnum .. 'header'
            local colNheader = isFirst and col1header or  getArg(prefix, colheaderkey)

            if headerTR and colNheader then
                debugLog('ColRow Herder Cell', {['colnum'] = colnum})
                local headerNCell = headerTR:tag('td')
                headerNCell
                    :addClass('navbox-abovebelow')
                    :cssText(isFirst and "" or "border-left:2px solid #fdfdfd;")
                    :cssText(getArg(prefix, "colheaderstyle"))
                    :cssText(getArg(prefix,colheaderkey ..'style'))
                    :attr((colnum ~= Limit.horizontal.col and
                         {['colspan'] = getArg(prefix, colheaderkey .. 'colspan', 1)}) or
                         {})
--[[            if checkHaveChild(prefix,colheaderkey) and level<= Limit.child then
                    local childContext=NavboxContext.new(colheaderkey ,level+1 ,NavType.H,context)
                    debugLog('ColRow Herder NewChild',childContext)
                    headerNCell:node(p.renderNavTable(childContext):allDone())
                else]]
                -- debugLog('ColRow Herder Cell',{['colnum']=colnum})
                headerNCell:wikitext(addNewline("'''" .. colNheader .. "'''"))
                -- end
            end
        end
        debugLog('ColRow Header End', {['colnum'] = colnum})
    end

    -- col
    local col1havechild = checkHaveChild(prefix, "col1")
    if col1 or col1havechild then

        debugLog('ColRow Body', {['col1havechild'] = col1havechild})
        colbodyTR = rootTable:tag('tr'):cssText('vertical-align:top;')
        if not (col1header or col1footer or fullwidth) then
            local padding, test0 = getArg(prefix, "padding"), nil
            if padding then
                padding = mw.text.trim(padding)
                test0 = mw.ustring.find(padding,'^0[%%%a]?[%a]?[;]?$')
            end
            if test0 ~= nil or padding == 'off' then
            else
                colbodyTR
                    :tag('td')
                        :css("width", padding or '5em')
                        :wikitext('&nbsp;&nbsp;&nbsp;')
                        :done()
            end
        end

        for colnum = 1, Limit.horizontal.col do
            debugLog('ColRow Body', colnum)
            local isFirst, isOdd = colnum == 1, (colnum % 2) == 1
            local colkey = 'col' .. colnum
            local colN = isFirst and col1 or getArg(prefix, colkey)
            local colNhavechild = isFirst and col1havechild or checkHaveChild(prefix, colkey)
            
            if colN or colNhavechild then
                local oddevenstyle = getArg(prefix, isOdd and 'oddcolstyle' or'evencolstyle')
                local colNCell = colbodyTR
                    :tag('td')
                        :css("padding", "0px")
                        :cssText(((not isFirst) and "border-left:2px solid #fdfdfd;") or '')
                        :cssText(getArg(prefix, 'colstyle'))
                        :cssText(oddevenstyle)
                        :cssText(getArg(prefix, colkey .. 'style'))
                        :css('width',
                            (getArg(prefix, colkey .. 'width') or
                            getArg(prefix, 'colwidth')) or
                            '10em')

                if checkHaveChild(prefix, colkey) and level <= Limit.child then
                    local childContext =
                        NavboxContext.new(
                        	makePrefix(prefix , colkey),
                            level + 1,
                            getValidType(getArg(prefix, 'type'), NavType.H)
                        )
                    debugLog('ColRow Body NewChild', childContext)
                    colNCell
                        :tag('div'):done()
                        :node(p.renderNavTable(childContext):allDone())
                        :tag('div'):done()
                else
                    debugLog('ColRow Body Cell', {['colnum'] = colnum})
                    colNCell:tag('div'):wikitext(addNewline('\n'..colN..'\n'))
                end
            end
            debugLog('ColRow Body End', {['colnum'] = colnum})
        end
    end

    -- footer
    if col1footer then

        debugLog('ColRow footer', {})
        footerTR = rootTable:tag('tr')
        for colnum = 1, Limit.horizontal.col do
            debugLog('ColRow footer', colnum)
            local isFirst, isOdd = colnum == 1, (colnum % 2) == 1
            local colfooterkey = 'col' .. colnum .. 'footer'
            local colNfooter = isFirst and col1footer or getArg(prefix, colfooterkey)

            if colNfooter then
                debugLog('ColRow footer Cell', {['colnum'] = colnum})
                local footerNCell = footerTR:tag('td')
                footerNCell
                    :addClass('navbox-abovebelow')
                    :cssText(isFirst and "" or "border-left:2px solid #fdfdfd;")
                    :cssText(getArg(prefix, "colfooterstyle"))
                    :cssText(getArg(prefix, colfooterkey ..'style'))
                    :attr((colnum ~= Limit.horizontal.col and
                         {['colspan'] = getArg(prefix,colfooterkey .. 'colspan', 1)}) or
                         {})
--[[            if checkHaveChild(prefix,colfooterkey) and level<= Limit.child then
                    local childContext=NavboxContext.new(colfooterkey ,level+1 ,NavType.H,context)
                    debugLog('ColRow footer NewChild',childContext)
                    footerNCell:node(p.renderNavTable(childContext):allDone())
                else]]
                -- debugLog('ColRow footer Cell',{['colnum']=colnum})
                footerNCell:wikitext(addNewline("'''" .. colNfooter .. "'''"))
                -- end
            end
        end
        debugLog('ColRow footer End', {['colnum'] = colnum})
    end

    debugLog('ColRow Implement End')
    return rootTable:allDone()
end

-- 数据列,具体实现
local function renderColRow(rootTable, context)
    debugLog('renderColRow', {['context'] = context})

    context.notNeedGroup = true
    context['list1padding'] = '0px'
    context['list1style'] = "background:transparent;color:inherit;"
    context['otherListFunctionDivNotClose'] = true
    context['imageCellCompensate'] = 1

    _renderListRow(
        rootTable,
        context,
        _renderColRow_FunctionBuilder(rootTable,context,_renderColRow)
    )

    -- clean up
    context.notNeedGroup = nil
    context['list1padding'] = nil
    context['list1style'] = nil
    context['otherListFunctionDivNotClose'] = nil
    context['imageCellCompensate'] = nil
    debugLog('renderColRow End')
end

---------------------------------------------------------------

-- 折叠行式的子Nabox
local function _renderSmallNavboxInCollapsibleListRow(rootTable, context)
    local prefix, level = context.prefix, context.level
    debugLog('_renderSmallNavboxInCollapsibleListRow',
             {['prefix'] = prefix},
             {['context'] = context})
    local listnum = context.listnum

    -- 部分需要压制传入的样式
    context.bodyclass = ''
    context.titleclass = ''
    context.groupclass = ''
    context.imageclass = ''
    context.bodystyle = ''
    context.style = ''
    context.basestyle = ''
    context.imagestyle = ''
    context.imageleftstyle = ''

    -- 传入renderNavBar,renderTitleRow
    context.navbar = 'plain'
    context.border = 'child'
    local selected, abbrN, state =
                    getArg(prefix, 'selected'),
                    getArg(prefix, 'abbr' .. listnum),
                    'expanded'
    if selected ~= nil and selected == abbrN then
        state = 'expanded'
    else
        state = getArg(prefix, 'state' .. listnum, 'collapsed')
    end
    context.state = state

    -- 传入renderTitleRow
    -- context.titleEqGroup=true
    context.notNeedTitlegroup = true
    context.titlestyle = table.concat({
        (getArg(prefix, 'basestyle', '')),
        (getArg(prefix, 'groupstyle', '')),
        (getArg(prefix, 'secttitlestyle', '')),
        (getArg(prefix, 'group' .. listnum .. 'style', '')),
        (getArg(prefix, 'sect' .. listnum .. 'titlestyle', ''))
    }, ';')
    context.title = (getArg(prefix, 'group' .. listnum, '')) ..
                    (getArg(prefix, 'sect' .. listnum, '')) ..
                    (getArg(prefix, 'section' .. listnum, ''))

    -- 传入renderListRow
    context.contentEqList = true
    context.notNeedGroup = true
    context.liststyle = table.concat({
        (getArg(prefix, 'liststyle', '')),
        (getArg(prefix, 'contentstyle', '')),
        (getArg(prefix, 'list' .. listnum .. 'style', '')),
        (getArg(prefix, 'content' .. listnum .. 'style', ''))
    }, ';')
    local totalColspan = 2 -- title,above,below
    local totalRowspan = 1 -- image,imageleft

    -- 传入image
    local imageLeft, image = getArg(prefix, "imageleft" .. listnum, nil,context, 'imageleft'),
                             getArg(prefix,"image" ..listnum,nil, context,'image')
    if imageLeft then
        totalColspan = totalColspan + 1
        context.imageleft = imageLeft
    else
        context.notImageLeftCell = true -- CollapsibleListRow 适配
    end
    if image then
        totalColspan = totalColspan + 1
        context.image = image
    else
        context.notImageCell = true -- CollapsibleListRow 适配
    end

    context.totalColspan = totalColspan
    context.totalRowspan = totalRowspan
    context.lockEvenOdd = true -- CollapsibleListRow 适配

    debugLog(
        'SmallNavboxInCollapsibleListRow Implement',
        'listnum=' .. listnum,
        context)

    -- start
    local rootTable2 = createNavTableHeader(context)
    renderTitleRow(rootTable2, context)
    -- only 1 list
    local otherListFunction
    local listHaveChild = checkHaveChild(prefix, 'list' .. listnum)
    local contentHaveChild = context.contentEqList and
                                 checkHaveChild(prefix, 'content' .. listnum)
    if (listHaveChild or contentHaveChild) and level <= Limit.child then
        local listKeyName = 'list'
        if contentHaveChild then listKeyName = 'content' end
        local childPrefix = makePrefix(prefix , listKeyName .. listnum)
        local childContext = NavboxContext.new(
                childPrefix,
                level + 1,
                getValidType(getArg(childPrefix, 'type'),NavType.V)
        )
        debugLog('SmallNavboxInCollapsibleListRow NewChild', childContext)
        otherListFunction = _renderColRow_FunctionBuilder(
                nil,
                childContext,
                p.renderNavTable)
    end
    context.noEvenOddStyle = true
    _renderListRow(rootTable2, context, otherListFunction)
    context.noEvenOddStyle = nil
    debugLog('_renderSmallNavboxInCollapsibleListRow End')
    return rootTable2:allDone()
end

---折叠行具体实现
local function renderCollapsibleListRow(rootTable, context)
    local prefix, level = context.prefix, context.level
    debugLog('renderCollapsibleListRow', {
            ['prefix'] = prefix},
            {['context'] = context})
    context.notNeedGroup = true
    local listnum = context.listnum
    local context_function
    if getArg(prefix, 'group' .. listnum) or 
       getArg(prefix, 'sect' .. listnum) or
       getArg(prefix, 'section' .. listnum) 
    then
        local grandChild_context = NavboxContext.new(prefix, level)
        grandChild_context.notNeedGroup = true
        grandChild_context.listpadding = getArg(prefix, 'listpadding')
        grandChild_context.listnum = listnum
        context_function = _renderColRow_FunctionBuilder(
                            rootTable,
                            grandChild_context,
                            _renderSmallNavboxInCollapsibleListRow)
        debugLog('renderCollapsibleListRow function generate', {
            ['context'] = context,
            ['grandChild_context'] = grandChild_context
        })
    end
    context.noEvenOddStyle = true
    context.contentEqList = true
    debugLog('renderCollapsibleListRow renderListRow', {['context'] = context})
    _renderListRow(rootTable, context, context_function)
    context.noEvenOddStyle = nil
    context.contentEqList = nil
    debugLog('renderCollapsibleListRow End')
end

---------------------------------------------------------------
--
--   Tracking categories
--

-- 没有使用水平列表的导航框
local function needsHorizontalLists(context)
    local prefix = context.prefix
    local border, tracking  =
                context.border or getArg(prefix, 'border'),
                getArg(prefix, 'tracking')
    debugLog('needsHorizontalLists',
        {['border']=border,['tracking']=tracking})
    if borderIsChild(border) or tracking == 'no' then
        return false
    end

    return not listsCheck.hlist_t.found and not listsCheck.plainlist_t.found
end

-- 使用背景颜色的导航框
local function hasBackgroundColors(context)
    local prefix = context.prefix
    for _, key in ipairs({'titlestyle', 'groupstyle', 'basestyle'}) do
		local style=context[key] or getArg(prefix, key) or ''
        if tostring(style):find('background', 1, true) then
			return true
        end
    end
    return false
end

-- name參數和實際不同的導航框
local function argNameAndRealTitleAreDifferent(context)
    local prefix = context.prefix
    local border, name, tracking =
                getArg(prefix, 'border', nil, context),
                getArg(prefix, 'name', nil, context),
                getArg(prefix, 'tracking')
    debugLog('argNameAndRealTitleAreDifferent',
        {['border']=border,['name']=name,['tracking']=tracking})
    if borderIsChild(border) or tracking == 'no' or not hasNavBar(context) then
        return false
    end

    if name ~= mw.title.getCurrentTitle().text then return true end
    return false
end

local catCheckList = {
    ['needsHorizontalLists'] = {
        ['catkey'] = 'needsHorizontalLists',
        ['catCheckFunc'] = needsHorizontalLists,
        ['catName'] = '没有使用水平列表的导航框'
    },
    ['hasBackgroundColors'] = {
        ['catkey'] = 'hasBackgroundColors',
        ['catCheckFunc'] = hasBackgroundColors,
        ['catName'] = '使用背景颜色的导航框'
    },
    ['argNameAndRealTitleAreDifferent'] = {
        ['catkey'] = 'argNameAndRealTitleAreDifferent',
        ['catCheckFunc'] = argNameAndRealTitleAreDifferent,
        ['catName'] = 'name參數和實際不同的導航框'
    }
}

-- 检查并获得需要的分类
local function getTrackingCategories(context)
    local cats = _G['globalCatList'] or {}
    for catkey, checkObj in pairs(catCheckList) do
        if checkObj['catCheckFunc'](context) then
            table.insert(cats, checkObj['catkey'])
        end
    end
    debugLog('getTrackingCategories',{['level']=context.level,['catList']=cats})
    _G['globalCatList'] = cats
end

-- 生成分类
local function renderTrackingCategories(builder, context)
    local title = mw.title.getCurrentTitle()
    if DEBUG == false then
        if title.namespace ~= 10 then return end -- not in template space
        local subpage = title.subpageText
        if subpage == 'doc' or subpage == 'sandbox' or subpage == 'testcases' then
            return
        end --
    end

    getTrackingCategories(context)
    debugLog('renderTrackingCategories',{['level']=context.level})
    
    if context.level ==1 then
        local catList=_G['globalCatList'] or {}
        catList = removeDump(catList)
        for i, cat in ipairs(catList) do
            builder:wikitext('[[Category:' .. catCheckList[cat]['catName'] ..']]')
        end
    end
end
---------------------------------------------------------------
--
-- 模板样式的调整
--

-- work around [[phab:T303378]]
-- for each arg: find all the templatestyles strip markers, insert them into a
-- table. then remove all templatestyles markers from the arg
local function move_hiding_templatestyles(args)
	local gfind = string.gfind
	local gsub = string.gsub
	local templatestyles_markers = {}
	local strip_marker_pattern = '(\127[^\127]*UNIQ%-%-templatestyles%-%x+%-QINU[^\127]*\127)'
	for k, arg in pairs(args) do
		for marker in gfind(arg, strip_marker_pattern) do
			table.insert(templatestyles_markers, marker)
		end
		args[k] = gsub(arg, strip_marker_pattern, '')
	end
	return templatestyles_markers
end

--
-- Load the templatestyles for the navbox
--
local function loadTemplateStyles(hiding_templatestyles)
    local frame = mw.getCurrentFrame()
    local templateStyles = {}

	-- 提前注入,到时清空
	templateStyles[1] = frame:extensionTag{
        name = 'templatestyles', args = { src = listsCheck.hlist_t.styles }
    }
    --[[
    if listsCheck.hlist_t.found then
        hlist_templatestyles = frame:extensionTag{
	        name = 'templatestyles', args = { src = listsCheck.hlist_t.styles }
	    }
    else
        templateStyles[1] = ''
    end
    ]]
    -- a second workaround for [[phab:T303378]]
    -- when that issue is fixed, we can actually use has_navbar not to emit the
    -- tag here if we want
    --[[
    if hasNavBar(nil,true) and hlist_templatestyles == '' then
        hlist_templatestyles = frame:extensionTag{
            name = 'templatestyles', args = { src = listsCheck.hlist_t.styles }
        }
        templateStyles[1] = hlist_templatestyles
    end]]

    if listsCheck.plainlist_t.found then
         templateStyles[2] = frame:extensionTag{
            name = 'templatestyles', args = { src = listsCheck.plainlist_t.styles }
        }
    else
    	templateStyles[2] = ''	
    end

    templateStyles[3] = frame:extensionTag{
        name = 'templatestyles', args = { src = 'Module:Navbox/styles.css' }
    }

    local base_templatestyles = getArg("","templatestyles","")
    if base_templatestyles~= '' then
	    templateStyles[4] = frame:extensionTag{
	        name = 'templatestyles', args = { src = base_templatestyles }
	    }
    else
    	templateStyles[4] = ''
	end

    local child_templatestyles = getArg("","child templatestyles","")
    if child_templatestyles~= '' then 
	    templateStyles[5] = frame:extensionTag{
	        name = 'templatestyles', args = { src = child_templatestyles }
	    }
    else
    	templateStyles[5] = ''
	end
    
    -- 其他
    for _ , v in pairs(hiding_templatestyles) do
        templateStyles[#templateStyles+1] = v
    end
    
    return templateStyles
end

---------------------------------------------------------------
--
--  SubType Implement
--

---水平式
local function renderHorizontalTable(context)
    debugLog('render Horizontal NavTable', context)
    local prefix, level = context.prefix, context.level

    local rootTable = createNavTableHeader(context)

    local listnums = getListnum(prefix, Limit.horizontal.list)

    local totalColspan = 2 -- title,above,below
    local totalRowspan = #listnums -- image,imageleft
    if getArg(prefix, "imageleft", nil, context) then
        totalColspan = totalColspan + 1
    end
    if getArg(prefix, "image", nil, context) then
        totalColspan = totalColspan + 1
    end
    context.totalColspan = totalColspan
    context.totalRowspan = totalRowspan

    renderTitleRow(rootTable, context)
    renderAboveRow(rootTable, context)

    if listnums == nil or #listnums == 0 then -- 没有list的话,只有col
        debugLog('render Horizontal NavTable,no list', {listnums})
        context.listnum = 1
        renderColRow(rootTable, context)
        -- context.notNeedImage=true
    else
        debugLog('render Horizontal NavTable,have list with col', {listnums})
        for i, listnum in ipairs(listnums) do
            context.listnum = listnum
            context.listindex = i
            if listnum == 1 then
                -- 一行Col
                renderColRow(rootTable, context)
                context.notNeedImage = true
            else
                context.notNeedImage = nil
            end
            _renderListRow(rootTable, context)
        end
    end
    renderBelowRow(rootTable, context)

    if (getArg("nocat") or 'false'):lower() == 'false' then
       renderTrackingCategories(rootTable, context)
    end
    debugLog('render Horizontal NavTable End')
    return rootTable
end

---垂直式
local function renderVerticalTable(context)
    debugLog('render Vertical NavTable', context)
    local prefix, level = context.prefix, context.level

    local rootTable = createNavTableHeader(context)

    local listnums = getListnum(prefix, Limit.vertical)

    local totalColspan = 2 -- title,above,below
    local totalRowspan = #listnums -- image,imageleft
    if getArg(prefix, "imageleft", nil, context) then
        totalColspan = totalColspan + 1
    end
    if getArg(prefix, "image", nil, context) then
        totalColspan = totalColspan + 1
    end
    context.totalColspan = totalColspan
    context.totalRowspan = totalRowspan

    renderTitleRow(rootTable, context)
    renderAboveRow(rootTable, context)
    for i, listnum in ipairs(listnums) do
        context.listnum = listnum
        context.listindex = i
        renderListRow(rootTable, context)
    end
    renderBelowRow(rootTable, context)

    if (getArg("nocat") or 'false'):lower() == 'false' then
       renderTrackingCategories(rootTable, context)
    end
    debugLog('render Vertical NavTable End')
    return rootTable
end

---垂直折叠式
local function renderVerticalCollapsibleTable(context)
    debugLog('render VerticalCollapsible NavTable', context)
    local prefix, level = context.prefix, context.level

    local rootTable = createNavTableHeader(context)

    local listnums = getListnum(prefix, Limit.vertical,
        ( --[[context.contentEqList or ]] true) -- VerticalCollapsibleTable 的 Content适配
    )

    local totalColspan = 2 -- title,above,below
    local totalRowspan = #listnums -- image,imageleft
    if getArg(prefix, "imageleft", nil, context) then
        totalColspan = totalColspan + 1
    end
    if getArg(prefix, "image", nil, context) then
        totalColspan = totalColspan + 1
    end
    context.totalColspan = totalColspan
    context.totalRowspan = totalRowspan

    renderTitleRow(rootTable, context)
    renderAboveRow(rootTable, context)
    for i, listnum in ipairs(listnums) do
        context.listnum = listnum
        context.listindex = i
        renderCollapsibleListRow(rootTable, context)
    end
    renderBelowRow(rootTable, context)

    if (getArg("nocat") or 'false'):lower() == 'false' then
       renderTrackingCategories(rootTable, context)
    end
    debugLog('render VerticalCollapsible NavTable End')
    return rootTable
end

---Type Selector
function p.renderNavTable(context)
    local navtype = context.type
    debugLog('render NavTable')
    debugLog('Type=' .. navtype)
    local result
    if navtype == NavType.H then
        result = renderHorizontalTable(context)
    elseif navtype == NavType.VC then
        result = renderVerticalCollapsibleTable(context)
    else
        result = renderVerticalTable(context)
    end
    debugLog('render NavTable End')
    return result
end

-- Main Funtion
function p._navbox(context)
    debugLog('Navbox mainfuntion', context)
    local prefix, level = context.prefix, context.level
	local hiding_templatestyles = move_hiding_templatestyles(args)
	
    local rootTable
    --[[
    适配list内再嵌套单独Navbox的情况,部分Navbox可以单独或者再嵌入使用
    原生的Navbox的各种实现机制就是Navbox嵌套
    ]]
    local border = mw.text.trim(getArg(prefix, 'border') or getArg(prefix, '1') or '')
    debugLog("_Navbox.border", border)
    local templateStylesArr={}
    if border == 'none' then
    	templateStylesArr=loadTemplateStyles(hiding_templatestyles)
        rootTable = p.renderNavTable(context):allDone()
        if not (listsCheck.hlist_t.found or hasNavBar(nil,true)) then
	    	templateStylesArr[1] = "" --清空掉
    	end
    elseif borderIsChild(border) then
        -- Navbox的值段直接嵌套单独Navbox的情况
        rootTable = mw.html.create()
        rootTable
            :wikitext('</div>')
            :node(p.renderNavTable(context):allDone())
            :wikitext('<div>')
    else
    	templateStylesArr=loadTemplateStyles(hiding_templatestyles)
        rootTable = mw.html.create('table')
        rootTable
            :attr('cellspacing', 0)
            :addClass('navbox')
            :css('border-spacing', 0)
            :cssText(getArg(prefix, 'bodystyle'))
            :cssText(getArg(prefix, 'style'))
                :tag('tr')
                    :tag('td')
                    :css('padding', '2px')
                    :node(p.renderNavTable(context):allDone())
        if not (listsCheck.hlist_t.found or hasNavBar(nil,true)) then
	    	templateStylesArr[1] = "" --清空掉
    	end
    end
    
	local tsNode = mw.html.create('div')
		:addClass("navbox-styles")
		:wikitext(table.concat(templateStylesArr))
    debugLog('Navbox mainfuntion End')
    return tsNode:allDone() , rootTable:allDone()
end

function p.navbox(frame)
    if not getArgs then getArgs = require('Module:Arguments').getArgs end

    local moduleArgs = getArgs(frame, {frameOnly = true})
    DEBUG = (moduleArgs['DEBUG']=='true') or DEBUG
    MainTemplateName = moduleArgs['MainTemplateName'] or MainTemplateName
    args = getArgs(frame, {wrappers = MainTemplateName, trim = true})
    DEBUG = (args['DEBUG']=='true') or DEBUG
    debugLog('Navbox start')
		
    --debugLog('getArgs done,', args)

    local prefix, level = "", 1
    local navType = getValidType(
                getArg(prefix, 'type') or moduleArgs['type'], NavType.V)
    -- Read the arguments in the order they'll be output in, to make references number in the right order.
    p.shakeArgs(prefix, level, navType)

    local L0Context = NavboxContext.new(prefix, level, navType)
    local tsNode , rootNode = p._navbox(L0Context)
    debugLog('rootnode build done, Navbox end')
	
    return table.concat({tostring(tsNode) , tostring(rootNode)})
end

return p