• Welcome to Touhou Wiki!
  • Registering is temporarily disabled. Check in our Discord server to request an account and for assistance of any kind.

Module:Navbox: Difference between revisions

From Touhou Wiki
Jump to navigation Jump to search
m (trim -> string.trim)
No edit summary
(12 intermediate revisions by 2 users not shown)
Line 2: Line 2:
-- by DennouNeko
-- by DennouNeko


-- constants
-- == Helper functions ==
local colors = {
--[[ libraries ]]
  game = {title = '#FFC9C2', above = '#FFD1CA', group = '#FFD9D2', subgroup = '#FFE1DA', dark = '#FFEEE8', background = '#FFF4EE'};
local common = require("Module:Common")
  music = {title = '#FFF3B4', above = '#FFF6C0', group = '#FFF7C8', subgroup = '#FFF8D0', dark = '#FFFBE4', background = '#FFFBEE'};
local style = require("Module:Styles")
  printwork = {title = '#DDE6FF', above = '#E1E7FF', group = '#E6E9FF', subgroup = '#EAECFF', dark = '#EDF2FF', background = '#F4F9FF'}
}


-- helper functions
local colors = style.main_colors
require("Module:Common")


local function addstyle(tbl, val)
if mw.text == nil then mw.text = require("Module:MW.text") end
  if isset(val) then
    local av = string.trim(val)
    if string.sub(av, -1) ~= ';' then av = av .. ';' end
    table.insert(tbl, av)
  end
end


--[[ Retrieve a full list of 'list#', 'list#style', 'group#' and 'group#style' arguments
    as a table of objects with 'index', 'list', 'liststyle', 'group' and 'groupstyle' fields,
    where 'index' is the number in 'list#' argument name.
    Only 'list' and 'index' are always defined. Elements that weren't specified will be empty.
    If 'list#' wasn't defined, rest of elements for that given index will be ignored.
    Key of argument matches the number in arguments name. ]]
local function scan_lists(frame)
local function scan_lists(frame)
   local idx = {}
   local idx = {}
Line 32: Line 29:


   for k,v in frame:argumentPairs() do
   for k,v in frame:argumentPairs() do
     s,e,t = string.find(k, '^group(%d+)style$')
    -- accept only parameters without leading zeros
     s,e,t = string.find(k, '^group([1-9]%d*)style$')
     if s ~= nil then groupstyle[tonumber(t)] = v end
     if s ~= nil then groupstyle[tonumber(t)] = v end


     s,e,t = string.find(k, '^list(%d+)style$')
     s,e,t = string.find(k, '^list([1-9]%d*)style$')
     if s ~= nil then liststyle[tonumber(t)] = v end
     if s ~= nil then liststyle[tonumber(t)] = v end


     s,e,t = string.find(k, '^group(%d+)$')
     s,e,t = string.find(k, '^group([1-9]%d*)$')
     if s ~= nil then group[tonumber(t)] = v end
     if s ~= nil then group[tonumber(t)] = v end


     s,e,t = string.find(k, '^list(%d+)$')
     s,e,t = string.find(k, '^list([1-9]%d*)$')
     if s ~= nil then
     if s ~= nil then
       list[tonumber(t)] = v
       list[tonumber(t)] = v
