模块:Navbox:修订间差异

来自Rizline中文维基
无编辑摘要
标签已被回退
(撤销放克麦子讨论)的修订版本496
标签撤销
第2行: 第2行:
-- This module will implement {{Navbox}}
-- This module will implement {{Navbox}}
--
--
 
local p = {}
local p = {}
 
--Context start
local navbar = require('Module:Navbar')._navbar
local _NavboxContext={}
local NavboxContextNewObj=function(_prefix,_level,_type)
    return {
        prefix = _prefix
        ,level = _level
        ,type = _type
        ,_Context={}
    }
end
 
local NavboxContextMetaFunction={
    __index=function(_obj,key)
      local _key = tostring(key)
      if _key=='prefix' or _key =='level' or _key =='type' then
      return _obj[_key]
  else
        return _obj._Context[_key]
        end
    end
    ,__newindex=function(_obj,key,val)
    local _key = tostring(key)
      if _key=='prefix' or _key =='level' or _key =='type' then
      _obj[_key]=val
  else
        _obj._Context[_key]=val
        end
    end
    ,__tostring=function(_obj)
        local output={}
        table.insert(output,'prefix='.._obj.prefix)
        table.insert(output,'level='.._obj.level)
        table.insert(output,'type='.._obj.type)
        for k,v in pairs(_obj._Context) do
            table.insert(output,k..'='..v)
        end
        return 'context:{\n'..table.concat(output,",\n")..'\n}'
    end
}
 
_NavboxContext.new=function(prefix,level,_type)
    local _prefix = prefix or ""
    local _level = level or 1
 
    local newobj=NavboxContextNewObj(_prefix,_level,_type or '')
    setmetatable(newobj,NavboxContextMetaFunction)
    --[[function newobj:remove(key)
        mw.log(self)
        NavboxContext_Remove(self,key)
    end]]
    return newobj
end
--Context end
 
local navbarFunc = require('Module:Navbar')._navbar
local NavboxContext = _NavboxContext
local getArgs -- lazily initialized
local getArgs -- lazily initialized
local DEBUG=false


--全局性参数锚
local args
local args
 
local tableRowAdded = false
--常量定义 (Constant Define)
local border
local Limit={
local listnums = {}
      vertical=35
    ,horizontal={
        col =20
        ,list=6
      }
    ,vertical_collapsible=20
    ,child=10
}
 
local NavType={
    V="vertical" --垂直,list
    ,H="horizontal" --水平,col
    ,VC="vertical_collapsible" --折叠垂直
}
 
local MainTemplateName = 'Template:NavboxV2'
 
---------------------------------------------------------------
--
--工具箱方法 (Util Function)
--


local function trim(s)
local function trim(s)
第103行: 第25行:
end
end


---数组除重
local function addTableRow(tbl)
local function removeDump(arr)
     -- If any other rows have already been added, then we add a 2px gutter row.
    local _t1,_t2={},{}
     if tableRowAdded then
    for _,val in pairs(arr) do
         tbl
        _t1[val]=true
    end
    --table.remove(arr)
    for key,_ in pairs(_t1) do
        table.insert(_t2,key)
    end
    return _t2
end
 
local function tableToString(_table)
    local outputs={}
    if 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
 
local debugLog=function(...)
    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)
if NavType.V==input or NavType.H==input or NavType.VC==input then
  return input
end
return defVal
end
 
---检查border判断是不是子Navbox
local borderIsChild=function(border)
if border == 'subgroup' or border == 'child' then
  return true
end
return false
end
 
---获得参数
local getArg=function( _a , _b,defVal,context,_contextKey)
local contextKey = _contextKey or _b
if context and contextKey and context[contextKey] then
  --debugLog('getArg By Context',contextKey)
  return context[contextKey]
else
  local prefix= _a~=nil and _a or ""
  local key= (_b==nil and _a~=nil) and _a or _b
  local argsKey=prefix .. (prefix=="" and "" or "-") ..key
  --debugLog('getArg By InputArg',argsKey)
  return args[ argsKey ] or defVal
end
end
 
---子Navbox参数组判断
local checkHaveChild=function(prefix,valuekey)
    if getValidType(getArg(prefix, valuekey..'-'..'type'),nil) and
      borderIsChild(getArg(prefix, valuekey..'-'..'border')) then
        return true
    end
    return false
end
 
---获得listnum
local function getListnum(prefix,limit,contentEqList)
    debugLog("getListnum",{['prefix']=prefix,['limit']=limit})
    prefix=prefix:gsub('(-)','%%-')
    local listnums={}
    for k, v in pairs(args) do
        k = ('' .. k)
        --debugLog("getListnum,k=",k)
        local listnum =
              ( k:match('^'..prefix..(prefix=="" and "" or "%-")..'list(%d+)$') or
                k:match('^'..prefix..(prefix=="" and "" or "%-")..'list(%d+)%-')
              )or
              ( contentEqList and ( --VerticalCollapsibleTable 的 Content适配
                k:match('^'..prefix..(prefix=="" and "" or "%-")..'content(%d+)$') or
                k:match('^'..prefix..(prefix=="" and "" or "%-")..'content(%d+)%-')
              ) or nil)
        if listnum and tonumber(listnum)<=limit then
            listnum=tonumber(listnum)
            table.insert(listnums,listnum)
            --debugLog("getListnum,listnum=",listnum)
        end
    end
    listnums=removeDump(listnums)
    table.sort(listnums)
    debugLog('list:',listnums)
    debugLog('getListnum End')
    return listnums
end
 
