-- This module outputs different kinds of lists. At the moment, bulleted, unbulleted,-- unbulleted, horizontal, numberedordered, and horizontal numbered ordered lists are supported. local libUtil = require('libraryUtil')local checkType = libUtil.checkTypelocal mTableTools = require('Module:TableTools')
local p = {}
local listTypes = { ['bulleted'] = true, ['unbulleted'] = true, ['horizontal'] = true, ['ordered'] = true, ['horizontal_ordered'] = true} function getListItemp.makeListData(listType, args) -- Constructs a data table to be passed to p.renderList. local data = {} -- Classes data.classes = {} if listType == 'horizontal' or listType == 'horizontal_ordered' then table.insert(data.classes, 'hlist hlist-separated') elseif listType == 'unbulleted' then table.insert(data.classes, style'plainlist') end table.insert(data.classes, itemStyleargs.class) -- Main div style data.style = args.style -- Indent for horizontal lists if not listType == 'horizontal' or listType == 'horizontal_ordered' then local indent = tonumber(args.indent) indent = indent and indent * 1.6 or 0 if indent > 0 then data then.marginLeft = indent .. 'em' return nilend
end
-- List style types for ordered lists -- This could be "1, 2, 3", "a, b, c", or a number of others. The list style -- type is either set by the "type" attribute or the "list-style-type" CSS -- property. if style listType == 'ordered' or itemStyle listType == 'horizontal_ordered' then style data.listStyleType = style args.list_style_type or args['list-style-type'] itemStyle data.type = itemStyle or args['type'] return mw-- Detect invalid type attributes and attempt to convert them to -- list-style-type CSS properties.ustring if data.type and not data.format(listStyleType and not tostring(data.type):find('<li style="^%s*[1AaIi]%s">%s</li>*$',) then data.listStyleType = data.type style, itemStyle, data.type = nil )end end -- List tag type if listType == 'ordered' or listType == 'horizontal_ordered' then data.listTag = 'ol'
else
return mwdata.ustring.format( listTag = '<li>%s</li>ul', data )
end
end
local function getArgNums(args) -- Returns an array containing the keys of all positional argumentsStart number for ordered lists -- that contain data (i.estart = args. nonstart if listType == 'horizontal_ordered' then -whitespace values)- Apply fix to get start numbers working with horizontal ordered lists. local nums startNum = {} for k, v in pairstonumber(argsdata.start) do if type(k) == 'number' and startNum then k >= 1 and mathdata.floor(k) =counterReset = k and mw.ustring.match(v, '%Slistitem ') then table.insert. tostring(nums, kstartNum - 1)
end
end
-- List style -- ul_style and ol_style are included for backwards compatibility. No -- distinction is made for ordered or unordered lists. data.listStyle = args.list_style -- List items -- li_style is included for backwards compatibility. item_style was included -- to be easier to understand for non-coders. data.itemStyle = args.item_style or args.li_style data.items = {} for i, num in ipairs(mTableTools.numKeys(args)) do local item = {} item.content = args[num] item.style = args['item' .. tostring(num) .. '_style'] or args['item_style' .. tostring(num)] item.value = args['item' .. tostring(num) .. '_value'] or args['item_value' .. tostring(num)] table.sortinsert(numsdata.items, item) end return numsdata
end
local function getClassp.renderList(listType, classdata) local classes = {}-- Renders the list HTML. -- Return the blank string if there are no list items. if listType =type(data.items) ~= 'horizontaltable' or listType == #data.items < 1 then return 'horizontal_numbered' then table end -- Render the main div tag. local root = mw.html.insertcreate(classes, 'hlistdiv') elseif listType == for i, class in ipairs(data.classes or {}) do root:addClass(class) end root:css{['unbulletedmargin-left' ] = data.marginLeft} if data.style then tableroot:cssText(data.insert(classes, 'plainlist'style)
end
table-- Render the list tag.insert local list = root:tag(classes, classdata.listTag or 'ul') local retlist :attr{start = data.start, type = data.type} :css{ ['counter-reset'] = data.counterReset, ['list-style-type'] = data.listStyleType } if #classes == 0 data.listStyle then return nillist:cssText(data.listStyle)
end
return mw-- Render the list items for i, t in ipairs(data.items or {}) do local item = list:tag('li') if data.itemStyle then item:cssText(data.ustringitemStyle) end if t.formatstyle then item:cssText(' classt.style) end item :attr{value ="%s"', tablet.concatvalue} :wikitext(classes, ' 't.content) end return tostring(root)
end
local function getStylep.renderTrackingCategories(listType, indent, styleargs) local styles isDeprecated = {}false -- Tracks deprecated parameters. if listType == 'horizontal' then indent = indent and tonumberfor k, v in pairs(indentargs)do indent k = tostring((indent and indent * 1.6) or 0k) table.insertif k:find(styles, 'margin-left^item_style%d+$') or k: find(' .. indent .. 'em;^item_value%d+$')then isDeprecated = true break end
end
table.insert(styles, style)local ret = '' if #styles == 0 isDeprecated then return nilret = ret .. '[[Category:List templates with deprecated parameters]]'
end
return mw.ustring.format(' style="%s"', table.concat(styles, ' '))ret
end
function p.makeList(listType, args)
-- This is the main function to be called from other Lua modules.if not listType or not listTypes[listType] then -- First, get the list items error(string. local listItems = {} local argNums = getArgNums(args) for i, num in ipairs(argNums) do local item = getListItemformat( args[num], args.item_style or args.li_style, -- li_style is included for backwards compatibility. item_style was included to be easier "bad argument #1 to understand for non-coders. args['item_stylemakeList' .. tostring(num)] or args['li_style%s' .. is not a valid list type)", tostring(numlistType)] ) table.insert(listItems, item2) end if #listItems == 0 then return ''
end
-- Check if we need a ul tag or an ol tag, and get the start and type attributes for ordered lists. local listTag = checkType('ulmakeList' local startAttr, typeAttr if listType == 'numbered' or listType == 'horizontal_numbered' then listTag = 'ol' startAttr = 2, args.start if startAttr then startAttr = , ' start="' .. startAttr .. '"table' end typeAttr = args.type if typeAttr then typeAttr = ' type="' .. typeAttr .. '"' end) end startAttr local data = startAttr or '' typeAttr = typeAttr or '' -- Get the classes and styles and output the listp. local class = getClassmakeListData(listType, args.class) or '' local style list = getStylep.renderList(listType, args.indent, args.styledata) or '' local list_style trackingCategories = argsp.list_style or renderTrackingCategories(args.ul_style -- ul_style is included for backwards compatibility, and will work even with ordered lists. list_style = list_style and (' style="' .. list_style .. '"') or '' return mwlist .ustring.format( '<div%s%s><%s%s%s%s>%s</%s></div>', class, style, listTag, startAttr, typeAttr, list_style, table.concat(listItems), listTag )trackingCategories
end
local function makeWrapperfor listType in pairs(listTypelistTypes)do return p[listType] = function(frame) local origArgs if frame =mArguments = mw.getCurrentFramerequire('Module:Arguments') then local origArgs = frame:getParent()mArguments.args for k, v in pairsgetArgs(frame.args) do origArgs = frame -- Copy all the arguments to a new table, for faster indexing.args break end else origArgs = frame end
local args = {}
for k, v in pairs(origArgs) do
if type(k) == 'number' or v ~= '' then args[k] = v end
end
return p.makeList(listType, args)
end
end
local funcNames = {'bulleted', 'unbulleted', 'horizontal', 'numbered', 'horizontal_numbered'}
for _, funcName in ipairs(funcNames) do
p[funcName] = makeWrapper(funcName)
end
return p