모듈:Navbox

--[[
Navbox Module

  • Fully CSS styled (inline styles possible but not default)
  • Supports unlimited rows

by User:Tjcool007
http://layton.wikia.com/wiki/Module:Navbox

Next changes are applied by User:Cafeinlove:

  • Parameter names are translated into Korean.
  • CSS class names reflect BEM rules
  • Parameters `name`, `border` are removed.
  • VDE linkset no more requires Template:Vdelinks. It is generated out of
`참조` argument, and the links color is customizable via `참조색` argument.
  • Parameters related to alternative group/list have been removed.
Instead, parameters for individual cells such as
`제목클래스n`, `제목모양n`, `내용클래스n`, `내용모양n` are introduced.
  • List items are separated by a middot(plain text) instead of CSS pseudo.
  • List parameter accepts both list items and non-list items.
  • Class `navbox__title` is assigned to `th` element instead of `tr` element.

]]

local p = {}

-- Default config. Values will be replaced with
-- proprecessed arguments passed to template
local args = {}
local navbox -- Actual navbox

local rownums, skiprows = {}, {}
local alt, hasrows, hasData, isChild = false, false, false, false
local activeSection, sections, cimage, cimageleft
local colspan, rowspan

local showText, hideText = '보이기', '숨기기'


-- Title


--- Processes the VDE links in the title
--
-- @param titlecell The table cell of the title
local function processVde( titlecell )

if not args['참조'] then return end

local vde = { '보기', '토론', '편집' }

local vdeLinks = {}
local link, ns, fullurl
local page = args['참조']
local color = args['참조색'] or '#111'

for k, v in pairs(vde) do

ns = '틀'

if v ~= '편집' then

if v == '토론' then ns = '틀토론' end
link = '' .. v .. ''
else
fullurl = mw.uri.fullUrl( ns .. ':' .. page, 'action=edit')
link = '[' .. tostring(fullurl) .. ' ' .. v .. ']'
end
table.insert(vdeLinks, link)
end

titlecell

tag('span')
addClass('navbox__vde')
wikitext( table.concat(vdeLinks, ' ᛫ ') )

end

--- Processes the main title row
local function processTitle()

local titlerow = mw.html.create('tr')
local titlecell = mw.html.create('th'):addClass('navbox__title'):attr('colspan',colspan):attr('scope','col')

processVde( titlecell )

titlecell:wikitext( args['큰제목'] or ' ' )

if args['큰제목클래스'] then titlerow:addClass( args['큰제목클래스'] ) end

if args['큰제목모양'] then titlecell:cssText( args['큰제목모양'] ) end

titlerow:node( titlecell )

navbox:node( titlerow )

end

local function _addGutter( parent, incRowspan )

parent:tag('tr'):addClass('navbox__gutter'):tag('td'):attr('colspan',2)

if incRowspan then

rowspan = rowspan + 1
end

end


-- Above/Below


--- Processes the above and below rows
--
-- @param rowtype Either 'above' or 'below'
local function processAboveBelow( rowtype, prefix )

if not args[rowtype .. '글'] then return end

local abrow = mw.html.create('tr'):addClass('navbox__'..rowtype)

local abcell = mw.html.create('td'):attr('colspan',colspan):wikitext( args[rowtype .. '글'] )

if args[rowtype .. '클래스'] then abrow:addClass( args[rowtype .. '클래스'] ) end

if args[rowtype .. '모양'] then abcell:cssText( args[rowtype .. '모양'] ) end

abrow:node( abcell )

_addGutter( navbox )
navbox:node( abrow )

end


-- Main Rows


--- Processes the images
local function _processImage(row, imgtype)

if not args[imgtype] then return end

local iclass = imgtype == '그림' and 'navboximageright' or 'navboximageleft'

local imagecell = mw.html.create('td'):addClass('navbox__image'):addClass(iclass)

local image = args[imgtype]

if image:sub(1,1) ~= '[' then
local width = args[imgtype .. '너비'] or '100px'
imagecell:css('width',width):wikitext('' .. width .. '|link=' .. (args[imgtype .. '링크'] or ) .. '')
else
imagecell:css('width','0%'):wikitext(image)
end

if args[imgtype .. '클래스'] then imagecell:addClass( args[imgtype .. '클래스'] ) end