---参数检查和摇匀
function p.shakeArgs(prefix,level)
    local _
    local list_limit=0
 
    _ = getArg(prefix,"title")
    _ = getArg(prefix,"above")
 
     if getArg(prefix,"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((prefix=="" and "" or "-").."col"..tostring(i).."header",level+1)
          end
 
          _ = getArg(prefix,"col"..tostring(i))
          if checkHaveChild(prefix,"col"..tostring(i)) then
              p.shakeArgs((prefix=="" and "" or "-").."col"..tostring(i),level+1)
          end
 
          _ = getArg(prefix,"col"..tostring(i).."footer")
          if checkHaveChild(prefix,"col"..tostring(i).."footer") then
              p.shakeArgs((prefix=="" and "" or "-").."col"..tostring(i).."footer",level+1)
          end
      end
     end
 
    if getArg(prefix,"type")==NavType.V then
        list_limit = Limit.vertical
    elseif getArg(prefix,"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
            --debugLog('shakeArgs',prefix,"list"..tostring(i))
            p.shakeArgs((prefix=="" and "" or "-").."list"..tostring(i),level+1)
        end
        if checkHaveChild(prefix,"content"..tostring(i)) then
            p.shakeArgs((prefix=="" and "" or "-").."content"..tostring(i),level+1)
        end
    end
 
    _ = getArg(prefix,"below")
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 rootTable=
        mw.html.create('table')
            :attr('cellspacing', 0)
            :addClass('nowraplinks')
            :addClass(getArg(prefix,"bodyclass",nil,context))
            :css('border-spacing', 0)
 
    if title and (state ~= 'plain' and state ~= 'off') then
        rootTable
            :addClass('collapsible')
            :addClass( state or 'autocollapse')
    end
 
    if border == 'subgroup' or border == 'child' 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
 
---分割行 (SplitRow)
local function renderSplitRow(rootTable,context)
    local colspan= context.splitRowcolspan or context.totalColspan
    debugLog('render SplitRow',{
        ['needAddSplitRow']=context.needAddSplitRow,
        ['colspan']=colspan,
    }
    ,context)
    if context.needAddSplitRow then
         rootTable
             :tag('tr')
             :tag('tr')
                 :css('height', '2px')
                 :css('height', '2px')
                 :tag('td')
                 :tag('td')
                    :attr('colspan',colspan)
                :attr('colspan', 3)
    else
     end
     end
     context.splitRowcolspan=colspan
      
     context.needAddSplitRow=true
     tableRowAdded = true
   
    return tbl:tag('tr')
end
end


---创建三键导航
local function renderNavBar(titleCell)
local function renderNavBar(titleCell,context)
    local prefix = context.prefix
    local  navbar , state , border, name , titlestyle =
          getArg(prefix,"navbar",nil,context)
          ,getArg(prefix,"state",nil,context)
          ,getArg(prefix,"border",nil,context)
          ,getArg(prefix,"name")
          ,getArg(prefix,'titlestyle',nil,context)
    debugLog('render Navbar',
        {['prefix']=prefix,
        ['navbar']=navbar,['state']=state,
        ['border']=border,['name']=name,
        ['titlestyle']=titlestyle}
        ,context
    )
     -- Depending on the presence of the navbar and/or show/hide link, we may need to add a spacer div on the left
     -- Depending on the presence of the navbar and/or show/hide link, we may need to add a spacer div on the left
     -- or right to keep the title centered.
     -- or right to keep the title centered.
     local spacerSide = nil
     local spacerSide = nil


     if navbar == 'off' then
     if args.navbar == 'off' then
         -- No navbar, and client wants no spacer, i.e. wants the title to be shifted to the left. If there's
         -- No navbar, and client wants no spacer, i.e. wants the title to be shifted to the left. If there's
         -- also no show/hide link, then we need a spacer on the right to achieve the left shift.
         -- also no show/hide link, then we need a spacer on the right to achieve the left shift.
         if state == 'plain' then spacerSide = 'right' end
         if args.state == 'plain' then spacerSide = 'right' end
     elseif navbar == 'plain' or
     elseif args.navbar == 'plain' or (not args.name and mw.getCurrentFrame():getParent():getTitle() == 'Template:Navbox' and (border == 'subgroup' or border == 'child' or border == 'none')) then
        (   not name and
            mw.getCurrentFrame():getParent():getTitle() == MainTemplateName and
            (border == 'subgroup' or border == 'child' or border == 'none')
        )
        then
         -- No navbar. Need a spacer on the left to balance out the width of the show/hide link.
         -- No navbar. Need a spacer on the left to balance out the width of the show/hide link.
            if state ~= 'plain' then spacerSide = 'left' end
        if args.state ~= 'plain' then spacerSide = 'left' end
     else
     else
         -- Will render navbar (or error message). If there's no show/hide link, need a spacer on the right
         -- Will render navbar (or error message). If there's no show/hide link, need a spacer on the right
         -- to balance out the width of the navbar.
         -- to balance out the width of the navbar.
         if state == 'plain' then spacerSide = 'right' end
         if args.state == 'plain' then spacerSide = 'right' end


         titleCell:wikitext(navbarFunc{
         titleCell:wikitext(navbar{  
             name,
             args.name,  
             mini = 1,
             mini = 1,  
             fontstyle = table.concat(
             fontstyle = (args.basestyle or '') .. ';' .. (args.titlestyle or '') ..  ';background:none transparent;border:none;'
            {
                  getArg(prefix,'basestyle',nil,context) or ''
                ,(titlestyle or '')
                ,'background:none transparent;border:none'
            }
            ,';')
         })
         })
     end
     end
 
   
     -- Render the spacer div.
     -- Render the spacer div.
     if spacerSide then
     if spacerSide then
第400行: 第74行:
                 :wikitext('&nbsp;')
                 :wikitext('&nbsp;')
     end
     end
    debugLog('render Navbar End')
end
end


---标题行
--
local function renderTitleRow(rootTable,context)
--  Title row
    local prefix = context.prefix
--
    local title = getArg(prefix,"title",nil,context)
local function renderTitleRow(tbl)
     if not title then return end
     if not args.title then return end
    debugLog('render TitleRow',{['prefix']=prefix,['title']=title},context)
    local basestyle = getArg(prefix,"basestyle",nil,context)
     local titleRow = addTableRow(tbl)
    renderSplitRow(rootTable,context)
   
     local titleRow=rootTable:tag('tr')
     if args.titlegroup then
 
    local titlegroup=getArg(prefix,"titlegroup")
     if titlegroup and (not context.notNeedTitlegroup) then
         titleRow
         titleRow
             :tag('th')
             :tag('th')
                 :attr('scope', 'row')
                 :attr('scope', 'row')
                 :addClass('navbox-group')
                 :addClass('navbox-group')
                 :addClass(getArg(prefix,"titlegroupclass"))
                 :addClass(args.titlegroupclass)
                 :cssText(basestyle)
                 :cssText(args.basestyle)
                 :cssText(getArg(prefix,"groupstyle",nil,context))
                 :cssText(args.groupstyle)
                 :cssText(getArg(prefix,"titlegroupstyle"))
                 :cssText(args.titlegroupstyle)
                 :wikitext(titlegroup)
                 :wikitext(args.titlegroup)
     end
     end
 
   
     local titleCell = titleRow:tag('th'):attr('scope', 'col')
     local titleCell = titleRow:tag('th'):attr('scope', 'col')
    local titleStyle = getArg(prefix,"titlestyle",nil,context)
           
     local titleColspan = context.totalColspan
     if args.titlegroup then
    if titlegroup and (not context.notNeedTitlegroup) then
         titleCell
         titleCell
             :css('border-left', '2px solid #fdfdfd')
             :css('border-left', '2px solid #fdfdfd')
             :css('width', '100%')
             :css('width', '100%')
        titleColspan = titleColspan - 1
     end
     end
   
    local titleColspan = 2
    if args.imageleft then titleColspan = titleColspan + 1 end
    if args.image then titleColspan = titleColspan + 1 end
    if args.titlegroup then titleColspan = titleColspan - 1 end
   
     titleCell
     titleCell
         :cssText(basestyle)
         :cssText(args.basestyle)
         :cssText(titleStyle)
         :cssText(args.titlestyle)
         :addClass('navbox-title')
         :addClass('navbox-title')
         :addClass(getArg(prefix,"titleclass",nil,context))
         :addClass(args.titleclass)
         :attr('colspan', titleColspan)
         :attr('colspan', titleColspan)
 
     renderNavBar(titleCell,context)
     renderNavBar(titleCell)


     titleCell
     titleCell
         :tag('div')
         :tag('div')
             :css('font-size', '110%')
             :css('font-size', '110%')
             :wikitext(addNewline(title))
             :wikitext(addNewline(args.title))
end
 
--
--  Above/Below rows
--


    debugLog('render TitleRow End')
local function getAboveBelowColspan()
    local ret = 2
    if args.imageleft then ret = ret + 1 end
    if args.image then ret = ret + 1 end
    return ret
end
end


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


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


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


     local Colspan=context.totalColspan
     addTableRow(tbl)
    local BelowRow=rootTable:tag('tr')
    BelowRow
         :tag('td')
         :tag('td')
             :addClass('navbox-abovebelow')
             :addClass('navbox-abovebelow')
             :addClass(getArg(prefix,"belowclass"))
             :addClass(args.belowclass)
             :cssText(getArg(prefix,"basestyle"))
             :cssText(args.basestyle)
             :cssText(getArg(prefix,"belowstyle"))
             :cssText(args.belowstyle)
             :attr('colspan', Colspan)
             :attr('colspan', getAboveBelowColspan())
             :tag('div')
             :tag('div')
                 :wikitext(addNewline(below))
                 :wikitext(addNewline(args.below))
 
    debugLog('render BelowRow End')
end
end
 
---------------------------------------------------------------
--
 
--   List rows
--数据列的方法生成器
--
local function _renderColRow_FunctionBuilder(rootTable,context,nodeFunc)
local function renderListRow(tbl, listnum)
     debugLog("_renderColRow_FunctionBuilder builded",{['context']=context})
     local row = addTableRow(tbl)
     return function(listCellDivToWrite,divNotClose)
      
        debugLog(debug.traceback('FunctionInrenderColRow'),{['context']=context,['divNotClose']=divNotClose})
    if listnum == 1 and args.imageleft then
         if not divNotClose then
         row
          listCellDivToWrite:done()--div end
            :tag('td')
          :node(
                :addClass('navbox-image')
              rootTable and nodeFunc(rootTable,context) or
                :addClass(args.imageclass)
              nodeFunc(context)
                :css('width', '0%')
          )
                :css('padding', '0px 2px 0px 0px')
          :tag('div'):done()
                :cssText(args.imageleftstyle)
        else
                :attr('rowspan', 2 * #listnums - 1)
          listCellDivToWrite:node(nodeFunc(rootTable,context))
                :tag('div')
        end
                    :wikitext(addNewline(args.imageleft))
    end
end
 
---数据行,统一的实现
local function _renderListRow(rootTable,context,OtherListFunction)
    renderSplitRow(rootTable,context)
 
    local prefix, level = context.prefix, context.level
    local listnum = context.listnum or 1
    local isFirst, isOdd = (listnum==1) ,(listnum % 2) == 1
    local ImageRowspan = 2 * context.totalRowspan - 1 + ( 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
    local insertImage=false
 
    --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
     end
     if isFirst and (not notNeedImage) then
        if imageLeft then
     if args['group' .. listnum] then
            debugLog('imageLeftRow',{['imageLeft']=imageLeft})
        local groupCell = row:tag('th')
            listRow:tag('td')--[[,{['parent']=listRow}]]
       
            :addClass('navbox-image')
        groupCell
            :addClass(getArg(prefix,"imageclass",nil,context))
              :attr('scope', 'row')
            :css('width', '0%')
              :addClass('navbox-group')
            :css('padding', '0px 2px 0px 0px')
              :addClass(args.groupclass)
            :cssText(getArg(prefix,"imageleftstyle",nil,context))
              :cssText(args.basestyle)
            :attr('rowspan', ImageRowspan)
             
            :tag('div')
        if args.groupwidth then
                :wikitext(addNewline(imageLeft))
             groupCell:css('width', args.groupwidth)
            :done() --div done
             :done() --td done
        end
        if image then
          insertImage=true
         end
         end
         
        groupCell
            :cssText(args.groupstyle)
            :cssText(args['group' .. listnum .. 'style'])
            :wikitext(args['group' .. listnum])
     end
     end
    --list pre
    local listHaveChild = checkHaveChild(prefix,'list'..listnum)
    local contentHaveChild = context.contentEqList and checkHaveChild(prefix,'content'..listnum)
    --group
    local  group, groupwidth , grouppadding , removeGroupPadding =
            getArg(prefix,"group"..listnum,nil,context)
            ,( ( group and getArg(prefix,"groupwidth") ) or nil )
            ,( getArg(prefix,"grouppadding") or '0em 0.75em;' )
            ,( getArg(prefix,'removeGroupPadding',false) and level > 1 )
    if group and not notNeedGroup 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((( groupwidth and {['width']=groupwidth}) or {}))
            :cssText(getArg(prefix,"groupstyle"))
            :cssText(getArg(prefix,'group' .. listnum .. 'style'))
        local tempEle=groupCell
        if (borderIsChild(getArg(prefix,"border"))) and (getArg(prefix,'type')==NavType.V) and (not removeGroupPadding) then --针对列式子组合的适配
        groupCell:cssText("padding-left:0em;padding-right:0em;")
        tempEle=tempEle:tag("div"):css("padding",grouppadding)
        end
        tempEle:wikitext(group)
    end
    --list
    do
        listCell=listRow:tag('td')
        if group and not notNeedGroup then
            listCell
                :css('text-align', 'left')
                :css('border-left-width', '2px')
                :css('border-left-style', 'solid')
        else
            listCell:attr('colspan', 2)
        end
        if not groupwidth then
            listCell:css('width', '100%')
        end
        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)
  listCell
            :css('padding', '0px')
            :cssText(liststyle)
            :cssText(evenOddStyle)
            :cssText(listNstyle)
            :addClass('navbox-list')
            :addClass('navbox-' .. evenOdd)
            :addClass(getArg(prefix,"listclass"))
        local tempdiv=listCell:tag('div'):css('padding', listNpadding)
        --local listHaveChild = checkHaveChild(prefix,'list'..listnum)
        --local contentHaveChild = context.contentEqList and checkHaveChild(prefix,'content'..listnum)
        if OtherListFunction then
            debugLog('ValueRow OtherListFunction',{['otherListFunctionDivNotClose']=context.otherListFunctionDivNotClose})
            --OtherListFunction(listCell)
            OtherListFunction(tempdiv,context.otherListFunctionDivNotClose)
        elseif (listHaveChild or contentHaveChild) and level<= Limit.child then
            local listKeyName='list'
            if contentHaveChild then
                listKeyName='content'
            end
            local childContext=NavboxContext.new(
                prefix..(prefix=='' and '' or '-')..listKeyName..listnum ,
                level+1 ,
                getValidType(
                    getArg(prefix..(prefix=='' and '' or '-')..
                                  listKeyName..listnum,'type'),
                    NavType.V
                )
            )
            debugLog('ValueRow NewChild',childContext)
            tempdiv:done()-- div end
                :node(p.renderNavTable(childContext))
                :tag('div'):done()
        else
            local listContent = getArg(prefix,'list'..listnum,'')..
                          ( ((not context.contentEqList ) and '') or getArg(prefix,'content' .. listnum,''))
            debugLog('ValueRow listnum',{['listnum']=listnum})
            tempdiv:wikitext(addNewline(listContent))
        end
    end
    --end
    if insertImage then
      debugLog('imageRow',{['image']=image})
      listRow:tag('td')
          :addClass('navbox-image')
          :addClass(getArg(prefix,"imageclass",nil,context))
          :css('width', '0%')
          :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,'col'..'1'..'header')
          ,getArg(prefix,'col'..'1')
          ,getArg(prefix,'col'..'1'..'footer')
    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
    context.needAddSplitRow=false
    context.splitRowcolspan=1
    --header
    if col1header then
        renderSplitRow(rootTable,context)
        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)
                    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
        renderSplitRow(rootTable,context)
        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 = trim(padding)
                test0=padding:find('^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(prefix..(prefix=='' and '' or '-')..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(colN))
                end
            end
            debugLog('ColRow Body End',{['colnum']=colnum})
        end
    end
    --footer
    if col1footer then
        renderSplitRow(rootTable,context)
        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)
                    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']=2
    _renderListRow(
        rootTable,context,
        _renderColRow_FunctionBuilder(rootTable,context,_renderColRow)
    )
      
      
     --clean up
     local listCell = row:tag('td')
    context.notNeedGroup=nil
    context['list1padding']=nil
    context['list1style']=nil
    context['otherListFunctionDivNotClose']=nil
    context['imageCellCompensate']=nil
    debugLog('renderColRow End')
end
 
---------------------------------------------------------------


--折叠行式的子Nabox
     if args['group' .. listnum] then
local function _renderSmallNavboxInCollapsibleListRow(rootTable,context)
        listCell
     local prefix, level = context.prefix, context.level
            :css('text-align', 'left')
    debugLog('_renderSmallNavboxInCollapsibleListRow',{['prefix']=prefix},{['context']=context})
            :css('border-left-width', '2px')
    local listnum = context.listnum
            :css('border-left-style', 'solid')
 
    --部分需要压制传入的样式
    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) , 'uncollapsed'
    if selected ~= nil and selected == abbrN then
      state='uncollapsed'
     else
     else
      state=getArg(prefix,'state'..listnum,'collapsed')
        listCell:attr('colspan', 2)
     end
     end
     context.state = state
      
 
     if not args.groupwidth then
     --传入renderTitleRow
        listCell:css('width', '100%')
    --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
     end
     if image then
   
    totalColspan = totalColspan + 1
    local isOdd = (listnum % 2) == 1
    context.image = image
    local rowstyle = args.evenstyle
     if isOdd then rowstyle = args.oddstyle end
    local evenOdd
    if args.evenodd == 'swap' then
        if isOdd then evenOdd = 'even' else evenOdd = 'odd' end
     else
     else
    context.notImageCell=true --CollapsibleListRow 适配
        if isOdd then evenOdd = args.evenodd or 'odd' else evenOdd = args.evenodd or 'even' end
     end
     end


     context.totalColspan = totalColspan
     listCell
    context.totalRowspan = totalRowspan
        :css('padding', '0px')
    context.splitRowcolspan = totalColspan
        :cssText(args.liststyle)
    context.lockEvenOdd=true --CollapsibleListRow 适配
        :cssText(rowstyle)
        :cssText(args['list' .. listnum .. 'style'])
        :addClass('navbox-list')
        :addClass('navbox-' .. evenOdd)
        :addClass(args.listclass)
        :tag('div')
            :css('padding', (listnum == 1 and args.list1padding) or args.listpadding or '0em 0.25em')
            :wikitext(addNewline(args['list' .. listnum]))


     debugLog('SmallNavboxInCollapsibleListRow Implement','listnum='..listnum,context)
     if listnum == 1 and args.image then
    --start
        row
    local rootTable2 = createNavTableHeader(context)
            :tag('td')
    renderTitleRow(rootTable2,context)
                :addClass('navbox-image')
    --only 1 list
                :addClass(args.imageclass)
    local otherListFunction
                :css('width', '0%')
    local listHaveChild = checkHaveChild(prefix,'list'..listnum)
                :css('padding', '0px 0px 0px 2px')
    local contentHaveChild = context.contentEqList and checkHaveChild(prefix,'content'..listnum)
                :cssText(args.imagestyle)
    if (listHaveChild or contentHaveChild) and level<= Limit.child then
                :attr('rowspan', 2 * #listnums - 1)
        local listKeyName='list'
                :tag('div')
        if contentHaveChild then
                    :wikitext(addNewline(args.image))
            listKeyName='content'
        end
        local childContext=NavboxContext.new(
                              prefix..(prefix=='' and '' or '-')..listKeyName..listnum ,
                              level+1 ,
                              getValidType(getArg(prefix..(prefix=='' and '' or '-')..listKeyName..listnum,'type'),NavType.V))
        debugLog('SmallNavboxInCollapsibleListRow NewChild',childContext)
        otherListFunction=_renderColRow_FunctionBuilder(nil,childContext,p.renderNavTable)
     end
     end
    context.noEvenOddStyle=true
    _renderListRow(rootTable2,context,otherListFunction)
    context.noEvenOddStyle=nil
    debugLog('_renderSmallNavboxInCollapsibleListRow End')
    return rootTable2:allDone()
end
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
    debugLog('renderCollapsibleListRow renderListRow',{['context']=context})
    _renderListRow(rootTable,context,context_function)
    context.noEvenOddStyle=nil
    debugLog('renderCollapsibleListRow End')
end


---------------------------------------------------------------
--
--
--  Tracking categories
--  Tracking categories
--
--
local function needsHorizontalLists(context)
    local prefix = context.prefix
    local border ,listclass ,bodyclass =
            context.border    or getArg(prefix,'border')
            ,context.listclass or getArg(prefix,'listclass')
            ,context.bodyclass or getArg(prefix,'bodyclass')


     if borderIsChild(border)
local function needsHorizontalLists()
        or getArg(prefix,'tracking') == 'no' then
     if border == 'child' or border == 'subgroup' or args.tracking == 'no' then return false end
        return false
      
     end
     local listClasses = {'plainlist', 'hlist', 'hlist hnum', 'hlist hwrap', 'hlist vcard', 'vcard hlist', 'hlist vevent', 'hlist hlist-pipe', 'hlist hlist-hyphen'}
 
     local listClasses = {'plainlist', 'hlist', 'hlist hnum', 'hlist hwrap', 'hlist vcard', 'vcard hlist', 'hlist vevent', 'hlist hlist-pipe'}
     for i, cls in ipairs(listClasses) do
     for i, cls in ipairs(listClasses) do
         if listclass == cls or bodyclass == cls then
         if args.listclass == cls or args.bodyclass == cls then
             return false
             return false
         end
         end
第1,048行: 第271行:
end
end


local function hasBackgroundColors(context)
local function hasBackgroundColors()
    local prefix = context.prefix
     return mw.ustring.match(args.titlestyle or '','background') or mw.ustring.match(args.groupstyle or '','background') or mw.ustring.match(args.basestyle or '','background')
    local titlestyle ,groupstyle ,basestyle =
            context.titlestyle or getArg(prefix,'titlestyle')
            ,context.groupstyle or getArg(prefix,'groupstyle')
            ,context.basestyle  or getArg(prefix,'basestyle')
     return mw.ustring.match(titlestyle or '','background') or
          mw.ustring.match(groupstyle or '','background') or
          mw.ustring.match(basestyle or '','background')
end
end


local function argNameAndRealTitleAreDifferent(context)
local function argNameAndRealTitleAreDifferent()
    local prefix = context.prefix
if border == 'child' or border == 'subgroup' or args.tracking == 'no' then return false end
    local border ,name =
            getArg(prefix,'border',nil,context)
            ,getArg(prefix,'name',nil,context)
    if borderIsChild(border)
        or getArg(prefix,'tracking') == 'no' then
        return false
    end


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


local function getTrackingCategories(context)
local function getTrackingCategories()
     local cats = {}
     local cats = {}
     if needsHorizontalLists(context) then table.insert(cats, '没有使用水平列表的导航框') end
     if needsHorizontalLists() then table.insert(cats, '没有使用水平列表的导航模板') end
     if hasBackgroundColors(context) then table.insert(cats, '使用背景颜色的导航框') end
     if hasBackgroundColors() then table.insert(cats, '使用背景颜色的导航模板') end
     if argNameAndRealTitleAreDifferent(context) then table.insert(cats, 'name參數和實際不同的導航框') end
     if argNameAndRealTitleAreDifferent() then table.insert(cats, 'name和实际不同的导航模板') end
     return cats
     return cats
end
end


local function renderTrackingCategories(builder,context)
local function renderTrackingCategories(builder)
     local title = mw.title.getCurrentTitle()
     local title = mw.title.getCurrentTitle()
     if title.namespace ~= 10 then return end -- not in template space
     if title.namespace ~= 10 then return end -- not in template space
     local subpage = title.subpageText
     local subpage = title.subpageText
     if subpage == 'doc' or subpage == 'sandbox' or subpage == 'testcases' then return end
     if subpage == 'doc' or subpage == 'sandbox' or subpage == 'testcases' then return end
 
   
     for i, cat in ipairs(getTrackingCategories(context)) do
     for i, cat in ipairs(getTrackingCategories()) do
         builder:wikitext('[[Category:' .. cat .. ']]')
         builder:wikitext('[[Category:' .. cat .. ']]')  
     end
     end
end
end


---------------------------------------------------------------
--
--
-- SubType Implement
--   Main navbox tables
--
--
 
local function renderMainTable()
---水平式
     local tbl = mw.html.create('table')
local function renderHorizontalTable(context)
        :attr('cellspacing', 0)
     debugLog('render Horizontal NavTable',context)
        :addClass('nowraplinks')
    local prefix, level = context.prefix, context.level
        :addClass(args.bodyclass)
 
           
    local rootTable = createNavTableHeader(context)
     if args.title and (args.state ~= 'plain' and args.state ~= 'off') then
 
        tbl
    local listnums=getListnum(prefix,Limit.horizontal.list)
            :addClass('collapsible')
 
            :addClass(args.state or 'autocollapse')
     local totalColspan=2 --title,above,below
     end
    local totalRowspan=#listnums --image,imageleft
    if getArg(prefix,"imageleft",nil,context) then totalColspan =totalColspan + 1 end
     tbl:css('border-spacing', 0)
    if getArg(prefix,"image",nil,context) then totalColspan =totalColspan + 1 end
     if border == 'subgroup' or border == 'child' or border == 'none' then
    context.totalColspan = totalColspan
        tbl
     context.totalRowspan = totalRowspan
            :addClass('navbox-subgroup')
    --context.splitRowcolspan = totalColspan
            :cssText(args.bodystyle)
 
            :cssText(args.style)
     renderTitleRow(rootTable,context)
    else -- regular navobx - bodystyle and style will be applied to the wrapper table
    renderAboveRow(rootTable,context)
        tbl
 
            :addClass('navbox-inner')
     if listnums==nil or #listnums==0 then --没有list的话,只有col
            :css('background', 'transparent')
    debugLog('render Horizontal NavTable,no list',{listnums})
            :css('color', 'inherit')
    context.listnum=1
    renderColRow(rootTable,context)
    --context.notNeedImage=true
    context.splitRowcolspan = totalColspan
    else
    debugLog('render Horizontal NavTable,have list with col',{listnums})
    for i,listnum in ipairs(listnums) do
        context.listnum=listnum
        if listnum==1 then
          --一行Col
          renderColRow(rootTable,context)
          context.notNeedImage=true
          context.splitRowcolspan = totalColspan
        else
          context.notNeedImage=nil
        end
        _renderListRow(rootTable,context)
    end
     end
     end
     renderBelowRow(rootTable,context)
     tbl:cssText(args.innerstyle)
 
    renderTrackingCategories(rootTable,context)
     renderTitleRow(tbl)
    debugLog('render Horizontal NavTable End')
     renderAboveRow(tbl)
    return rootTable
     for i, listnum in ipairs(listnums) do
end
         renderListRow(tbl, listnum)  
 
---垂直式
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
    --context.splitRowcolspan = totalColspan
 
     renderTitleRow(rootTable,context)
     renderAboveRow(rootTable,context)
     for i,listnum in ipairs(listnums) do
        context.listnum=listnum
         renderListRow(rootTable,context)
     end
     end
     renderBelowRow(rootTable,context)
     renderBelowRow(tbl)
 
      
     renderTrackingCategories(rootTable,context)
     return tbl
    debugLog('render Vertical NavTable End')
     return rootTable
end
end


---垂直折叠式
function p._navbox(navboxArgs)
local function renderVerticalCollapsibleTable(context)
     args = navboxArgs
     debugLog('render VerticalCollapsible NavTable',context)
      
     local prefix, level = context.prefix, context.level
     for k, v in pairs(args) do
 
        local listnum = ('' .. k):match('^list(%d+)$')
     local rootTable = createNavTableHeader(context)
        if listnum then table.insert(listnums, tonumber(listnum)) end
 
    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
    --context.splitRowcolspan = totalColspan
 
    renderTitleRow(rootTable,context)
    renderAboveRow(rootTable,context)
    for i,listnum in ipairs(listnums) do
        context.listnum=listnum
        renderCollapsibleListRow(rootTable,context)
     end
     end
     renderBelowRow(rootTable,context)
     table.sort(listnums)
    border = trim(args.border or args[1] or '')


     renderTrackingCategories(rootTable,context)
     -- render the main body of the navbox
     debugLog('render VerticalCollapsible NavTable End')
     local tbl = renderMainTable()
    return rootTable
end


---Type Selector
    -- render the appropriate wrapper around the navbox, depending on the border param
function p.renderNavTable(context)
     local res = mw.html.create()
     local navtype  = context.type
     if border == 'none' then
    debugLog('render NavTable')
         res:node(tbl)
    debugLog('Type='..navtype)
     elseif border == 'subgroup' or border == 'child' then
    local result
        -- We assume that this navbox is being rendered in a list cell of a parent navbox, and is
     if navtype==NavType.H then
        -- therefore inside a div with padding:0em 0.25em. We start with a </div> to avoid the
         result=renderHorizontalTable(context)
        -- padding being applied, and at the end add a <div> to balance out the parent's </div>
     elseif navtype==NavType.VC then
         res
         result=renderVerticalCollapsibleTable(context)
            :wikitext('</div>') -- mw.html 未支持 unclosed
            :node(tbl)
            :wikitext('<div>') -- mw.html 未支持 unclosed
     else
     else
         result=renderVerticalTable(context)
         res
            :tag('table')
                :attr('cellspacing', 0)
                :addClass('navbox')
                :css('border-spacing', 0)
                :cssText(args.bodystyle)
                :cssText(args.style)
                :tag('tr')
                    :tag('td')
                        :css('padding', '2px')
                        :node(tbl)
     end
     end
    debugLog('render NavTable End')
     return result
     renderTrackingCategories(res)
end
 
     return tostring(res)
--Main Funtion
function p._navbox(context)
    debugLog('Navbox mainfuntion',context)
     local prefix, level = context.prefix, context.level
    local 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())
    debugLog('Navbox mainfuntion End')
    return rootTable