Line 50: Line 48:
   table.sort(idx)
   table.sort(idx)


   for k,v in ipairs(idx) do
   for k,v in pairs(idx) do
     local tmp = {}
     local tmp = {}
     tmp['index'] = v
     tmp['index'] = v
     tmp['list'] = list[v]
     tmp['list'] = list[v]
     if isset(group[v]) then tmp['group'] = group[v] end
     if common.isset(group[v]) then tmp['group'] = group[v] end
     if isset(liststyle[v]) then tmp['liststyle'] = liststyle[v] end
     if common.isset(liststyle[v]) then tmp['liststyle'] = liststyle[v] end
     if isset(groupstyle[v]) then tmp['groupstyle'] = groupstyle[v] end
     if common.isset(groupstyle[v]) then tmp['groupstyle'] = groupstyle[v] end
     table.insert(ret, tmp)
     ret[#ret+1] = tmp
   end
   end


Line 63: Line 61:
end
end


-- functions that create the structure
 
local function start_box(frame, border, type)
-- == Functions generating the document elements ==
   local ret = {""}
 
--[[ Generates the beginning of box, based on specified 'ttype' and 'border'. ]]
local function start_box(frame, border, ttype)
   local ret = {}
   if border == "subgroup" or border == "child" then
   if border == "subgroup" or border == "child" then
     table.insert(ret, '</div>')
     -- since we're in a cell of parent navbox, we have to close its <div> element
    ret[#ret+1] = '</div>'
   elseif border == "none" then
   elseif border == "none" then
     -- nothing to do
     -- nothing to do
   else
   else
     table.insert(ret, '<table class="navbox')
     -- new, independent navbox - create a frame around it
     if isset(frame.args['bodyclass']) then table.insert(ret, " " .. frame.args['bodyclass']) end
    ret[#ret+1] = '<table class="navbox'
     table.insert(ret, '" cellspacing="0" style="')
     if common.isset(frame.args['bodyclass']) then ret[#ret+1] = " " .. frame.args['bodyclass'] end
     if isset(colors[type]) then table.insert(ret, 'background:' .. colors[type]['background'] .. ';') end
     ret[#ret+1] = '" cellspacing="0" style="'
     table.insert(ret, 'border:1px solid #aaa; padding:1px;')
     if common.isset(colors[ttype]) then ret[#ret+1] = 'background:' .. colors[ttype]['background'] .. ';' end
    table.insert(ret, 'width:100%;vertical-align:middle;margin:auto;clear:both;font-size:88%;text-align:center;')
     -- ret[#ret+1] = 'border:1px solid #aaa; padding:1px;width:100%;vertical-align:middle;margin:auto;clear:both;font-size:88%;text-align:center;'
     addstyle(ret, frame.args['bodystyle'])
     style.add(ret, frame.args['bodystyle'])
     addstyle(ret, frame.args['style'])
     style.add(ret, frame.args['style'])
     table.insert(ret, '"><tr><td style="padding: 2px;">')
     ret[#ret+1] = '"><tr><td style="padding: 2px;">'
   end
   end


   table.insert(ret, '<table cellspacing="0" class="nowraplinks')
   -- The actual navbox table starts here
   if isset(frame.args['title']) and frame.args['state'] ~= "plain" and frame.args['state'] ~= "off" then
  ret[#ret+1] = '<table cellspacing="0" class="nowraplinks'
     --table.insert(ret, ' collapsible ')
   if common.isset(frame.args['title']) and frame.args['state'] ~= "plain" and frame.args['state'] ~= "off" then
     table.insert(ret, ' mw-collapsible ')
     --TODO: If there is support for collapsible and autocollapse, swap comments here
     if isset(frame.args['state']) then
    --ret[#ret+1] = ' collapsible '
       table.insert(ret, frame.args['state'])
     ret[#ret+1] = ' mw-collapsible '
     if common.isset(frame.args['state']) then
       ret[#ret+1] = frame.args['state']
     else
     else
       --table.insert(ret, 'autocollapse')
       --ret[#ret+1] = 'autocollapse'
       table.insert(ret, 'mw-collapsed')
       ret[#ret+1] = 'mw-collapsed'
     end
     end
   end
   end
   if border == "subgroup" or border == "child" or border == "none" then
   if border == "subgroup" or border == "child" or border == "none" then
     table.insert(ret, ' navbox-subgroup" style="')
     ret[#ret+1] = ' navbox-subgroup" style="'
     if isset(colors[type]) then table.insert(ret, 'background:' .. colors[type]['background'] .. ';') end
     if common.isset(colors[ttype]) then table.insert(ret, 'background:' .. colors[ttype]['background'] .. ';') end
     table.insert(ret, 'margin:auto;clear:both;font-size:88%;text-align:center;')
     -- ret[#ret+1] = 'margin:auto;clear:both;font-size:88%;text-align:center;width:100%;vertical-align:middle;'
    table.insert(ret, 'width:100%;vertical-align:middle;')
     ret[#ret+1] = 'width: 100%;'
     addstyle(ret, frame.args['bodystyle'])
    style.add(ret, frame.args['bodystyle'])
     addstyle(ret, frame.args['style'])
     style.add(ret, frame.args['style'])
     table.insert(ret, '">')
     ret[#ret+1] = '">'
   else
   else
     table.insert(ret, '" style="width:100%;background:transparent;color:inherit;">')
     ret[#ret+1] = '" style="width:100%;background:transparent;color:inherit;">'
   end
   end


Line 108: Line 112:
end
end


local function end_box(frame, border, type)
--[[ Finalizes the box, based on specified 'ttype' and 'border' ]]
local function end_box(frame, border, ttype)
   local ret = {""}
   local ret = {""}
   table.insert(ret, '</table>')
   ret[#ret+1] = '</table>'
   if border == "subgroup" or border == "child" then
   if border == "subgroup" or border == "child" then
     table.insert(ret, '<div>')
     -- open a <div>, since we closed one when starting this child navbox
    ret[#ret+1] = '<div>'
   elseif border == "none" then
   elseif border == "none" then
     -- nothing to do
     -- nothing to do
   else
   else
     table.insert(ret, '</td></tr></table>')
     -- close the table we started as a frame
    ret[#ret+1] = '</td></tr></table>'
   end
   end
   return table.concat(ret)
   return table.concat(ret)
end
end


local function build_title(frame, border, type)
--[[ Generates the title row: 'v(iew) • d(iscuss) • e(dit)' + title + '[Expand]'/'[Collapse]' buttons. ]]
local function build_title(frame, border, ttype)
   local ret = {""}
   local ret = {""}
   if not isset(frame.args['title']) then return '' end
   if not common.isset(frame.args['title']) then return '' end


   table.insert(ret, '<tr>')
   table.insert(ret, '<tr>')
   if isset(frame.args['titlegroup']) then
   if common.isset(frame.args['titlegroup']) then
     table.insert(ret, '<td class="navbox-group" style="')
     -- in case that there's a group for title
     if isset(colors[type]) then table.insert(ret, 'background:' .. colors[type]['group'] .. ';') end
    ret[#ret+1] = '<td class="navbox-group" style="'
     table.insert(ret, 'padding-left:1em;padding-right:1em;white-space:nowrap;text-align:right;')
     if common.isset(colors[ttype]) then ret[#ret+1] = 'background:' .. colors[ttype]['group'] .. ';' end
     addstyle(ret, frame.args['basestyle'])
     ret[#ret+1] = 'padding-left:1em;padding-right:1em;white-space:nowrap;text-align:right;'
     addstyle(ret, frame.args['groupstyle'])
     style.add(ret, frame.args['basestyle'])
     addstyle(ret, frame.args['titlegroupstyle'])
     style.add(ret, frame.args['groupstyle'])
     table.insert(ret, '">')
     style.add(ret, frame.args['titlegroupstyle'])
     table.insert(ret, frame.args['titlegroup'])
     ret[#ret+1] = '">\n'
     table.insert(ret, '</td>')
     ret[#ret+1] = frame.args['titlegroup']
     ret[#ret+1] = '</td>'


     table.insert(ret, '<th style="border-left:2px solid #fdfdfd;width:100%;')
     ret[#ret+1] = '<th style="border-left:2px solid '
    ret[#ret+1] = common.cv(common.isset(colors[ttype]), colors[ttype]['background'], '#fdfdfd')
    ret[#ret+1] = ';width:100%;'
   else
   else
    -- no group for title
     table.insert(ret, '<th style="')
     table.insert(ret, '<th style="')
   end
   end
   if isset(colors[type]) then table.insert(ret, 'background:' .. colors[type]['title'] .. ';') end
   if common.isset(colors[ttype]) then ret[#ret+1] = 'background:' .. colors[ttype]['title'] .. ';' end
   table.insert(ret, 'text-align:center;')
   ret[#ret+1] = 'text-align:center;'
   addstyle(ret, frame.args['basestyle'])
   style.add(ret, frame.args['basestyle'])
   addstyle(ret, frame.args['titlestyle'])
   style.add(ret, frame.args['titlestyle'])
   table.insert(ret, '"')
   ret[#ret+1] = '"'


   local cs = 2
  -- calculate the colspan for title
   if isset(frame.args['imageleft']) then cs = cs + 1 end
   local cs = 2 -- 2 because each list element with group occupies 2 columns
   if isset(frame.args['image']) then cs = cs + 1 end
   if common.isset(frame.args['imageleft']) then cs = cs + 1 end
   if isset(frame.args['titlegroup']) then cs = cs - 1 end
   if common.isset(frame.args['image']) then cs = cs + 1 end
   table.insert(ret, ' colspan = "' .. cs .. '"')
   if common.isset(frame.args['titlegroup']) then cs = cs - 1 end -- if there was a titlegroup, it occupies one cell already
 
   ret[#ret+1] = ' colspan = "' .. cs .. '"'
   table.insert(ret, ' class="navbox-title"')
   ret[#ret+1] = ' class="navbox-title">'
  table.insert(ret, '>')


  -- add navbars and/or padding when needed
   if frame.args['navbar'] == "plain" or frame.args['navbar'] == "off" or border == "subgroup" or border == "child" or border == "none" then
   if frame.args['navbar'] == "plain" or frame.args['navbar'] == "off" or border == "subgroup" or border == "child" or border == "none" then
     if frame.args['navbar'] == "off" then
     if frame.args['navbar'] == "off" then
       if frame.args['state'] == "plain" then table.insert(ret, '<div style="float:right;width:6em;">&nbsp;</div>') end
       if frame.args['state'] == "plain" then ret[#ret+1] = '<div style="float:right;width:6em;">&nbsp;</div>' end
     else
     else
       if frame.args['state'] ~= "plain" then table.insert(ret, '<div style="float:left; width:6em;text-align:left;">&nbsp;</div>') end
       if frame.args['state'] ~= "plain" then ret[#ret+1] = '<div style="float:left; width:6em;text-align:left;">&nbsp;</div>' end
     end
     end
   else
   else
     if frame.args['state'] == "plain" then table.insert(ret, '<div style="float:right;width:6em;">&nbsp;</div>') end
     if frame.args['state'] == "plain" then ret[#ret+1] = '<div style="float:right;width:6em;">&nbsp;</div>' end
    table.insert(ret, '<div style="float:left; width:6em;text-align:left;">')


    ret[#ret+1] = '<div style="float:left; width:6em;text-align:left;">'
     if frame.args['name'] ~= nil then
     if frame.args['name'] ~= nil then
       local args = {}
       local args = {}
       args[#args+1] = frame.args['name']
       args[#args+1] = frame.args['name']
      args['mini'] = '1'


      -- TODO: Build the navbar without using external template?
       local q = {""}
       local q = {""}
       table.insert(q, 'text-align:left;')
       q[#q+1] = 'text-align:left;'
       addstyle(q, frame.args['basestyle'])
       style.add(q, frame.args['basestyle'])
       addstyle(q, frame.args['titlestyle'])
       style.add(q, frame.args['titlestyle'])
       table.insert(q, 'border:none;')
       q[#q+1] = 'border:none;'
       args['fontstyle'] = table.concat(q)
       args['fontstyle'] = table.concat(q)


       args['mini'] = '1'
       ret[#ret+1] = frame:expandTemplate{title = 'Navbar', args = args}
 
      table.insert(ret, frame:expandTemplate{title = 'Navbar', args = args})
     else
     else
       table.insert(ret, '&nbsp;')
       ret[#ret+1] = '&nbsp;'
       table.insert(ret, '[[Category:Navboxes without name]]')
       ret[#ret+1] = '[[Category:Navboxes without name]]'
     end
     end
    ret[#ret+1] = '</div>'
  end
  -- the title starts here
  ret[#ret+1] = '<span'
  if common.isset(frame.args['titleclass']) then ret[#ret+1] = ' class="' .. frame.args['titleclass'] .. '"' end
  ret[#ret+1] = ' style="font-size:' .. common.cv((border == "subgroup" or border == "child" or border == "none"), '100%', '110%') .. ';">\n'


     table.insert(ret, '</div>')
  ret[#ret+1] = frame.args['title']
  end
 
  ret[#ret+1] = '</span>'
  ret[#ret+1] = '</th></tr>'
  return table.concat(ret)
end
 
--[[ Generates the 'above' and 'below' rows.
    Returns the generated row and updated 'sep' value (if separation is going to be needed). ]]
local function build_above_below(frame, border, ttype, text, rstyle, sep)
  local ret = {''}
  if common.isset(text) then
     if sep then -- if separation is needed
      table.insert(ret, '<tr style="height: 2px;"><td></td></tr>')
    end


  table.insert(ret, '<span')
    -- start the 'above' or 'below' row
  if isset(frame.args['titleclass']) then table.insert(ret, ' class="' .. frame.args['titleclass'] .. '"') end
    ret[#ret+1] = '<tr>'
  table.insert(ret, ' style="font-size:')
    ret[#ret+1] = '<td class="navbox-abovebelow" style="'
  if border == "subgroup" or border == "child" or border == "none" then
    if common.isset(colors[ttype]) then
     table.insert(ret, '100%')
      -- both above and below share same default color from 'colors' table
  else
      ret[#ret+1] = 'background:' .. common.cv((border ~= "subgroup" and border ~= "child"), colors[ttype]['above'], colors[ttype]['group']) .. ';'
     table.insert(ret, '110%')
    end
  end
    ret[#ret+1] = 'padding-left:1em;padding-right:1em;text-align:center;'
  table.insert(ret, ';">')
     style.add(ret, frame.args['basestyle'])
     style.add(ret, rstyle)
    ret[#ret+1] = '"'


  table.insert(ret, frame.args['title'])
    -- calculate and add the colspan (always full table width)
    local cs = 2
    if common.isset(frame.args['imageleft']) then cs = cs + 1 end
    if common.isset(frame.args['image']) then cs = cs + 1 end
    ret[#ret+1] = ' colspan="' .. cs .. '">\n'


  table.insert(ret, '</span>')
    -- row content
    ret[#ret+1] = text


  table.insert(ret, '</th></tr>')
    ret[#ret+1] = '</td></tr>'
   return table.concat(ret)
    sep = true -- now we're going to need separation
  end
   return table.concat(ret),sep
end
end


local function build_row(frame, k, group, list, groupstyle, liststyle, border, type)
--[[ Generates a single row of the list. ]]
local function build_row(frame, border, ttype, k, group, list, groupstyle, liststyle)
   local ret = {""}
   local ret = {""}
   if isset(group) then
   if common.isset(group) then
     table.insert(ret, '<td class="navbox-group" style="')
     -- there's a group name for current list, so add a cell for it
     if border ~= "subgroup" and border ~= "child" then
    ret[#ret+1] = '<td class="navbox-group" style="'
      if isset(colors[type]) then table.insert(ret, 'background:' .. colors[type]['group'] .. ';') end
     if common.isset(colors[ttype]) then
    else
      ret[#ret+1] = 'background:' .. common.cv((border ~= "subgroup" and border ~= "child"), colors[ttype]['group'], colors[ttype]['subgroup']) .. ';'
      if isset(colors[type]) then table.insert(ret, 'background:' .. colors[type]['subgroup'] .. ';') end
     end
     end
     table.insert(ret, 'padding-left:1em; padding-right:1em; white-space:nowrap; text-align:right;')
     ret[#ret+1] = 'padding-left:1em; padding-right:1em; white-space:nowrap; text-align:right;'
     addstyle(ret, frame.args['basestyle'])
     style.add(ret, frame.args['basestyle'])
     if isset(frame.args['groupwidth']) then table.insert(ret, 'width:' .. frame.args['groupwidth'] .. ';') end
     if common.isset(frame.args['groupwidth']) then ret[#ret+1] = 'width:' .. frame.args['groupwidth'] .. ';' end
     addstyle(ret, frame.args['groupstyle'])
     style.add(ret, frame.args['groupstyle'])
     addstyle(ret, groupstyle)
     style.add(ret, groupstyle)
     table.insert(ret, '"><div style="padding:0;">' .. group .. '</div></td>')
     ret[#ret+1] = '">'
     table.insert(ret, '<td style="text-align:left;border-left-width:2px;border-left-style:solid;')
    ret[#ret+1] = '<div style="padding:0;">\n'
    ret[#ret+1] = group
    ret[#ret+1] = '</div></td>'
 
    -- start the content cell
     ret[#ret+1] = '<td style="text-align:left;border-left-width:2px;border-left-style:solid;'
   else
   else
     table.insert(ret, '<td colspan=2 style="')
     -- no group name, start the content already
    ret[#ret+1] = '<td colspan=2 style="'
   end
   end
   -- a bit tricky, but it works as XOR
   -- a bit tricky, but this works as XOR
   if (frame.args['evenodd'] == "swap") ~= ((k % 2) == 0) then
   if (frame.args['evenodd'] == "swap") ~= ((k % 2) == 0) then
     if isset(colors[type]) then table.insert(ret, 'background:' .. colors[type]['dark'] .. ';') end
     if common.isset(colors[ttype]) then ret[#ret+1] = 'background:' .. colors[ttype]['dark'] .. ';' end
   else
   else
     table.insert(ret, 'background:transparent;')
     ret[#ret+1] = 'background:transparent;'
   end
   end
 
   if not common.isset(frame.args['groupwidth']) then ret[#ret+1] = 'width:100%;' end
   if not isset(frame.args['groupwidth']) then table.insert(ret, 'width:100%;') end
   ret[#ret+1] = 'padding: 0;'
   table.insert(ret, 'padding: 0;')
   style.add(ret, frame.args['liststyle'])
   addstyle(ret, frame.args['liststyle'])
   style.add(ret, common.cv((frame.args['evenodd'] == "swap") ~= ((k % 2) == 0), frame.args['evenstyle'], frame.args['oddstyle']))
   if (frame.args['evenodd'] == "swap") ~= ((k % 2) == 0) then
   style.add(ret, liststyle)
    addstyle(ret, frame.args['evenstyle'])
   ret[#ret+1] = '" class="navbox-list ' .. common.cv((frame.args['evenodd'] == "swap") ~= ((k % 2) == 0), 'navbox-even', 'navbox-odd') .. '">'
  else
    addstyle(ret, frame.args['oddstyle'])
   end
  addstyle(ret, liststyle)
   table.insert(ret, '" class="navbox-list')
  if (frame.args['evenodd'] == "swap") ~= ((k % 2) == 0) then
    table.insert(ret, ' navbox-even')
  else
    table.insert(ret, ' navbox-odd')
  end
  table.insert(ret, '">')


   table.insert(ret, '<div style="padding:')
   -- add the <div> with content (same <div> that child navbox has to close when starting table)
   if isset(frame.args['list' .. k .. 'padding']) then
  ret[#ret+1] = '<div style="padding:'
     table.insert(ret, frame.args['list' .. k .. 'padding'])
   if common.isset(frame.args['list' .. k .. 'padding']) then
   elseif isset(frame.args['listpadding']) then
     ret[#ret+1] = frame.args['list' .. k .. 'padding']
     table.insert(ret, frame.args['listpadding'])
   elseif common.isset(frame.args['listpadding']) then
     ret[#ret+1] = frame.args['listpadding']
   else
   else
     table.insert(ret, '0em 0.25em')
     ret[#ret+1] = '0em 0.25em'
   end
   end
   table.insert(ret, ';">\n' .. list .. '</div>')
   ret[#ret+1] = ';">\n'
  table.insert(ret, '</td>')
  ret[#ret+1] = list
  ret[#ret+1] = '</div></td>'
   return table.concat(ret)
   return table.concat(ret)
end
end


local function build_body(frame, border, type)
--[[ Generates the "body" of table (everything below title) ]]
   local ret = {""}
local function build_body(frame, border, ttype, lists)
   local sep = isset(frame.args['title'])
   local ret = {}
   local sep = common.isset(frame.args['title']) -- if there was a title, we have to add separation for first row
  local imgs = true -- add images if present
  local irows = common.cv( (#lists > 0), (2 * #lists - 1), 1 )


   local lists = scan_lists(frame)
   -- aff the 'above' row
  ret[#ret+1],sep = build_above_below(frame, border, ttype, frame.args['above'], frame.args['abovestyle'], sep)
    
    
   if isset(frame.args['above']) then
   for k,v in pairs(lists) do
     if sep then
     if sep then -- add separation if needed
      table.insert(ret, '<tr style="height: 2px;"><td></td></tr>')
       ret[#ret+1] = '<tr style="height: 2px;"><td></td></tr>'
    end
    sep = true
    table.insert(ret, '<tr><td class="navbox-abovebelow" style="')
    if isset(colors[type]) then
       if border ~= "subgroup" and border ~= "child" then
        table.insert(ret, 'background:' .. colors[type]['above'] .. ';')
      else
        table.insert(ret, 'background:' .. colors[type]['group'] .. ';')
      end
    end
    table.insert(ret, 'padding-left:1em;padding-right:1em;text-align:center;')
    addstyle(ret, frame.args['basestyle'])
    addstyle(ret, frame.args['abovestyle'])
    table.insert(ret, '"')
 
    local cs = 2
    if isset(frame.args['imageleft']) then cs = cs + 1 end
    if isset(frame.args['image']) then cs = cs + 1 end
    table.insert(ret, ' colspan="' .. cs .. '"')
    table.insert(ret, '>' .. frame.args['above'] .. '</td></tr>')
  end
 
  local imgs = true
  local irows = 1
  if #lists > 0 then irows = 2 * #lists - 1 end
 
  for k,v in ipairs(lists) do
    if sep then
      table.insert(ret, '<tr style="height: 2px;"><td></td></tr>')
     end
     end
    sep = true


     table.insert(ret, '<tr>')
     table.insert(ret, '<tr>')


    -- add left image (if wasn't added yet and is present)
     if imgs then
     if imgs then
       if isset(frame.args['imageleft']) then
       if common.isset(frame.args['imageleft']) then
         table.insert(ret, '<td style="width:0%;padding:0px 2px 0px 0px;')
         ret[#ret+1] = '<td style="width:0%;padding:0px 2px 0px 0px;'
         addstyle(ret, frame.args['imageleftstyle'])
         style.add(ret, frame.args['imageleftstyle'])
         table.insert(ret, '"')
         ret[#ret+1] = '" rowspan="' .. irows .. '">' .. frame.args['imageleft'] .. '</td>'
        table.insert(ret, ' rowspan="' .. irows .. '"')
        table.insert(ret, '>' .. frame.args['imageleft'] .. '</td>')
       end
       end
     end
     end
   
    table.insert(ret, build_row(frame, v['index'], v['group'], v['list'], v['groupstyle'], v['liststyle'], border, type))


    -- add the list content
    ret[#ret+1] = build_row(frame, border, ttype, v['index'], v['group'], v['list'], v['groupstyle'], v['liststyle'])
    -- add right image (if wasn't added yet and is present)
     if imgs then
     if imgs then
       if isset(frame.args['image']) then
       if common.isset(frame.args['image']) then
         table.insert(ret, '<td style="width:0%;padding:0px 2px 0px 0px;')
         ret[#ret+1] = '<td style="width:0%;padding:0px 0px 0px 2px;'
         addstyle(ret, frame.args['imagestyle'])
         style.add(ret, frame.args['imagestyle'])
         table.insert(ret, '"')
         ret[#ret+1] = '" rowspan="' .. irows .. '">' .. frame.args['image'] .. '</td>'
        table.insert(ret, ' rowspan="' .. irows .. '"')
        table.insert(ret, '>' .. frame.args['image'] .. '</td>')
       end
       end


      -- mark that images were added already
       imgs = false
       imgs = false
     end
     end
     table.insert(ret, '</tr>')
 
     ret[#ret+1] = '</tr>'
    sep = true -- now the separation is going to be needed for sure
   end
   end


   if isset(frame.args['below']) then
   ret[#ret+1],sep = build_above_below(frame, border, ttype, frame.args['below'], frame.args['belowstyle'], sep)
    if sep then
      table.insert(ret, '<tr style="height: 2px;"><td></td></tr>')
    end
    sep = true
    table.insert(ret, '<tr><td class="navbox-abovebelow" style="')
    if isset(colors[type]) then
      if border ~= "subgroup" and border ~= "child" then
        table.insert(ret, 'background:' .. colors[type]['above'] .. ';')
      else
        table.insert(ret, 'background:' .. colors[type]['group'] .. ';')
      end
    end
    table.insert(ret, 'padding-left:1em;padding-right:1em;text-align:center;')
    addstyle(ret, frame.args['basestyle'])
    addstyle(ret, frame.args['belowstyle'])
    table.insert(ret, '"')
 
    local cs = 2
    if isset(frame.args['imageleft']) then cs = cs + 1 end
    if isset(frame.args['image']) then cs = cs + 1 end
    table.insert(ret, ' colspan="' .. cs .. '"')
    table.insert(ret, '>' .. frame.args['below'] .. '</td></tr>')
  end


   return table.concat(ret)
   return table.concat(ret)
end
end


-- exported functions
-- == Exported functions ==
--[[ Generates and returns the whole navbox table. ]]
local function buildNavbox(frame)
local function buildNavbox(frame)
   local template = {""}
   local template = {}
   local border = ""
   local border = ""
   local type = ""
   local ttype = ""


   if isset(frame.args['border']) then
   if common.isset(frame.args['border']) then
     border = frame.args['border']
     border = frame.args['border']
   elseif isset(frame.args[1]) then
   elseif common.isset(frame.args[1]) then
     border = string.trim(frame.args[1])
     border = mw.text.trim(frame.args[1])
   end
   end


   if isset(frame.args['type']) then
   if common.isset(frame.args['type']) then
     type = frame.args['type']
     ttype = frame.args['type']
   end
   end


   -- TODO: filtering of border and type values?
   -- TODO: filtering of border and type values?


   table.insert(template, start_box(frame, border, type))
   -- prepare the data first
   table.insert(template, build_title(frame, border, type))
  local lists = scan_lists(frame)
   table.insert(template, build_body(frame, border, type))
 
   table.insert(template, end_box(frame, border, type))
  -- build the content 
  template[#template+1] = start_box(frame, border, ttype)
   template[#template+1] = build_title(frame, border, ttype)
   template[#template+1] = build_body(frame, border, ttype, lists)
   template[#template+1] = end_box(frame, border, ttype)


   return table.concat(template)
   return table.concat(template)
end
end


local function buildNavboxTemplate(frame)
-- [[ Workaround for the "Navbox subgroup" template ]]
   return buildNavbox(frame:getParent())
local function buildNavboxSubgroup(frame)
  if not common.isset(frame.args['border']) then frame.args['border'] = 'child' end
 
  -- TODO: add/modify/remove other params?
 
  -- call the main function
   return buildNavbox(frame)
end
end


--[[ Mostly for debugging, generates and returns a table of sets of colors
    and the values in cells with colors used as backgrounds. ]]
local function buildColorTable(frame)
local function buildColorTable(frame)
   local ret = {""}
   local ret = {""}
Line 412: Line 416:
return {
return {
   ['buildNavbox'] = buildNavbox,
   ['buildNavbox'] = buildNavbox,
   ['buildNavboxTemplate'] = buildNavboxTemplate,
   ['buildNavboxTemplate'] = function(frame) return buildNavbox(frame:getParent()) end, -- for wrappers
  ['buildNavboxSubgroup'] = buildNavboxSubgroup,
  ['buildNavboxSubgroupTemplate'] = function(frame) return buildNavboxSubgroup(frame:getParent()) end, -- for wrappers
   ['buildColorTable'] = buildColorTable
   ['buildColorTable'] = buildColorTable
}
}
-- [[Category:Lua Scripts|{{PAGENAME}}]]

Revision as of 02:08, 12 March 2015

Documentation for this module may be created at Module:Navbox/doc

-- lua port of [[Template:Navbox]]
-- by DennouNeko

-- == Helper functions ==
--[[ libraries ]]
local common = require("Module:Common")
local style = require("Module:Styles")

local colors = style.main_colors

if mw.text == nil then mw.text = require("Module:MW.text") end

--[[ Retrieve a full list of 'list#', 'list#style', 'group#' and 'group#style' arguments
     as a table of objects with 'index', 'list', 'liststyle', 'group' and 'groupstyle' fields,
     where 'index' is the number in 'list#' argument name.
     Only 'list' and 'index' are always defined. Elements that weren't specified will be empty.
     If 'list#' wasn't defined, rest of elements for that given index will be ignored.
     Key of argument matches the number in arguments name. ]]
local function scan_lists(frame)
  local idx = {}
  local list = {}
  local group = {}
  local liststyle = {}
  local groupstyle = {}

  local ret = {}

  local s,e,t

  for k,v in frame:argumentPairs() do
    -- accept only parameters without leading zeros
    s,e,t = string.find(k, '^group([1-9]%d*)style$')
    if s ~= nil then groupstyle[tonumber(t)] = v end

    s,e,t = string.find(k, '^list([1-9]%d*)style$')
    if s ~= nil then liststyle[tonumber(t)] = v end

    s,e,t = string.find(k, '^group([1-9]%d*)$')
    if s ~= nil then group[tonumber(t)] = v end

    s,e,t = string.find(k, '^list([1-9]%d*)$')
    if s ~= nil then
      list[tonumber(t)] = v
      idx[#idx+1] = tonumber(t)
    end
  end

  table.sort(idx)

  for k,v in pairs(idx) do
    local tmp = {}
    tmp['index'] = v
    tmp['list'] = list[v]
    if common.isset(group[v]) then tmp['group'] = group[v] end
    if common.isset(liststyle[v]) then tmp['liststyle'] = liststyle[v] end
    if common.isset(groupstyle[v]) then tmp['groupstyle'] = groupstyle[v] end
    ret[#ret+1] = tmp
  end

  return ret
end


-- == Functions generating the document elements ==

--[[ Generates the beginning of box, based on specified 'ttype' and 'border'. ]]
local function start_box(frame, border, ttype)
  local ret = {}
  if border == "subgroup" or border == "child" then
    -- since we're in a cell of parent navbox, we have to close its <div> element
    ret[#ret+1] = '</div>'
  elseif border == "none" then
    -- nothing to do
  else
    -- new, independent navbox - create a frame around it
    ret[#ret+1] = '<table class="navbox'
    if common.isset(frame.args['bodyclass']) then ret[#ret+1] = " " .. frame.args['bodyclass'] end
    ret[#ret+1] = '" cellspacing="0" style="'
    if common.isset(colors[ttype]) then ret[#ret+1] = 'background:' .. colors[ttype]['background'] .. ';' end
    -- ret[#ret+1] = 'border:1px solid #aaa; padding:1px;width:100%;vertical-align:middle;margin:auto;clear:both;font-size:88%;text-align:center;'
    style.add(ret, frame.args['bodystyle'])
    style.add(ret, frame.args['style'])
    ret[#ret+1] = '"><tr><td style="padding: 2px;">'
  end

  -- The actual navbox table starts here
  ret[#ret+1] = '<table cellspacing="0" class="nowraplinks'
  if common.isset(frame.args['title']) and frame.args['state'] ~= "plain" and frame.args['state'] ~= "off" then
    --TODO: If there is support for collapsible and autocollapse, swap comments here
    --ret[#ret+1] = ' collapsible '
    ret[#ret+1] = ' mw-collapsible '
    if common.isset(frame.args['state']) then
      ret[#ret+1] = frame.args['state']
    else
      --ret[#ret+1] = 'autocollapse'
      ret[#ret+1] = 'mw-collapsed'
    end
  end
  if border == "subgroup" or border == "child" or border == "none" then
    ret[#ret+1] = ' navbox-subgroup" style="'
    if common.isset(colors[ttype]) then table.insert(ret, 'background:' .. colors[ttype]['background'] .. ';') end
    -- ret[#ret+1] = 'margin:auto;clear:both;font-size:88%;text-align:center;width:100%;vertical-align:middle;'
    ret[#ret+1] = 'width: 100%;'
    style.add(ret, frame.args['bodystyle'])
    style.add(ret, frame.args['style'])
    ret[#ret+1] = '">'
  else
    ret[#ret+1] = '" style="width:100%;background:transparent;color:inherit;">'
  end

  return table.concat(ret)
end

--[[ Finalizes the box, based on specified 'ttype' and 'border' ]]
local function end_box(frame, border, ttype)
  local ret = {""}
  ret[#ret+1] = '</table>'
  if border == "subgroup" or border == "child" then
    -- open a <div>, since we closed one when starting this child navbox
    ret[#ret+1] = '<div>'
  elseif border == "none" then
    -- nothing to do
  else
    -- close the table we started as a frame
    ret[#ret+1] = '</td></tr></table>'
  end
  return table.concat(ret)
end

--[[ Generates the title row: 'v(iew) • d(iscuss) • e(dit)' + title + '[Expand]'/'[Collapse]' buttons. ]]
local function build_title(frame, border, ttype)
  local ret = {""}
  if not common.isset(frame.args['title']) then return '' end

  table.insert(ret, '<tr>')
  if common.isset(frame.args['titlegroup']) then
    -- in case that there's a group for title
    ret[#ret+1] = '<td class="navbox-group" style="'
    if common.isset(colors[ttype]) then ret[#ret+1] = 'background:' .. colors[ttype]['group'] .. ';' end
    ret[#ret+1] = 'padding-left:1em;padding-right:1em;white-space:nowrap;text-align:right;'
    style.add(ret, frame.args['basestyle'])
    style.add(ret, frame.args['groupstyle'])
    style.add(ret, frame.args['titlegroupstyle'])
    ret[#ret+1] = '">\n'
    ret[#ret+1] = frame.args['titlegroup']
    ret[#ret+1] = '</td>'

    ret[#ret+1] = '<th style="border-left:2px solid '
    ret[#ret+1] = common.cv(common.isset(colors[ttype]), colors[ttype]['background'], '#fdfdfd')
    ret[#ret+1] = ';width:100%;'
  else
    -- no group for title
    table.insert(ret, '<th style="')
  end
  if common.isset(colors[ttype]) then ret[#ret+1] = 'background:' .. colors[ttype]['title'] .. ';' end
  ret[#ret+1] = 'text-align:center;'
  style.add(ret, frame.args['basestyle'])
  style.add(ret, frame.args['titlestyle'])
  ret[#ret+1] = '"'

  -- calculate the colspan for title
  local cs = 2 -- 2 because each list element with group occupies 2 columns
  if common.isset(frame.args['imageleft']) then cs = cs + 1 end
  if common.isset(frame.args['image']) then cs = cs + 1 end
  if common.isset(frame.args['titlegroup']) then cs = cs - 1 end -- if there was a titlegroup, it occupies one cell already
  ret[#ret+1] = ' colspan = "' .. cs .. '"'
  ret[#ret+1] = ' class="navbox-title">'

  -- add navbars and/or padding when needed
  if frame.args['navbar'] == "plain" or frame.args['navbar'] == "off" or border == "subgroup" or border == "child" or border == "none" then
    if frame.args['navbar'] == "off" then
      if frame.args['state'] == "plain" then ret[#ret+1] = '<div style="float:right;width:6em;">&nbsp;</div>' end
    else
      if frame.args['state'] ~= "plain" then ret[#ret+1] = '<div style="float:left; width:6em;text-align:left;">&nbsp;</div>' end
    end
  else
    if frame.args['state'] == "plain" then ret[#ret+1] = '<div style="float:right;width:6em;">&nbsp;</div>' end

    ret[#ret+1] = '<div style="float:left; width:6em;text-align:left;">'
    if frame.args['name'] ~= nil then
      local args = {}
      args[#args+1] = frame.args['name']
      args['mini'] = '1'

      -- TODO: Build the navbar without using external template?
      local q = {""}
      q[#q+1] = 'text-align:left;'
      style.add(q, frame.args['basestyle'])
      style.add(q, frame.args['titlestyle'])
      q[#q+1] = 'border:none;'
      args['fontstyle'] = table.concat(q)

      ret[#ret+1] = frame:expandTemplate{title = 'Navbar', args = args}
    else
      ret[#ret+1] = '&nbsp;'
      ret[#ret+1] = '[[Category:Navboxes without name]]'
    end
    ret[#ret+1] = '</div>'
  end

  -- the title starts here
  ret[#ret+1] = '<span'
  if common.isset(frame.args['titleclass']) then ret[#ret+1] = ' class="' .. frame.args['titleclass'] .. '"' end
  ret[#ret+1] = ' style="font-size:' .. common.cv((border == "subgroup" or border == "child" or border == "none"), '100%', '110%') .. ';">\n'

  ret[#ret+1] = frame.args['title']
  
  ret[#ret+1] = '</span>'
  ret[#ret+1] = '</th></tr>'
  return table.concat(ret)
end

--[[ Generates the 'above' and 'below' rows.
     Returns the generated row and updated 'sep' value (if separation is going to be needed). ]]
local function build_above_below(frame, border, ttype, text, rstyle, sep)
  local ret = {''}
  if common.isset(text) then
    if sep then -- if separation is needed
      table.insert(ret, '<tr style="height: 2px;"><td></td></tr>')
    end

    -- start the 'above' or 'below' row
    ret[#ret+1] = '<tr>'
    ret[#ret+1] = '<td class="navbox-abovebelow" style="'
    if common.isset(colors[ttype]) then
      -- both above and below share same default color from 'colors' table
      ret[#ret+1] = 'background:' .. common.cv((border ~= "subgroup" and border ~= "child"), colors[ttype]['above'], colors[ttype]['group']) .. ';'
    end
    ret[#ret+1] = 'padding-left:1em;padding-right:1em;text-align:center;'
    style.add(ret, frame.args['basestyle'])
    style.add(ret, rstyle)
    ret[#ret+1] = '"'

    -- calculate and add the colspan (always full table width)
    local cs = 2
    if common.isset(frame.args['imageleft']) then cs = cs + 1 end
    if common.isset(frame.args['image']) then cs = cs + 1 end
    ret[#ret+1] = ' colspan="' .. cs .. '">\n'

    -- row content
    ret[#ret+1] = text

    ret[#ret+1] = '</td></tr>'
    sep = true -- now we're going to need separation
  end
  return table.concat(ret),sep
end

--[[ Generates a single row of the list. ]]
local function build_row(frame, border, ttype, k, group, list, groupstyle, liststyle)
  local ret = {""}
  if common.isset(group) then
    -- there's a group name for current list, so add a cell for it
    ret[#ret+1] = '<td class="navbox-group" style="'
    if common.isset(colors[ttype]) then 
      ret[#ret+1] = 'background:' .. common.cv((border ~= "subgroup" and border ~= "child"), colors[ttype]['group'], colors[ttype]['subgroup']) .. ';'
    end
    ret[#ret+1] = 'padding-left:1em; padding-right:1em; white-space:nowrap; text-align:right;'
    style.add(ret, frame.args['basestyle'])
    if common.isset(frame.args['groupwidth']) then ret[#ret+1] = 'width:' .. frame.args['groupwidth'] .. ';' end
    style.add(ret, frame.args['groupstyle'])
    style.add(ret, groupstyle)
    ret[#ret+1] = '">'
    ret[#ret+1] = '<div style="padding:0;">\n'
    ret[#ret+1] = group
    ret[#ret+1] = '</div></td>'

    -- start the content cell
    ret[#ret+1] = '<td style="text-align:left;border-left-width:2px;border-left-style:solid;'
  else
    -- no group name, start the content already
    ret[#ret+1] = '<td colspan=2 style="'
  end
  -- a bit tricky, but this works as XOR
  if (frame.args['evenodd'] == "swap") ~= ((k % 2) == 0) then
    if common.isset(colors[ttype]) then ret[#ret+1] = 'background:' .. colors[ttype]['dark'] .. ';' end
  else
    ret[#ret+1] = 'background:transparent;'
  end
  if not common.isset(frame.args['groupwidth']) then ret[#ret+1] = 'width:100%;' end
  ret[#ret+1] = 'padding: 0;'
  style.add(ret, frame.args['liststyle'])
  style.add(ret, common.cv((frame.args['evenodd'] == "swap") ~= ((k % 2) == 0), frame.args['evenstyle'], frame.args['oddstyle']))
  style.add(ret, liststyle)
  ret[#ret+1] = '" class="navbox-list ' .. common.cv((frame.args['evenodd'] == "swap") ~= ((k % 2) == 0), 'navbox-even', 'navbox-odd') .. '">'

  -- add the <div> with content (same <div> that child navbox has to close when starting table)
  ret[#ret+1] = '<div style="padding:'
  if common.isset(frame.args['list' .. k .. 'padding']) then
    ret[#ret+1] = frame.args['list' .. k .. 'padding']
  elseif common.isset(frame.args['listpadding']) then
    ret[#ret+1] = frame.args['listpadding']
  else
    ret[#ret+1] = '0em 0.25em'
  end
  ret[#ret+1] = ';">\n'
  ret[#ret+1] = list
  ret[#ret+1] = '</div></td>'
  return table.concat(ret)
end

--[[ Generates the "body" of table (everything below title) ]]
local function build_body(frame, border, ttype, lists)
  local ret = {}
  local sep = common.isset(frame.args['title']) -- if there was a title, we have to add separation for first row
  local imgs = true -- add images if present
  local irows = common.cv( (#lists > 0), (2 * #lists - 1), 1 )

  -- aff the 'above' row
  ret[#ret+1],sep = build_above_below(frame, border, ttype, frame.args['above'], frame.args['abovestyle'], sep)
  
  for k,v in pairs(lists) do
    if sep then -- add separation if needed
      ret[#ret+1] = '<tr style="height: 2px;"><td></td></tr>'
    end

    table.insert(ret, '<tr>')

    -- add left image (if wasn't added yet and is present)
    if imgs then
      if common.isset(frame.args['imageleft']) then
        ret[#ret+1] = '<td style="width:0%;padding:0px 2px 0px 0px;'
        style.add(ret, frame.args['imageleftstyle'])
        ret[#ret+1] = '" rowspan="' .. irows .. '">' .. frame.args['imageleft'] .. '</td>'
      end
    end

    -- add the list content
    ret[#ret+1] = build_row(frame, border, ttype, v['index'], v['group'], v['list'], v['groupstyle'], v['liststyle'])

    -- add right image (if wasn't added yet and is present)
    if imgs then
      if common.isset(frame.args['image']) then
        ret[#ret+1] = '<td style="width:0%;padding:0px 0px 0px 2px;'
        style.add(ret, frame.args['imagestyle'])
        ret[#ret+1] = '" rowspan="' .. irows .. '">' .. frame.args['image'] .. '</td>'
      end

      -- mark that images were added already
      imgs = false
    end

    ret[#ret+1] = '</tr>'
    sep = true -- now the separation is going to be needed for sure
  end

  ret[#ret+1],sep = build_above_below(frame, border, ttype, frame.args['below'], frame.args['belowstyle'], sep)

  return table.concat(ret)
end

-- == Exported functions ==
--[[ Generates and returns the whole navbox table. ]]
local function buildNavbox(frame)
  local template = {}
  local border = ""
  local ttype = ""

  if common.isset(frame.args['border']) then
    border = frame.args['border']
  elseif common.isset(frame.args[1]) then
    border = mw.text.trim(frame.args[1])
  end

  if common.isset(frame.args['type']) then
    ttype = frame.args['type']
  end

  -- TODO: filtering of border and type values?

  -- prepare the data first
  local lists = scan_lists(frame)

  -- build the content  
  template[#template+1] = start_box(frame, border, ttype)
  template[#template+1] = build_title(frame, border, ttype)
  template[#template+1] = build_body(frame, border, ttype, lists)
  template[#template+1] = end_box(frame, border, ttype)

  return table.concat(template)
end

-- [[ Workaround for the "Navbox subgroup" template ]]
local function buildNavboxSubgroup(frame)
  if not common.isset(frame.args['border']) then frame.args['border'] = 'child' end

  -- TODO: add/modify/remove other params?

  -- call the main function
  return buildNavbox(frame)
end

--[[ Mostly for debugging, generates and returns a table of sets of colors
     and the values in cells with colors used as backgrounds. ]]
local function buildColorTable(frame)
  local ret = {""}
  table.insert(ret, '<table class="wikitable" style="text-align: center;">')
  table.insert(ret, '<caption>List of colors in order from darkest to brigthest one</caption>')
  table.insert(ret, '<tr><th>"type"</th><th>title</th><th>above, below</th><th>group,<br/>sub-above/below</th><th>sub-group</th><th>dark background</th><th>background</th></tr>')
  for k,v in pairs(colors) do
    table.insert(ret, '<tr>')
    table.insert(ret, '<td>' .. k .. '</td>')
    table.insert(ret, '<td style="background:' .. v['title'] .. '">' .. v['title'] .. '</td>')
    table.insert(ret, '<td style="background:' .. v['above'] .. '">' .. v['above'] .. '</td>')
    table.insert(ret, '<td style="background:' .. v['group'] .. '">' .. v['group'] .. '</td>')
    table.insert(ret, '<td style="background:' .. v['subgroup'] .. '">' .. v['subgroup'] .. '</td>')
    table.insert(ret, '<td style="background:' .. v['dark'] .. '">' .. v['dark'] .. '</td>')
    table.insert(ret, '<td style="background:' .. v['background'] .. '">' .. v['background'] .. '</td>')
    table.insert(ret, '</tr>')
  end
  table.insert(ret, '</table>')
  return table.concat(ret)
end

-- export local functions
return {
  ['buildNavbox'] = buildNavbox,
  ['buildNavboxTemplate'] = function(frame) return buildNavbox(frame:getParent()) end, -- for wrappers
  ['buildNavboxSubgroup'] = buildNavboxSubgroup,
  ['buildNavboxSubgroupTemplate'] = function(frame) return buildNavboxSubgroup(frame:getParent()) end, -- for wrappers
  ['buildColorTable'] = buildColorTable
}

-- [[Category:Lua Scripts|{{PAGENAME}}]]