Module:Listing: Difference between revisions

From Zelda Dungeon Wiki
Jump to navigation Jump to search
Want an adless experience? Log in or Create an account.
(handle transclusion (yikes). limitation: this expands templates in the transcluded page, which makes looking for things like {{Main}} harder.)
(strip {{{params|}}})
Line 25: Line 25:


function handleLine( line, currentSection )
function handleLine( line, currentSection )
  line = line:gsub( '{{{.-|}}}', '' ) -- can appear on listings that are transcluded into other listings, but are only relevant to those other listings
   -- recurse on transclusion
   -- recurse on transclusion
   local transcludedTitle, args = line:match( '^{{:(.-)|(.-)}}$' )
   local transcludedTitle, args = line:match( '^{{:(.-)|(.-)}}$' )

Revision as of 04:08, July 26, 2020

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

local Args = require( 'Module:Args' )
local Box = require( 'Module:Box' ).Box

-- got this from http://lua-users.org/wiki/SplitJoin
-- idk how it works but it's 100x more performant than mw.text.gsplit
function gsplit(s,sep)
   local lasti, done, g = 1, false, s:gmatch('(.-)'..sep..'()')
   return function()
      if done then
         return
      end
      local v,i = g()
      if s == '' or sep == '' then
         done = true
         return s
      end
      if v == nil then
         done = true
         return s:sub(lasti)
      end
      lasti = i
      return v
   end
end

function handleLine( line, currentSection )
  line = line:gsub( '{{{.-|}}}', '' ) -- can appear on listings that are transcluded into other listings, but are only relevant to those other listings
  -- recurse on transclusion
  local transcludedTitle, args = line:match( '^{{:(.-)|(.-)}}$' )
  if transcludedTitle then
    local transcludedContent = mw.text.killMarkers( mw.getCurrentFrame():expandTemplate{ title = ':' .. transcludedTitle, args = { [1] = args } } )
    for transcludedLine in gsplit( transcludedContent, '\n' ) do
      currentSection = handleLine( transcludedLine, currentSection )
    end

    return currentSection
  end

  local headingLevel, headingText = string.match( line, '^%s*(=+)%s*(.-)%s*=+$' )
  if headingLevel then -- line is a heading
    local newSection = {
      level = #headingLevel,
      name = headingText,
      content = "",
      summary = "",
      sections = {}
    }

    -- find the right parent and insert
    while currentSection.level >= #headingLevel do
      currentSection = currentSection.parent
    end
    newSection.parent = currentSection
    currentSection.sections[#currentSection.sections + 1] = newSection
    currentSection = newSection
  elseif #currentSection.sections == 0 then -- no child headings yet so this is part of the summary of the current section
    currentSection.summary = currentSection.summary .. line .. '\n'
  end

  -- add to content of all parent sections, plus current section if line isn't a heading
  local contentBackfillSection = headingLevel and currentSection.parent or currentSection
  repeat
    contentBackfillSection.content = contentBackfillSection.content .. line .. '\n'
    contentBackfillSection = contentBackfillSection.parent
  until not contentBackfillSection

  return currentSection
end

local Navbox = Box.new()
Navbox.__index = Navbox
setmetatable( Navbox, Box )

function Navbox.new( args )
  local subject = args[1] .. ' ' .. args[2]
  args.class = 'navbox'
  args.title = '[[' .. subject .. ']]'
  args.edit = subject
  args.hide = args.hide or 'show'
  local obj = Box.new( 'light', args )
  obj.subject = subject
  obj.categories = { args[1], subject, args[2] }
  return setmetatable( obj, Navbox )
end

local p = {}

p.Navbox = Navbox

function p._parseListing( pageName, pageContent )
  local pageContent = pageContent or mw.title.new( pageName ):getContent()
  local root = {
    level = 1,
    name = pageName,
    content = "",
    summary = "",
    sections = {},
    topLevelLeaves = {}, -- i.e. L2 sections with no children
    groups = {} -- i.e. L2 sections that have children
  }
  local currentSection = root

  -- can't think of a regex to split sections so go line by line
  for line in gsplit( pageContent, '\n' ) do
    currentSection = handleLine( line, currentSection )
  end

  -- split sections into top-level items and groups with second-level items
  for _, section in ipairs( root.sections ) do
    if #section.sections > 0 then
      root.groups[#root.groups + 1] = section
    else
      root.topLevelLeaves[#root.topLevelLeaves + 1] = section
    end
  end

  return root
end

function p.bullets( frame )
  local listing = p._parseListing( frame.args[1] )
  local bullets = mw.html.create( 'ul' )
  for _, section in ipairs( listing.sections ) do
    local sublist = bullets:tag( 'li' )
      :wikitext( section.name )
      :tag( 'ul' )
    for _, subsection in ipairs( section.sections ) do
      sublist:tag( 'li' ):wikitext( subsection.name )
    end
  end
  return tostring( bullets )
end

p.debugFrame = {
  args = {
    [1] = 'The Legend of Zelda Locations'
  }
}

p.debugContent = [[
Summary {{Infobox|thing=value}}

== First Section ==
Section 1 summary {{Template|prop=val}}

=== Subsection of First Section ===
Subsection 1 content {{Template|prop=val}}

== Second Section ==
Section 2 summary {{Template|prop=val}}

=== Subsection of Second Section ===
Subsection 2 content {{Template|prop=val}}

{{Cat}}
]]

return p