end
end
 
function p.navbox(frame)
function p.navbox(frame)
     if not getArgs then
     if not getArgs then
        getArgs = require('Module:Arguments').getArgs
    getArgs = require('Module:Arguments').getArgs
     end
     end
     local modelArgs=getArgs(frame,{frameOnly=true})
     args = getArgs(frame, {wrappers = 'Template:Navbox'})
    DEBUG = modelArgs['DEBUG'] or DEBUG
    MainTemplateName=modelArgs['MainTemplateName'] or MainTemplateName
    debugLog('Navbox start')


    args = getArgs(frame, {wrappers = MainTemplateName, trim = true})
    debugLog('getArgs done,',args)
    local prefix, level = "", 1
    local NavType = getValidType(getArg(prefix,'type') or  modelArgs['type'],NavType.V)
    DEBUG = modelArgs['DEBUG'] or DEBUG
     -- Read the arguments in the order they'll be output in, to make references number in the right order.
     -- 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 _
    _ = args.title
    _ = args.above
    for i = 1, 35 do
        _ = args["group" .. tostring(i)]
        _ = args["list" .. tostring(i)]
    end   
    _ = args.below


     local L0Context=NavboxContext.new(prefix,level,NavType)
     return p._navbox(args)
    local rootNode=p._navbox(L0Context)
    debugLog('rootnode build done, Navbox end')
    return tostring(rootNode:allDone())