if args[imgtype .. '모양'] then imagecell:cssText( args[imgtype .. '모양'] ) end

row:node( imagecell )

if imgtype == '그림' then
cimage = imagecell
else
cimageleft = imagecell
end

end

--- Closes the currently active section (if any)
local function _closeCurrentSection()

if not activeSection then return end

local row = mw.html.create('tr'):addClass('navbox__section-row')

local cell = mw.html.create('td'):attr('colspan',2)
if not hasrows then
_processImage(row,'왼쪽그림')
end

cell:node(sections[activeSection])

row:node(cell)

local firstRow = false

if not hasrows then
firstRow = true
hasrows = true
_processImage(row,'그림')
end

_addGutter(navbox,not firstRow)

navbox:node(row)
rowspan = rowspan + 1

activeSection = false

hasData = false

end

--- Handles alternating rows
--
-- @return Alternatingly returns true or false. Always returns false if alternating rows
-- are disabled with "alternaterows = no"
local function _alternateRow()

if args['색교차'] == 'no' then return false end

if alt then

alt = false
return true
else
alt = true
return false
end

end

--- Process a single Header "row"
--
-- @param num Number of the row to be processed
local function processHeader(num)

if not args['작은제목'..num] then return end
_closeCurrentSection()

local subtable = mw.html.create('table'):addClass('navbox__section')

local headerrow = mw.html.create('tr')
local header = mw.html.create('th'):addClass('navbox__header'):attr('colspan',2):attr('scope','col'):wikitext( args['작은제목'..num] )

local collapseme = args['작은제목상태'..num] or false

local state = false

if collapseme then

-- Look at this one
if collapseme ~= 'plain' then
state = collapseme == 'expanded' and 'expanded' or 'collapsed'
end
else
-- Look at default
local collapseall = args['작은제목기본상태'] or false
if collapseall then
state = collapseall == 'expanded' and 'expanded' or 'collapsed'
end
end

if state then

subtable:addClass('mw-collapsible'):attr('data-expandtext',showText):attr('data-collapsetext',hideText)
if state == 'collapsed' then
subtable:addClass('mw-collapsed')
end
end

if args['작은제목클래스'] then headerrow:addClass( args['작은제목클래스'] ) end

if args['작은제목모양'] then header:cssText( args['작은제목모양'] ) end

headerrow:node(header)

subtable:node(headerrow)

sections[num] = subtable

activeSection = num

end

--- Processes a single list row
--
-- @param num Number of the row to be processed
local function processList(num)

if not args['내용'..num] then return end

local row = mw.html.create('tr'):addClass('navbox__row')

if not hasrows and not activeSection then
_processImage(row, '왼쪽그림')
end

local listcell = mw.html.create('td'):addClass('navbox__list')

