Module:Listing: Difference between revisions
Jump to navigation
Jump to search
Want an adless experience? Log in or Create an account.
(comment out some things to try to reduce cpu usage... this doesn't seem like it should be so expensive though) |
(remove remaining staging checks (WW Enemies, HW Characters). Migration is complete.) |
||
(18 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
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 ) | |||
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 | |||
-- determine if line is a category | |||
local cat = string.match( line, '^%s*%[%[Category:(.-)]]%s*$' ) | |||
cat = cat and mw.text.split( cat, '|' )[1] | |||
return currentSection, cat | |||
end | |||
local Navbox = Box.new() | |||
Navbox.__index = Navbox | |||
setmetatable( Navbox, Box ) | |||
function Navbox.new( args ) | |||
local subject = args[2] and (args[1] .. ' ' .. args[2]) or args[1] | |||
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[2] and { args[1], subject, args[2] } or {} -- will be set later when parsing the page | |||
return setmetatable( obj, Navbox ) | |||
end | |||
local p = {} | local p = {} | ||
function p._parseListing( pageName ) | p.Navbox = Navbox | ||
local pageContent = mw. | |||
function p._parseListing( pageName, pageContent ) | |||
local pageContent = pageContent or mw.text.killMarkers( mw.getCurrentFrame():expandTemplate{ title = ':' .. pageName, args = {} } ) | |||
local root = { | local root = { | ||
level = 1, | level = 1, | ||
Line 8: | Line 87: | ||
content = "", | content = "", | ||
summary = "", | summary = "", | ||
sections = {} | sections = {}, | ||
categories = {}, | |||
topLevelLeaves = {}, -- i.e. L2 sections with no children | |||
groups = {} -- i.e. L2 sections that have children | |||
} | } | ||
local currentSection = root | local currentSection = root | ||
local cat = nil | |||
-- can't think of a regex to split sections so go line by line | -- can't think of a regex to split sections so go line by line | ||
for line in | for line in gsplit( pageContent, '\n' ) do | ||
currentSection, cat = handleLine( line, currentSection ) | |||
if | if cat and cat ~= "Listings" then root.categories[#root.categories + 1] = cat end | ||
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 | ||
end | end | ||
Line 63: | Line 129: | ||
p.debugFrame = { | p.debugFrame = { | ||
args = { | args = { | ||
[1] = ' | [1] = 'The Legend of Zelda Locations' | ||
} | } | ||
} | } |
Latest revision as of 03:10, August 14, 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 ) 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 -- determine if line is a category local cat = string.match( line, '^%s*%[%[Category:(.-)]]%s*$' ) cat = cat and mw.text.split( cat, '|' )[1] return currentSection, cat end local Navbox = Box.new() Navbox.__index = Navbox setmetatable( Navbox, Box ) function Navbox.new( args ) local subject = args[2] and (args[1] .. ' ' .. args[2]) or args[1] 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[2] and { args[1], subject, args[2] } or {} -- will be set later when parsing the page return setmetatable( obj, Navbox ) end local p = {} p.Navbox = Navbox function p._parseListing( pageName, pageContent ) local pageContent = pageContent or mw.text.killMarkers( mw.getCurrentFrame():expandTemplate{ title = ':' .. pageName, args = {} } ) local root = { level = 1, name = pageName, content = "", summary = "", sections = {}, categories = {}, topLevelLeaves = {}, -- i.e. L2 sections with no children groups = {} -- i.e. L2 sections that have children } local currentSection = root local cat = nil -- can't think of a regex to split sections so go line by line for line in gsplit( pageContent, '\n' ) do currentSection, cat = handleLine( line, currentSection ) if cat and cat ~= "Listings" then root.categories[#root.categories + 1] = cat end 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