end
end
 
return p
return p

2024年3月30日 (六) 10:00的版本

可在模块:Navbox/doc创建此模块的帮助文档

--
-- This module will implement {{Navbox}}
--
 
local p = {}
 
local navbar = require('Module:Navbar')._navbar
local getArgs -- lazily initialized

local args
local tableRowAdded = false
local border
local listnums = {}

local function trim(s)
    return (mw.ustring.gsub(s, "^%s*(.-)%s*$", "%1"))
end

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

local function addTableRow(tbl)
    -- If any other rows have already been added, then we add a 2px gutter row.
    if tableRowAdded then
        tbl
            :tag('tr')
                :css('height', '2px')
                :tag('td')
                	:attr('colspan', 3)
    end
    
    tableRowAdded = true
    
    return tbl:tag('tr')
end

local function renderNavBar(titleCell)
    -- Depending on the presence of the navbar and/or show/hide link, we may need to add a spacer div on the left
    -- or right to keep the title centered.
    local spacerSide = nil

    if args.navbar == 'off' then
        -- No navbar, and client wants no spacer, i.e. wants the title to be shifted to the left. If there's
        -- also no show/hide link, then we need a spacer on the right to achieve the left shift.
        if args.state == 'plain' then spacerSide = 'right' end
    elseif args.navbar == 'plain' or (not args.name and mw.getCurrentFrame():getParent():getTitle() == 'Template:Navbox' and (border == 'subgroup' or border == 'child' or border == 'none')) then
        -- No navbar. Need a spacer on the left to balance out the width of the show/hide link.
        if args.state ~= 'plain' then spacerSide = 'left' end
    else
        -- Will render navbar (or error message). If there's no show/hide link, need a spacer on the right
        -- to balance out the width of the navbar.
        if args.state == 'plain' then spacerSide = 'right' end

        titleCell:wikitext(navbar{ 
            args.name, 
            mini = 1, 
            fontstyle = (args.basestyle or '') .. ';' .. (args.titlestyle or '') ..  ';background:none transparent;border:none;'
        })
    end
    
    -- Render the spacer div.
    if spacerSide then
        titleCell
            :tag('span')
                :css('float', spacerSide)
                :css('width', '8em')
                :css('font-size', '80%')
                :css('margin-' .. (spacerSide == 'left' and 'right' or 'left'), '0.5em')
                :wikitext('&nbsp;')
    end