local data = args['내용'..num]
local listTable = {}
local list =
local separator = ' ᛫ '
local function forwardJoined(str, tbl, sep)
local joined = table.concat(tbl, sep)
for i = 0, #tbl do tbl[i] = nil end -- empty tbl
return str .. joined
end
local function appendWrapped(str, item, patt)
return str .. string.format(patt, item)
end
for line in data:gmatch('[^\r\n]+') do -- get line by line
if string.len(line) == 0 then break end
if line:sub(1, 2) == '* ' then -- line starting with '* '
table.insert(listTable, line:sub(3))
else -- other lines
if #listTable ~= 0 then
list = forwardJoined(list, listTable, separator)
end
list = appendWrapped(list, line, '
%s
')
end
end
list = forwardJoined(list, listTable, separator)

listcell:wikitext( list )

local altRow = _alternateRow()

if altRow then row:addClass( 'alt' ) end -- 홀수 행

if args['모든내용클래스'] then listcell:addClass( args['모든내용클래스'] ) end

if args['모든내용모양'] then listcell:cssText( args['모든내용모양'] ) end

local listclass = args['내용클래스'..num] or false

if listclass then listcell:addClass( listclass ) end

local liststyle = args['내용모양'..num] or false

if liststyle then listcell:cssText( liststyle ) end

if args['제목'..num] then

local groupcell = mw.html.create('th'):addClass('navbox__group'):attr('scope','row'):wikitext( args['제목'..num] )

if args['모든제목클래스'] then groupcell:addClass( args['모든제목클래스'] ) end

if args['모든제목모양'] then groupcell:cssText( args['모든제목모양'] ) end

local groupclass = args['제목클래스'..num] or false

if groupclass then groupcell:addClass( groupclass ) end

local groupstyle = args['제목모양'..num] or false

if groupstyle then groupcell:cssText( groupstyle ) end

row:node( groupcell )

else
listcell:attr('colspan',2):addClass('no-group')
end

row:node( listcell )

local firstRow = false

if not hasrows and not activeSection then
firstRow = true
hasrows = true
_processImage(row, '그림')
end

if activeSection then

local parent = sections[activeSection]
if not isChild or not firstRow then
_addGutter(parent)
end
parent:node(row)
hasData = true
else
if not isChild or not firstRow then
_addGutter(navbox,not firstRow)
end
navbox:node( row )
rowspan = rowspan + 1
end

end

--- Processes all rows
local function processRows()

sections = {}
for i=1,#rownums do
local num = rownums[i]
if not skiprows[num] then
processHeader(num)
processList(num)
end
end
_closeCurrentSection()

if cimageleft then

cimageleft:attr('rowspan',rowspan)
end
if cimage then
cimage:attr('rowspan',rowspan)
end

end


-- ARGUMENTS PREPROCESSOR
-- * Extracts arguments from frame and stores them in args table
-- * At the same time, checks for valid row numbers


--- Preprocessor for the arguments.
-- Will fill up the args table with the parameters from the frame grouped by their type.
--
-- @param frame The frame passed to the Module.
local function preProcessArgs(frame)

local tmp = {}

if frame == mw.getCurrentFrame() then

tmp = frame:getParent().args
else
tmp = frame
end

-- Storage tables

local nums = {}

-- Loop over all the args

for k,v in pairs(tmp) do
-- Skip empty args, which are useless
if v ~= then
local cat,num = tostring(k):match('^(.-)([1-9]%d*)$')

if cat == '제목' or cat == '내용' then

nums[num] = true
end

args[k] = v -- Simple copy

end
end

colspan = args['그림'] and 3 or 2

if args['왼쪽그림'] then colspan = colspan + 1 end
rowspan = 0

if args['색교차'] == '반전' then alt = true end

for k, v in pairs(nums) do

table.insert(rownums, tonumber(k))
end

table.sort(rownums)

-- Calculate skip rows

local cSection, cSkip
local showall = args['상태']
for i = 1, #rownums do
local num = rownums[i]
if args['작은제목'..num] then
cSection = true
cSkip = false
local showme = args['작은제목상태'..num]
if showme == hideText then
cSkip = true
elseif showme == '자동' or (showme ~= showText and showall ~= showText) then
if not args['내용'..num] then
local nextNum = rownums[i+1]
cSkip = not nextNum or args['작은제목'..nextNum] -- If next has a header -> skip
end
end
end
if cSection and cSkip then
skiprows[num] = true
end
end

end


-- MAIN FUNCTIONS


--- Processes the arguments to create the navbox.
--
-- @return A string with HTML that is the navbox.
local function _navbox()

-- Create the root HTML element
local trim = function(s)
return s and mw.ustring.gsub(s, "^%s*(.-)%s*$", "%1") or
end
isChild = (trim(args[1]) == '하위')

if isChild then

navbox = mw.html.create('table'):addClass('navbox__subgroup')
else
navbox = mw.html.create('table'):addClass('navbox')

if args['상태'] ~= 'plain' then

navbox:addClass('mw-collapsible'):attr('data-expandtext',showText):attr('data-collapsetext',hideText)
if args['상태'] == 'collapsed' then
navbox:addClass('mw-collapsed')
end
end
end

if args['클래스'] then navbox:addClass(args['클래스']) end

if args['모양'] then navbox:cssText(args['모양']) end

-- Process...

if not isChild then
processTitle()
processAboveBelow('above', '윗')
processRows()
processAboveBelow('below', '아랫')

return tostring(navbox)

else
processRows()

return tostring(navbox)

end

end

--- Main module entry point.

-- To be called with

or directly from another module.

--
-- @param frame The frame passed to the module via the #invoke. If called from another
-- module directly, this should be a table with the parameter definition.
function p.main(frame)

-- Save the arguments in a local variable so other functions can use them.
preProcessArgs(frame)

return _navbox()
end

return p