Diff: Module:List
Comparing revision #1 (2022-12-29 17:57:56) with revision #2 (2023-02-02 05:32:49).
| Old | New |
|---|---|
local libUtil = require('libraryUtil') |
local libUtil = require('libraryUtil') |
local checkType = libUtil.checkType |
local checkType = libUtil.checkType |
local mTableTools = require('Module:TableTools') |
local mTableTools = require('Module:TableTools') |
local p = {} |
local p = {} |
local listTypes = { |
local listTypes = { |
['bulleted'] = true, |
['bulleted'] = true, |
['unbulleted'] = true, |
['unbulleted'] = true, |
['horizontal'] = true, |
['horizontal'] = true, |
['ordered'] = true, |
['ordered'] = true, |
['horizontal_ordered'] = true |
['horizontal_ordered'] = true |
} |
} |
function p.makeListData(listType, args) |
function p.makeListData(listType, args) |
-- Constructs a data table to be passed to p.renderList. |
-- Constructs a data table to be passed to p.renderList. |
local data = {} |
local data = {} |
-- Classes and TemplateStyles |
-- Classes and TemplateStyles |
data.classes = {} |
data.classes = {} |
data.templatestyles = '' |
data.templatestyles = '' |
if listType == 'horizontal' or listType == 'horizontal_ordered' then |
if listType == 'horizontal' or listType == 'horizontal_ordered' then |
table.insert(data.classes, 'hlist') |
table.insert(data.classes, 'hlist') |
data.templatestyles = mw.getCurrentFrame():extensionTag{ |
data.templatestyles = mw.getCurrentFrame():extensionTag{ |
name = 'templatestyles', args = { src = 'Hlist/styles.css' } |
name = 'templatestyles', args = { src = 'Hlist/styles.css' } |
} |
} |
elseif listType == 'unbulleted' then |
elseif listType == 'unbulleted' then |
table.insert(data.classes, 'plainlist') |
table.insert(data.classes, 'plainlist') |
data.templatestyles = mw.getCurrentFrame():extensionTag{ |
data.templatestyles = mw.getCurrentFrame():extensionTag{ |
name = 'templatestyles', args = { src = 'Plainlist/styles.css' } |
name = 'templatestyles', args = { src = 'Plainlist/styles.css' } |
} |
} |
end |
end |
table.insert(data.classes, args.class) |
table.insert(data.classes, args.class) |
-- Main div style |
-- Main div style |
data.style = args.style |
data.style = args.style |
-- Indent for horizontal lists |
-- Indent for horizontal lists |
if listType == 'horizontal' or listType == 'horizontal_ordered' then |
if listType == 'horizontal' or listType == 'horizontal_ordered' then |
local indent = tonumber(args.indent) |
local indent = tonumber(args.indent) |
indent = indent and indent * 1.6 or 0 |
indent = indent and indent * 1.6 or 0 |
if indent > 0 then |
if indent > 0 then |
data.marginLeft = indent .. 'em' |
data.marginLeft = indent .. 'em' |
end |
end |
end |
end |
-- List style types for ordered lists |
-- List style types for ordered lists |
-- This could be "1, 2, 3", "a, b, c", or a number of others. The list style |
-- 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 |
-- type is either set by the "type" attribute or the "list-style-type" CSS |
-- property. |
-- property. |
if listType == 'ordered' or listType == 'horizontal_ordered' then |
if listType == 'ordered' or listType == 'horizontal_ordered' then |
data.listStyleType = args.list_style_type or args['list-style-type'] |
data.listStyleType = args.list_style_type or args['list-style-type'] |
data.type = args['type'] |
data.type = args['type'] |
-- Detect invalid type attributes and attempt to convert them to |
-- Detect invalid type attributes and attempt to convert them to |
-- list-style-type CSS properties. |
-- list-style-type CSS properties. |
if data.type |
if data.type |
and not data.listStyleType |
and not data.listStyleType |
and not tostring(data.type):find('^%s*[1AaIi]%s*$') |
and not tostring(data.type):find('^%s*[1AaIi]%s*$') |
then |
then |
data.listStyleType = data.type |
data.listStyleType = data.type |
data.type = nil |
data.type = nil |
end |
end |
end |
end |
-- List tag type |
-- List tag type |
if listType == 'ordered' or listType == 'horizontal_ordered' then |
if listType == 'ordered' or listType == 'horizontal_ordered' then |
data.listTag = 'ol' |
data.listTag = 'ol' |
else |
else |
data.listTag = 'ul' |
data.listTag = 'ul' |
end |
end |
-- Start number for ordered lists |
-- Start number for ordered lists |
data.start = args.start |
data.start = args.start |
if listType == 'horizontal_ordered' then |
if listType == 'horizontal_ordered' then |
-- Apply fix to get start numbers working with horizontal ordered lists. |
-- Apply fix to get start numbers working with horizontal ordered lists. |
local startNum = tonumber(data.start) |
local startNum = tonumber(data.start) |
if startNum then |
if startNum then |
data.counterReset = 'listitem ' .. tostring(startNum - 1) |
data.counterReset = 'listitem ' .. tostring(startNum - 1) |
end |
end |
end |
end |
-- List style |
-- List style |
-- ul_style and ol_style are included for backwards compatibility. No |
-- ul_style and ol_style are included for backwards compatibility. No |
-- distinction is made for ordered or unordered lists. |
-- distinction is made for ordered or unordered lists. |
data.listStyle = args.list_style |
data.listStyle = args.list_style |
-- List items |
-- List items |
-- li_style is included for backwards compatibility. item_style was included |
-- li_style is included for backwards compatibility. item_style was included |
-- to be easier to understand for non-coders. |
-- to be easier to understand for non-coders. |
data.itemStyle = args.item_style or args.li_style |
data.itemStyle = args.item_style or args.li_style |
data.items = {} |
data.items = {} |
for _, num in ipairs(mTableTools.numKeys(args)) do |
for _, num in ipairs(mTableTools.numKeys(args)) do |
local item = {} |
local item = {} |
item.content = args[num] |
item.content = args[num] |
item.style = args['item' .. tostring(num) .. '_style'] |
item.style = args['item' .. tostring(num) .. '_style'] |
or args['item_style' .. tostring(num)] |
or args['item_style' .. tostring(num)] |
item.value = args['item' .. tostring(num) .. '_value'] |
item.value = args['item' .. tostring(num) .. '_value'] |
or args['item_value' .. tostring(num)] |
or args['item_value' .. tostring(num)] |
table.insert(data.items, item) |
table.insert(data.items, item) |
end |
end |
return data |
return data |
end |
end |
function p.renderList(data) |
function p.renderList(data) |
-- Renders the list HTML. |
-- Renders the list HTML. |
-- Return the blank string if there are no list items. |
-- Return the blank string if there are no list items. |
if type(data.items) ~= 'table' or #data.items < 1 then |
if type(data.items) ~= 'table' or #data.items < 1 then |
return '' |
return '' |
end |
end |
-- Render the main div tag. |
-- Render the main div tag. |
local root = mw.html.create('div') |
local root = mw.html.create('div') |
for _, class in ipairs(data.classes or {}) do |
for _, class in ipairs(data.classes or {}) do |
root:addClass(class) |
root:addClass(class) |
end |
end |
root:css{['margin-left'] = data.marginLeft} |
root:css{['margin-left'] = data.marginLeft} |
if data.style then |
if data.style then |
root:cssText(data.style) |
root:cssText(data.style) |
end |
end |
-- Render the list tag. |
-- Render the list tag. |
local list = root:tag(data.listTag or 'ul') |
local list = root:tag(data.listTag or 'ul') |
list |
list |
:attr{start = data.start, type = data.type} |
:attr{start = data.start, type = data.type} |
:css{ |
:css{ |
['counter-reset'] = data.counterReset, |
['counter-reset'] = data.counterReset, |
['list-style-type'] = data.listStyleType |
['list-style-type'] = data.listStyleType |
} |
} |
if data.listStyle then |
if data.listStyle then |
list:cssText(data.listStyle) |
list:cssText(data.listStyle) |
end |
end |
-- Render the list items |
-- Render the list items |
for _, t in ipairs(data.items or {}) do |
for _, t in ipairs(data.items or {}) do |
local item = list:tag('li') |
local item = list:tag('li') |
if data.itemStyle then |
if data.itemStyle then |
item:cssText(data.itemStyle) |
item:cssText(data.itemStyle) |
end |
end |
if t.style then |
if t.style then |
item:cssText(t.style) |
item:cssText(t.style) |
end |
end |
item |
item |
:attr{value = t.value} |
:attr{value = t.value} |
:wikitext(t.content) |
:wikitext(t.content) |
end |
end |
return data.templatestyles .. tostring(root) |
return data.templatestyles .. tostring(root) |
end |
end |
function p.renderTrackingCategories(args) |
function p.renderTrackingCategories(args) |
local isDeprecated = false -- Tracks deprecated parameters. |
local isDeprecated = false -- Tracks deprecated parameters. |
for k, v in pairs(args) do |
for k, v in pairs(args) do |
k = tostring(k) |
k = tostring(k) |
if k:find('^item_style%d+$') or k:find('^item_value%d+$') then |
if k:find('^item_style%d+$') or k:find('^item_value%d+$') then |
isDeprecated = true |
isDeprecated = true |
break |
break |
end |
end |
end |
end |
local ret = '' |
local ret = '' |
if isDeprecated then |
if isDeprecated then |
ret = ret .. '[[Category:List templates with deprecated parameters]]' |
ret = ret .. '[[Category:List templates with deprecated parameters]]' |
end |
end |
return ret |
return ret |
end |
end |
function p.makeList(listType, args) |
function p.makeList(listType, args) |
if not listType or not listTypes[listType] then |
if not listType or not listTypes[listType] then |
error(string.format( |
error(string.format( |
"bad argument #1 to 'makeList' ('%s' is not a valid list type)", |
"bad argument #1 to 'makeList' ('%s' is not a valid list type)", |
tostring(listType) |
tostring(listType) |
), 2) |
), 2) |
end |
end |
checkType('makeList', 2, args, 'table') |
checkType('makeList', 2, args, 'table') |
local data = p.makeListData(listType, args) |
local data = p.makeListData(listType, args) |
local list = p.renderList(data) |
local list = p.renderList(data) |
local trackingCategories = p.renderTrackingCategories(args) |
local trackingCategories = p.renderTrackingCategories(args) |
return list .. trackingCategories |
return list .. trackingCategories |
end |
end |
for listType in pairs(listTypes) do |
for listType in pairs(listTypes) do |
p[listType] = function (frame) |
p[listType] = function (frame) |
local mArguments = require('Module:Arguments') |
local mArguments = require('Module:Arguments') |
local origArgs = mArguments.getArgs(frame, { |
local origArgs = mArguments.getArgs(frame, { |
valueFunc = function (key, value) |
valueFunc = function (key, value) |
if not value or not mw.ustring.find(value, '%S') then return nil end |
if not value or not mw.ustring.find(value, '%S') then return nil end |
if mw.ustring.find(value, '^%s*[%*#;:]') then |
if mw.ustring.find(value, '^%s*[%*#;:]') then |
return value |
return value |
else |
else |
return value:match('^%s*(.-)%s*$') |
return value:match('^%s*(.-)%s*$') |
end |
end |
return nil |
return nil |
end |
end |
}) |
}) |
-- Copy all the arguments to a new table, for faster indexing. |
-- Copy all the arguments to a new table, for faster indexing. |
local args = {} |
local args = {} |
for k, v in pairs(origArgs) do |
for k, v in pairs(origArgs) do |
args[k] = v |
args[k] = v |
end |
end |
return p.makeList(listType, args) |
return p.makeList(listType, args) |
end |
end |
end |
end |
return p |
return p |