end

--
--   Title row
--
local function renderTitleRow(tbl)
    if not args.title then return end
 
    local titleRow = addTableRow(tbl)
     
    if args.titlegroup then
        titleRow
            :tag('th')
                :attr('scope', 'row')
                :addClass('navbox-group')
                :addClass(args.titlegroupclass)
                :cssText(args.basestyle)
                :cssText(args.groupstyle)
                :cssText(args.titlegroupstyle)
                :wikitext(args.titlegroup)
    end
    
    local titleCell = titleRow:tag('th'):attr('scope', 'col')
            
    if args.titlegroup then
        titleCell
            :css('border-left', '2px solid #fdfdfd')
            :css('width', '100%')
    end
    
    local titleColspan = 2
    if args.imageleft then titleColspan = titleColspan + 1 end
    if args.image then titleColspan = titleColspan + 1 end
    if args.titlegroup then titleColspan = titleColspan - 1 end
    
    titleCell
        :cssText(args.basestyle)
        :cssText(args.titlestyle)
        :addClass('navbox-title')
        :addClass(args.titleclass)
        :attr('colspan', titleColspan)
 
    renderNavBar(titleCell)

    titleCell
         :tag('div')
             :css('font-size', '110%')
             :wikitext(addNewline(args.title))
end

--
--   Above/Below rows
--

