Module:Subpages 5

Everything About Fiction You Never Wanted to Know.

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

local sp = {}

local pageorder = {
	["trope"] = {
		"Analysis", "Haiku", "Headscratchers", "Image Links", "Laconic", "Playing With",
		"Quotes", "Useful Notes"
	},
	["work"] = {
		"Analysis", "Characters", "Laconic", "Recap", "Trivia", "Setting", "YMMV",
		"Fridge", "Fanfic Recs", "Haiku", "Headscratchers", "Ho Yay", "Image Links",
		"Memes", "Radar", "Quotes", "Source", "Useful Notes", "WMG"
	},
	["creator"] = {"YMMV", "Quotes", "Fanfic Recs", "Analysis", "Trivia", "WMG", "Image Links", "Haiku", "Laconic"}
}
local crowners = {
	["trope"] = { "Animation", "Animated Films", "Anime", "Anime and Manga", "Board Games", "Comics", "Comic Books",
		"Fan Works", "Fanfic", "Fanfiction", "Fan Fiction", "Film", "Folklore", "Literature",
		"Live Action Television", "Live Action TV", "Machinima",
		"Manga", "Manga and Anime", "Music", "Musicians", "New Media",
		"Opera", "Professional Wrestling", "Puppet Shows", "Radio", "Tabletop Games", "Tabletop RPGs",
		"Television", "TV",
		"Theatre", "Theater", "Toys", 
		"Webcomics", "Video Games", "Visual Art", "Visual Novels",
		"Web Original", "Web Animation", "Web Comics", "Websites",
		"Western Animation", "Wikis", "Wrestling", "Other", "Real Life" },
	["work"] = { "Awesome", "Funny", "Heartwarming", "Nightmare Fuel", "Tear Jerker" },
	["creator"] = { "Awesome", "Funny", "Heartwarming", "Nightmare Fuel", "Tear Jerker" }
}
local crownername = {
	["trope"]   = "By Medium",
	["work"]    = "Crowners",
	["creator"] = "Crowners"
}
local addns = {
	["trope"]   = { },
	["work"]    = { "Reviews" },
	["creator"] = { }
}

-- 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 = { '*', '**', '***', '****', '*****' }

-- 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 "work"
	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 = "trope"
		crowners["trope"] = {}
		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 = frame:callParserFunction('SUBPAGES', { page, sep = "|" })
	local subpage_list = split(allsptxt, "|")

	local tree = build_tree(page, subpage_list)

	-- initialize result with Main link
	local linkout = { '* [[' .. mainpage .. '|<span id="tm-main"></span>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
			insert(crownerout, text)
		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, '* [[' .. tobj.fullText .. '|<span id="tm-'..ns..'"></span>'..ns .. ']]\n')
		else
			insert(missingns, ns)
		end
	end

	local jsdata = '<div id="tm-data" style="display:none" '
		.. 'data-toplevelpage="' .. page .. '" '
		.. 'data-wanted="'	   .. concat( missingout, "&#9;" ) .. '" '
		.. 'data-nswanted="'  .. concat( missingns, "&#9;" ) .. '" '
		.. 'data-templatetype="' .. template .. '" '
		.. '></div>'
	local crowner_link = next(crownerout)
		and '* [[#top|<span id="tm-' .. crownername[template].. '"></span>'..crownername[template]..']]\n'
		or ''
	local wikipedia_link = nowp
		and ''
		or "* [[wikipedia:" .. wppage ..
		'|<span id="tm-Wikipedia"'.. (frame.args[3] == "" and ' class="tm-wpdefault"' or '') ..'></span>Wikipedia]]\n'
	local all_sp_link = '* [[Special:PrefixIndex/' .. pageslash .. '|<span id="tm-Allothers"></span>All Subpages]]\n'
	local italictitle = ( template == "work" )
		and italictitle(frame, page)
		or ''

	return concat(linkout)
		.. concat(linkns)
		.. crowner_link
		.. concat(crownerout)
		.. wikipedia_link
		.. all_sp_link
		.. concat(otherout)
		.. '* <strong><span id="tm-New"></span>Create New</strong><ul id="tm-wantedpages"></ul>\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 allsptxt = frame:callParserFunction('SUBPAGES', { page, sep = "|" })
	local subpage_list = split(allsptxt, "|")

	local tree = build_tree(page, subpage_list)

	if page:match("^Category:") then page = ":"..page end
	return "; [["..page.."]]\n" ..	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 .. " [["..prefix..page..'|<span id="tm-'..page..'"></span>'..page..']]\n'
		else
			li = libase ..' [['..prefix..page..'|'..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