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

  1. -- This module outputs different kinds of lists. At the moment, bulleted,
  2. -- unbulleted, horizontal, ordered, and horizontal ordered lists are supported.
  3.  
  4. local libUtil = require('libraryUtil')
  5. local checkType = libUtil.checkType
  6. local mTableTools = require('Module:TableTools')
  7.  
  8. local p = {}
  9.  
  10. local listTypes = {
  11. ['bulleted'] = true,
  12. ['unbulleted'] = true,
  13. ['horizontal'] = true,
  14. ['ordered'] = true,
  15. ['horizontal_ordered'] = true
  16. }
  17.  
  18. function p.makeListData(listType, args)
  19. -- Constructs a data table to be passed to p.renderList.
  20. local data = {}
  21.  
  22. -- Classes
  23. data.classes = {}
  24. if listType == 'horizontal' or listType == 'horizontal_ordered' then
  25. table.insert(data.classes, 'hlist')
  26. elseif listType == 'unbulleted' then
  27. table.insert(data.classes, 'plainlist')
  28. end
  29. table.insert(data.classes, args.class)
  30.  
  31. -- Main div style
  32. data.style = args.style
  33.  
  34. -- Indent for horizontal lists
  35. if listType == 'horizontal' or listType == 'horizontal_ordered' then
  36. local indent = tonumber(args.indent)
  37. indent = indent and indent * 1.6 or 0
  38. if indent > 0 then
  39. data.marginLeft = indent .. 'em'
  40. end
  41. end
  42. -- List style types for ordered lists
  43. -- This could be "1, 2, 3", "a, b, c", or a number of others. The list style
  44. -- type is either set by the "type" attribute or the "list-style-type" CSS
  45. -- property.
  46. if listType == 'ordered' or listType == 'horizontal_ordered' then
  47. data.listStyleType = args.list_style_type or args['list-style-type']
  48. data.type = args['type']
  49.  
  50. -- Detect invalid type attributes and attempt to convert them to
  51. -- list-style-type CSS properties.
  52. if data.type
  53. and not data.listStyleType
  54. and not tostring(data.type):find('^%s*[1AaIi]%s*$')
  55. then
  56. data.listStyleType = data.type
  57. data.type = nil
  58. end
  59. end
  60. -- List tag type
  61. if listType == 'ordered' or listType == 'horizontal_ordered' then
  62. data.listTag = 'ol'
  63. else
  64. data.listTag = 'ul'
  65. end
  66.  
  67. -- Start number for ordered lists
  68. data.start = args.start
  69. if listType == 'horizontal_ordered' then
  70. -- Apply fix to get start numbers working with horizontal ordered lists.
  71. local startNum = tonumber(data.start)
  72. if startNum then
  73. data.counterReset = 'listitem ' .. tostring(startNum - 1)
  74. end
  75. end
  76.  
  77. -- List style
  78. -- ul_style and ol_style are included for backwards compatibility. No
  79. -- distinction is made for ordered or unordered lists.
  80. data.listStyle = args.list_style
  81.  
  82. -- List items
  83. -- li_style is included for backwards compatibility. item_style was included
  84. -- to be easier to understand for non-coders.
  85. data.itemStyle = args.item_style or args.li_style
  86. data.items = {}
  87. for i, num in ipairs(mTableTools.numKeys(args)) do
  88. local item = {}
  89. item.content = args[num]
  90. item.style = args['item' .. tostring(num) .. '_style']
  91. or args['item_style' .. tostring(num)]
  92. item.value = args['item' .. tostring(num) .. '_value']
  93. or args['item_value' .. tostring(num)]
  94. table.insert(data.items, item)
  95. end
  96. return data
  97. end
  98.  
  99. function p.renderList(data)
  100. -- Renders the list HTML.
  101. -- Return the blank string if there are no list items.
  102. if type(data.items) ~= 'table' or #data.items < 1 then
  103. return ''
  104. end
  105. -- Render the main div tag.
  106. local root = mw.html.create('div')
  107. for i, class in ipairs(data.classes or {}) do
  108. root:addClass(class)
  109. end
  110. root:css{['margin-left'] = data.marginLeft}
  111. if data.style then
  112. root:cssText(data.style)
  113. end
  114.  
  115. -- Render the list tag.
  116. local list = root:tag(data.listTag or 'ul')
  117. list
  118. :attr{start = data.start, type = data.type}
  119. :css{
  120. ['counter-reset'] = data.counterReset,
  121. ['list-style-type'] = data.listStyleType
  122. }
  123. if data.listStyle then
  124. list:cssText(data.listStyle)
  125. end
  126.  
  127. -- Render the list items
  128. for i, t in ipairs(data.items or {}) do
  129. local item = list:tag('li')
  130. if data.itemStyle then
  131. item:cssText(data.itemStyle)
  132. end
  133. if t.style then
  134. item:cssText(t.style)
  135. end
  136. item
  137. :attr{value = t.value}
  138. :wikitext(t.content)
  139. end
  140.  
  141. return tostring(root)
  142. end
  143.  
  144. function p.renderTrackingCategories(args)
  145. local isDeprecated = false -- Tracks deprecated parameters.
  146. for k, v in pairs(args) do
  147. k = tostring(k)
  148. if k:find('^item_style%d+$') or k:find('^item_value%d+$') then
  149. isDeprecated = true
  150. break
  151. end
  152. end
  153. local ret = ''
  154. if isDeprecated then
  155. ret = ret .. '[[Category:List templates with deprecated parameters]]'
  156. end
  157. return ret
  158. end
  159.  
  160. function p.makeList(listType, args)
  161. if not listType or not listTypes[listType] then
  162. error(string.format(
  163. "bad argument #1 to 'makeList' ('%s' is not a valid list type)",
  164. tostring(listType)
  165. ), 2)
  166. end
  167. checkType('makeList', 2, args, 'table')
  168. local data = p.makeListData(listType, args)
  169. local list = p.renderList(data)
  170. local trackingCategories = p.renderTrackingCategories(args)
  171. return list .. trackingCategories
  172. end
  173.  
  174. for listType in pairs(listTypes) do
  175. p[listType] = function (frame)
  176. local mArguments = require('Module:Arguments')
  177. local origArgs = mArguments.getArgs(frame)
  178. -- Copy all the arguments to a new table, for faster indexing.
  179. local args = {}
  180. for k, v in pairs(origArgs) do
  181. args[k] = v
  182. end
  183. return p.makeList(listType, args)
  184. end
  185. end
  186.  
  187. return p