Module:Listbox: Difference between revisions
Jump to navigation
Jump to search
Want an adless experience? Log in or Create an account.
(parse extra as json) |
(support variants and preparing to implement gallery format) |
||
Line 15: | Line 15: | ||
end | end | ||
function | function getPageTree( categoryName, expandVariants ) | ||
-- get all pages in the category | |||
local pages = mw.ext.dpl.getPages{ category = categoryName, ordermethod = 'sortkey', order = 'ascending' } | |||
-- get | |||
local pages = mw.ext.dpl.getPages{ category = | |||
-- organize them according to metadata | -- organize them according to metadata | ||
local | local pageTree = { default = {} } | ||
for _, page in ipairs( pages ) do | for _, page in ipairs( pages ) do | ||
-- get metadata | -- get metadata | ||
Line 58: | Line 31: | ||
page.extra = result | page.extra = result | ||
else | else | ||
page.sortkey = page.text .. mw.getCurrentFrame():expandTemplate{ title = 'Tt', args = { 'PARSING ERROR: Please ensure the argument to \'extra\' in this page\'s invocation of | page.sortkey = page.text .. mw.getCurrentFrame():expandTemplate{ title = 'Tt', args = { 'PARSING ERROR: Please ensure the argument to \'extra\' in this page\'s invocation of \'Cat\' is valid JSON' } } | ||
page.extra = {} | page.extra = {} | ||
end | end | ||
Line 65: | Line 38: | ||
-- add page to group | -- add page to group | ||
page.__index = page -- allow variants to fall back to page | |||
page.extra.__index = page.extra -- allow variants' extra to fall back to page's extra | |||
local variants = expandVariants and page.extra.variants or {{}} -- that's a table containing a single table (variant) with no properties (overrides) | |||
for _, variant in ipairs( variants ) do | |||
setmetatable( variant, page.extra ) | |||
if not variant.group then variant.group = 'default' end | |||
if not pageTree[variant.group] then pageTree[variant.group] = {} end | |||
pageTree[variant.group][#pageTree[variant.group] + 1] = setmetatable( { extra = variant }, page ) | |||
end | |||
end | end | ||
return pageTree | |||
end | |||
function buildGallery( categoryProps, pageTree ) | |||
return mw.html.create( 'div ') | |||
end | |||
function renderHList( parent, pages ) | |||
local list = parent:addClass( 'hlist' ) | |||
:tag( 'ul' ) | |||
for _, page in ipairs( pages ) do | |||
list:tag( 'li' ) | |||
:wikitext( '[[' .. page.text .. '|' .. (page.extra.name or page.sortkey or page.text) .. ']]' ) | |||
end | |||
end | |||
function buildTable( categoryProps, pageTree ) | |||
local content = mw.html.create( 'table' ) | local content = mw.html.create( 'table' ) | ||
if # | if #pageTree.default then | ||
local | local defaultCell = content:tag( 'tr' ) | ||
:tag( 'td' ) | :tag( 'td' ) | ||
:addClass( 'odd' ) | :addClass( 'odd' ) | ||
:attr( 'colspan', '2' ) | :attr( 'colspan', '2' ) | ||
:css( 'text-align', 'center' ) | :css( 'text-align', 'center' ) | ||
renderHList( | renderHList( defaultCell, pageTree.default ) | ||
end | end | ||
if | if categoryProps.groups then | ||
-- coerce it to a table for easier processing | -- coerce it to a table for easier processing | ||
local groups = type( | local groups = type(categoryProps.groups) == 'table' and categoryProps.groups or { categoryProps.groups } | ||
for index, group in ipairs(groups) do | for index, group in ipairs(groups) do | ||
if( | if( pageTree[group] ) then | ||
local row = content:tag( 'tr' ) | local row = content:tag( 'tr' ) | ||
row:tag( 'th' ) | row:tag( 'th' ) | ||
Line 90: | Line 85: | ||
:wikitext( group ) | :wikitext( group ) | ||
local cell = row:tag( 'td' ) | local cell = row:tag( 'td' ) | ||
:addClass( (index + (# | :addClass( (index + (#pageTree.default and 1 or 0)) % 2 == 0 and 'even' or 'odd' ) | ||
renderHList( cell, | renderHList( cell, pageTree[group] ) | ||
end | end | ||
end | end | ||
end | end | ||
return | return content | ||
end | |||
local Navbox = Box.new() | |||
Navbox.__index = Navbox | |||
setmetatable( Navbox, Box ) | |||
function Navbox.new( format, args ) | |||
local subject = args[1] .. ' ' .. args[2] | |||
args.class = 'navbox' | |||
args.title = subject | |||
args.edit = subject | |||
args.hide = 'show' -- TODO count number of navboxes, hide after the second or third (could relegate to the calling template) | |||
local obj = Box.new( 'light', args ) | |||
obj.format = format | |||
obj.subject = subject | |||
obj.categories = { args[1], subject, args[2] } | |||
return setmetatable( obj, Navbox ) | |||
end | |||
function Navbox:renderContent() | |||
local categoryProps = getCategoryProps( self.subject ) | |||
local pageTree = getPageTree( self.subject, self.format == 'gallery' ) | |||
local build = setmetatable( { | |||
gallery = buildGallery | |||
}, { | |||
__index = function() return buildTable end -- default | |||
} ) | |||
return build[self.format]( categoryProps, pageTree ) | |||
end | end | ||
Revision as of 00:06, June 22, 2020
Documentation for this module may be created at Module:Listbox/doc
local Box = require( 'Module:Box' ).Box function getCategoryProps( categoryName ) local categoryContent = mw.title.new( categoryName, 'Category' ):getContent() local props = {} for match in string.gmatch( categoryContent, '{{Prop|([^}]*)}}' ) do local prop, value = unpack(mw.text.split( match, '|' )) -- table if multiple values, value if one value, true if no values (i.e. flag) props[prop] = value and string.match( value, ',' ) and mw.text.split( value, ',' ) or value or true end return props end function getPageTree( categoryName, expandVariants ) -- get all pages in the category local pages = mw.ext.dpl.getPages{ category = categoryName, ordermethod = 'sortkey', order = 'ascending' } -- organize them according to metadata local pageTree = { default = {} } for _, page in ipairs( pages ) do -- get metadata if page.extra then -- remove extra from sortkey page.sortkey = string.sub( page.sortkey, 1, -string.len( page.extra ) - 2 ) local success, result = pcall( mw.text.jsonDecode, page.extra ) if success then page.extra = result else page.sortkey = page.text .. mw.getCurrentFrame():expandTemplate{ title = 'Tt', args = { 'PARSING ERROR: Please ensure the argument to \'extra\' in this page\'s invocation of \'Cat\' is valid JSON' } } page.extra = {} end else page.extra = {} end -- add page to group page.__index = page -- allow variants to fall back to page page.extra.__index = page.extra -- allow variants' extra to fall back to page's extra local variants = expandVariants and page.extra.variants or {{}} -- that's a table containing a single table (variant) with no properties (overrides) for _, variant in ipairs( variants ) do setmetatable( variant, page.extra ) if not variant.group then variant.group = 'default' end if not pageTree[variant.group] then pageTree[variant.group] = {} end pageTree[variant.group][#pageTree[variant.group] + 1] = setmetatable( { extra = variant }, page ) end end return pageTree end function buildGallery( categoryProps, pageTree ) return mw.html.create( 'div ') end function renderHList( parent, pages ) local list = parent:addClass( 'hlist' ) :tag( 'ul' ) for _, page in ipairs( pages ) do list:tag( 'li' ) :wikitext( '[[' .. page.text .. '|' .. (page.extra.name or page.sortkey or page.text) .. ']]' ) end end function buildTable( categoryProps, pageTree ) local content = mw.html.create( 'table' ) if #pageTree.default then local defaultCell = content:tag( 'tr' ) :tag( 'td' ) :addClass( 'odd' ) :attr( 'colspan', '2' ) :css( 'text-align', 'center' ) renderHList( defaultCell, pageTree.default ) end if categoryProps.groups then -- coerce it to a table for easier processing local groups = type(categoryProps.groups) == 'table' and categoryProps.groups or { categoryProps.groups } for index, group in ipairs(groups) do if( pageTree[group] ) then local row = content:tag( 'tr' ) row:tag( 'th' ) :addClass( 'label' ) :wikitext( group ) local cell = row:tag( 'td' ) :addClass( (index + (#pageTree.default and 1 or 0)) % 2 == 0 and 'even' or 'odd' ) renderHList( cell, pageTree[group] ) end end end return content end local Navbox = Box.new() Navbox.__index = Navbox setmetatable( Navbox, Box ) function Navbox.new( format, args ) local subject = args[1] .. ' ' .. args[2] args.class = 'navbox' args.title = subject args.edit = subject args.hide = 'show' -- TODO count number of navboxes, hide after the second or third (could relegate to the calling template) local obj = Box.new( 'light', args ) obj.format = format obj.subject = subject obj.categories = { args[1], subject, args[2] } return setmetatable( obj, Navbox ) end function Navbox:renderContent() local categoryProps = getCategoryProps( self.subject ) local pageTree = getPageTree( self.subject, self.format == 'gallery' ) local build = setmetatable( { gallery = buildGallery }, { __index = function() return buildTable end -- default } ) return build[self.format]( categoryProps, pageTree ) end local p, mt = {}, {} function p._main( format, args ) local navbox = Navbox.new( format, args ) return navbox:render() end -- translates p.function( frame ) to p._main( function, args ) function mt.__index( table, key ) return function ( frame ) return table._main( key, frame.args ) end end -- for use in the debug console: -- =p.list(p.debugframe) p.debugframe = { args = { [1] = "The Legend of Zelda", [2] = "Enemies", } } return setmetatable( p, mt )