Module:Subpages

local sp = {}

local sbh = require('Module:Subpages-helper').sbh

local currentTitle = mw.title.getCurrentTitle

local pageorder = { ["troll"] = { "Adventure", "Ancestor", "Gallery", "Hive", "Inventory", "Land", "Lusus", "Relationships", "Specibus", "Sprite", "Quotes" },	["nontroll"] = { "Adventure", "Ancestor", "Gallery", "House", "Inventory", "Land", "Guardian", "Relationships", "Specibus", "Sprite", "Quotes" } } local crowners = { ["troll"] = { }, ["nontroll"] = { } } local crownername = { ["troll"]    = "By Medium", ["nontroll"] = "Crowners" } local addns = { ["troll"]  = { }, ["nontroll"]   = { } }

-- localize functions local insert = table.insert local concat = table.concat local find = string.find local len = string.len local sub = string.sub local rep = string.rep local listlevel = { '*', '**', '***', '****', '*****' }

local function expandArg(args, key) -- Emulate how unspecified template parameters appear in wikitext. If the -- specified argument exists, its value is returned, and if not the argument -- name is returned inside triple curly braces. local val = args[key] if val then return val else return string.format('', key) end end

local function getPages(args) local pages = {} pages.root = args.rootpage or currentTitle.prefixedText pages.subpage = pages.root .. '/' .. expandArg(args, 'subpage') return pages end

-- This function is the main page menu type, with dropdowns for subpages function sp.menu ( frame ) local page	  = frame.args[1] or frame:callParserFunction('TOPLEVELPAGE') local template = frame.args[2] or "nontroll" local wppage  = frame.args[3] or page local nowp    = (frame.args[4] ~= "" ) if wppage == "" then wppage = page end

-- create variant top level page variables local mainpage = page; if template == "index" then template = "troll" crowners["troll"] = {} mainpage = ":" .. page page = page:gsub("Category:", "", 1) end local pageslash = page..'/'

if pageorder[template] == nil then return "Module error: invalid template argument" end

local allsptxt = sbh.subpages(page)('SUBPAGES', { page, sep = "|" }) local subpage_list = split(allsptxt, "|")

local tree = build_tree(page, subpage_list)

-- initialize result with Main link local linkout = { '* Main\n' } local crownerout = { } local otherout  = { } local missingout = { } local linkns   = { } local missingns = { }

for _, subpage in ipairs(pageorder[template]) do		text = build_list( { [subpage] = tree[subpage] }, pageslash, 1 ) if text ~= '' then insert(linkout, text) else insert(missingout, subpage) end tree[subpage] = nil end for _, subpage in ipairs(crowners[template]) do		text = build_list( { [subpage] = tree[subpage] }, pageslash, 2 ) if text ~= '' then -- Don't use "by medium" section on works because it's too hard to list -- everything, but do provide a standard selection for the create page menu below if template ~= 'troll' then insert(crownerout, text) end else insert(missingout, subpage) end tree[subpage] = nil end --deal with the leftover subpages if next(tree) then local ordered_keys = {} for k in pairs(tree) do			insert(ordered_keys, k)		end table.sort(ordered_keys)

for i = 1, #ordered_keys do			local subpage = ordered_keys[i] text = build_list( { [subpage] = tree[subpage] }, pageslash, 2 ) if text ~= '' then insert(otherout, text) end end end

for _, ns in ipairs(addns[template]) do		local tobj = mw.title.new( page, ns ) if tobj.exists then insert(linkns, '* '..ns .. '\n') else insert(missingns, ns) end end

local jsdata = ' '	local crowner_link = next(crownerout) and '*  '..crownername[template]..'\n' or '' local all_sp_link = '* All Subpages\n' local italictitle = ( template == "work" ) and italictitle(frame, page) or ''

return concat(linkout) .. concat(linkns) .. crowner_link .. concat(crownerout) .. all_sp_link .. concat(otherout) .. '* Create New \n' .. jsdata .. italictitle end

-- Another output function, which makes an ordinary bullet tree of subpages function sp.tree ( frame ) local page	 = frame.args[1] or frame:callParserFunction('TOPLEVELPAGE') local filter = frame.args['filter'] or ''

local allsptxt = frame:callParserFunction('SUBPAGES', { page, sep = "|" }) local subpage_list = split(allsptxt, "|")

local tree = build_tree(page, subpage_list)

if filter ~= '' then for _, subpage in ipairs(pageorder[filter]) do tree[ subpage ] = nil end if filter ~= 'troll' then for _, subpage in ipairs(crowners[filter]) do tree[ subpage ] = nil end end end

if page:match("^Category:") then page = ":"..page end local thispage = mw.title.getCurrentTitle.text ~= page and "; "..page.."\n" or '' return thispage .. build_list( tree, page..'/', 1 ) end

-- transforms an array (table) of subpages into a tree data structure function build_tree ( page, subpage_list ) local path_tree = { } local pagelenoffset = len(page) + 2

for _, fullpath in ipairs(subpage_list) do		local path = sub(fullpath, pagelenoffset) local list = split(path, '/') local lastdir = path_tree for i, dir in ipairs(list) do			if lastdir[dir] == nil then lastdir[dir] = { } end lastdir = lastdir[dir] end end return path_tree end

-- given a tree of subpages, outputs an indented list -- recursively calls itself to build deeper trees function build_list ( tree, prefix, level ) local libase = listlevel[level] or rep('*', level) local ul = {}

local ordered_sp = {} for page in pairs(tree) do		insert(ordered_sp, page) end table.sort(ordered_sp)

for i = 1, #ordered_sp do		local page = ordered_sp[i] local branch = tree[page] local li		if level <= 2 then li = libase .. " '..page..'\n' else li = libase ..' '..page..'\n' end insert(ul, li)

if next(branch) then local nextprefix = (prefix..page..'/') insert(ul, build_list(branch, nextprefix, level+1)) end end return concat(ul) end

-- split implementation reproduced from, uh, somewhere function split(str, sSeparator, nMax, bRegexp) assert(sSeparator ~= '') assert(nMax == nil or nMax >= 1)

local aRecord = {}

if len(str) > 0 then local bPlain = not bRegexp nMax = nMax or -1

local nField=1 nStart=1 local nFirst,nLast = find(str, sSeparator, nStart, bPlain) while nFirst and nMax ~= 0 do			aRecord[nField] = sub(str, nStart, nFirst-1) nField = nField+1 nStart = nLast+1 nFirst,nLast = find(str, sSeparator, nStart, bPlain) nMax = nMax-1 end aRecord[nField] = sub(str, nStart) end

return aRecord end

-- for work type pages, italicizes the title of the work function italictitle(frame, basepage) local title = mw.title.getCurrentTitle

-- don't italicize subpages -- but we can't just naively split on '/' due to top level pages with slashes local subpages = (len(title.text) > len(basepage)) and sub(title.text, len( mw.text.decode(basepage, 1))+1 ) or '' -- Find the parts before and after the disambiguation parentheses, if any. local prefix, parentheses = mw.ustring.match(basepage, '^(.+) (%([^%(%)]+%))$')

-- If parentheses were found, italicise only the part before them. Otherwise -- italicise the whole title. local result if prefix and parentheses then result = "''" .. prefix .. "'' " .. parentheses .. subpages else result = "''" .. basepage .. "''" .. subpages end

-- Add the namespace if we're not in mainspace. if title.namespace ~= 0 then result = mw.site.namespaces[title.namespace].name .. ':' .. result end

-- Call displaytitle with the text we generated. return mw.getCurrentFrame:callParserFunction(		'DISPLAYTITLE',		result		) end

return sp