Module:Listbox: Difference between revisions

From Zelda Dungeon Wiki
Jump to navigation Jump to search
Want an adless experience? Log in or Create an account.
(couple bugfixes with table)
(parse extra as json)
Line 49: Line 49:
   local pagetree = { default = {} }
   local pagetree = { default = {} }
   for _, page in ipairs( pages ) do
   for _, page in ipairs( pages ) do
     -- parse extra
     -- get metadata
    local extra = page.extra
    if page.extra then
    page.extra = {}
      -- remove extra from sortkey
      page.sortkey = string.sub( page.sortkey, 1, -string.len( page.extra ) - 2 )


    if extra then
       local success, result = pcall( mw.text.jsonDecode, page.extra )
       for prop in mw.text.gsplit( extra, ',' ) do
      if success then
        if prop then
        page.extra = result
          local propvalue = mw.text.split( prop, ':' )
      else
          page.extra[propvalue[1]] = propvalue[2] or true -- for valueless flags use true
        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' } }
        end
        page.extra = {}
       end
       end
 
    else page.extra = {}
      -- remove extra from sortkey
      page.sortkey = string.sub( page.sortkey, 1, -string.len( extra ) - 2 )
     end
     end



Revision as of 23:05, June 21, 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 renderHList(parent, pages)
  local list = parent:addClass( 'hlist' )
    :tag( 'ul' )
  for _, page in ipairs(pages) do
    list:tag( 'li' )
      :wikitext( '[[' .. page.text .. '|' .. (page.sortkey or page.text) .. ']]' )
  end
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.subject = subject
  obj.categories = { args[1], subject, args[2] }
  return setmetatable( obj, Navbox )
end

function Navbox:renderContent()
  local catprops = getCategoryProps( self.subject )

  -- get list of pages in the category
  local pages = mw.ext.dpl.getPages{ category = self.subject, 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
    if not page.extra.group then page.extra.group = 'default' end
    if not pagetree[page.extra.group] then pagetree[page.extra.group] = {} end
    pagetree[page.extra.group][#pagetree[page.extra.group] + 1] = page
  end

  -- build the table
  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 catprops.groups then
    -- coerce it to a table for easier processing
    local groups = type(catprops.groups) == 'table' and catprops.groups or { catprops.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 tostring( content )
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 )