local function getAboveBelowColspan()
    local ret = 2
    if args.imageleft then ret = ret + 1 end
    if args.image then ret = ret + 1 end
    return ret
end

local function renderAboveRow(tbl)
    if not args.above then return end

    addTableRow(tbl)
        :tag('td')
            :addClass('navbox-abovebelow')
            :addClass(args.aboveclass)
            :cssText(args.basestyle)
            :cssText(args.abovestyle)
            :attr('colspan', getAboveBelowColspan())
            :tag('div')
                :wikitext(addNewline(args.above))
end

local function renderBelowRow(tbl)
    if not args.below then return end

    addTableRow(tbl)
        :tag('td')
            :addClass('navbox-abovebelow')
            :addClass(args.belowclass)
            :cssText(args.basestyle)
            :cssText(args.belowstyle)
            :attr('colspan', getAboveBelowColspan())
            :tag('div')
                :wikitext(addNewline(args.below))
end
 
--
--   List rows
--
local function renderListRow(tbl, listnum)
    local row = addTableRow(tbl)
    
    if listnum == 1 and args.imageleft then
        row
            :tag('td')
                :addClass('navbox-image')
                :addClass(args.imageclass)
                :css('width', '0%')
                :css('padding', '0px 2px 0px 0px')
                :cssText(args.imageleftstyle)
                :attr('rowspan', 2 * #listnums - 1)
                :tag('div')
                    :wikitext(addNewline(args.imageleft))
    end
 
    if args['group' .. listnum] then
        local groupCell = row:tag('th')
        
        groupCell
               :attr('scope', 'row')
               :addClass('navbox-group')
               :addClass(args.groupclass)
               :cssText(args.basestyle)
               
        if args.groupwidth then
            groupCell:css('width', args.groupwidth)
        end
           
        groupCell
            :cssText(args.groupstyle)
            :cssText(args['group' .. listnum .. 'style'])
            :wikitext(args['group' .. listnum])
    end
    
    local listCell = row:tag('td')

    if args['group' .. listnum] then
        listCell
            :css('text-align', 'left')
            :css('border-left-width', '2px')
            :css('border-left-style', 'solid')
    else
        listCell:attr('colspan', 2)
    end
    
    if not args.groupwidth then 
        listCell:css('width', '100%')
    end
    
    local isOdd = (listnum % 2) == 1
    local rowstyle = args.evenstyle
    if isOdd then rowstyle = args.oddstyle end
 
    local evenOdd
    if args.evenodd == 'swap' then
        if isOdd then evenOdd = 'even' else evenOdd = 'odd' end
    else
        if isOdd then evenOdd = args.evenodd or 'odd' else evenOdd = args.evenodd or 'even' end
    end

    listCell
        :css('padding', '0px')
        :cssText(args.liststyle)
        :cssText(rowstyle)
        :cssText(args['list' .. listnum .. 'style'])
        :addClass('navbox-list')
        :addClass('navbox-' .. evenOdd)
        :addClass(args.listclass)
        :tag('div')
            :css('padding', (listnum == 1 and args.list1padding) or args.listpadding or '0em 0.25em')
            :wikitext(addNewline(args['list' .. listnum]))

    if listnum == 1 and args.image then
        row
            :tag('td')
                :addClass('navbox-image')
                :addClass(args.imageclass)
                :css('width', '0%')
                :css('padding', '0px 0px 0px 2px')
                :cssText(args.imagestyle)
                :attr('rowspan', 2 * #listnums - 1)
                :tag('div')
                    :wikitext(addNewline(args.image))
    end
end


--
--   Tracking categories
--

local function needsHorizontalLists()
    if border == 'child' or border == 'subgroup'  or args.tracking == 'no' then return false end
    
    local listClasses = {'plainlist', 'hlist', 'hlist hnum', 'hlist hwrap', 'hlist vcard', 'vcard hlist', 'hlist vevent', 'hlist hlist-pipe', 'hlist hlist-hyphen'}
    for i, cls in ipairs(listClasses) do
        if args.listclass == cls or args.bodyclass == cls then
            return false
        end
    end

    return true
end

local function hasBackgroundColors()
    return mw.ustring.match(args.titlestyle or '','background') or mw.ustring.match(args.groupstyle or '','background') or mw.ustring.match(args.basestyle or '','background')
end

local function argNameAndRealTitleAreDifferent()
	if border == 'child' or border == 'subgroup'  or args.tracking == 'no' then return false end

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

local function getTrackingCategories()
    local cats = {}
    if needsHorizontalLists() then table.insert(cats, '没有使用水平列表的导航模板') end
    if hasBackgroundColors() then table.insert(cats, '使用背景颜色的导航模板') end
    if argNameAndRealTitleAreDifferent() then table.insert(cats, 'name和实际不同的导航模板') end
    return cats
end

local function renderTrackingCategories(builder)
    local title = mw.title.getCurrentTitle()
    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
    
    for i, cat in ipairs(getTrackingCategories()) do
        builder:wikitext('[[Category:' .. cat .. ']]') 
    end
end

--
--   Main navbox tables
--
local function renderMainTable()
    local tbl = mw.html.create('table')
        :attr('cellspacing', 0)
        :addClass('nowraplinks')
        :addClass(args.bodyclass)
             
    if args.title and (args.state ~= 'plain' and args.state ~= 'off') then
        tbl
            :addClass('collapsible')
            :addClass(args.state or 'autocollapse')
    end
 
    tbl:css('border-spacing', 0)
    if border == 'subgroup' or border == 'child' or border == 'none' then
        tbl
            :addClass('navbox-subgroup')
            :cssText(args.bodystyle)
            :cssText(args.style)
    else -- regular navobx - bodystyle and style will be applied to the wrapper table
        tbl
            :addClass('navbox-inner')
            :css('background', 'transparent')
            :css('color', 'inherit')
    end
    tbl:cssText(args.innerstyle)
 
    renderTitleRow(tbl)
    renderAboveRow(tbl)
    for i, listnum in ipairs(listnums) do
        renderListRow(tbl, listnum) 
    end
    renderBelowRow(tbl)
    
    return tbl
end

function p._navbox(navboxArgs)
    args = navboxArgs
    
    for k, v in pairs(args) do
        local listnum = ('' .. k):match('^list(%d+)$')
        if listnum then table.insert(listnums, tonumber(listnum)) end
    end
    table.sort(listnums)
 
    border = trim(args.border or args[1] or '')

    -- render the main body of the navbox
    local tbl = renderMainTable()

    -- render the appropriate wrapper around the navbox, depending on the border param
    local res = mw.html.create()
    if border == 'none' then
        res:node(tbl)
    elseif border == 'subgroup' or border == 'child' then
        -- We assume that this navbox is being rendered in a list cell of a parent navbox, and is
        -- therefore inside a div with padding:0em 0.25em. We start with a </div> to avoid the
        -- padding being applied, and at the end add a <div> to balance out the parent's </div>
        res
            :wikitext('</div>') -- mw.html 未支持 unclosed
            :node(tbl)
            :wikitext('<div>') -- mw.html 未支持 unclosed
    else
        res
            :tag('table')
                :attr('cellspacing', 0)
                :addClass('navbox')
                :css('border-spacing', 0)
                :cssText(args.bodystyle)
                :cssText(args.style)
                :tag('tr')
                    :tag('td')
                        :css('padding', '2px')
                        :node(tbl)
    end
 
    renderTrackingCategories(res)
 
    return tostring(res)
end
 
function p.navbox(frame)
    if not getArgs then
    	getArgs = require('Module:Arguments').getArgs
    end
    args = getArgs(frame, {wrappers = 'Template:Navbox'})

    -- Read the arguments in the order they'll be output in, to make references number in the right order.
    local _
    _ = args.title
    _ = args.above
    for i = 1, 35 do
        _ = args["group" .. tostring(i)]
        _ = args["list" .. tostring(i)]
    end    
    _ = args.below

    return p._navbox(args)
end
 
return p