Module:UnSignpost wrapper

From Uncyclopedia, the content-free encyclopedia
Jump to navigation Jump to search

local p = {}

local getArgs = require('Module:Arguments').getArgs

-- ==================================================
-- Utilities
-- ==================================================

--- Build a no-ping user link, replicating {{no ping|Username}}.
--- Uses the same mw.uri.fullUrl approach as Module:No ping.
local function noPing(username)
	if not username or username == '' then
		return ''
	end
	local url = tostring(mw.uri.fullUrl(mw.site.namespaces.User.name .. ':' .. username))
	return '<span class="plainlinks">[' .. url .. ' ' .. username .. ']</span>'
end

--- Format a list of author names with proper comma/and joining.
--- Uses noPing to avoid triggering talk page notifications.
--- 1 author:  "By Author1"
--- 2 authors: "By Author1&nbsp;and Author2"
--- 3 authors: "By Author1, Author2&nbsp;and Author3"
local function formatAuthors(authors)
	if not authors or #authors == 0 then
		return nil
	end

	local links = {}
	for i, name in ipairs(authors) do
		links[i] = noPing(name)
	end

	local n = #links
	if n == 1 then
		return 'By ' .. links[1]
	elseif n == 2 then
		return 'By ' .. links[1] .. '&nbsp;and ' .. links[2]
	else
		return 'By ' .. table.concat(links, ', ', 1, n - 1) ..
			'&nbsp;and ' .. links[n]
	end
end

local function collectNumbered(args, prefix)
	local t = {}
	local i = 1
	while args[prefix .. i] do
		t[#t + 1] = args[prefix .. i]
		i = i + 1
	end
	return t
end

-- ==================================================
-- Data Collection
-- ==================================================

--- Collect all authors for a given story index.
--- Primary author: "authorN", additional: "authorN-2", "authorN-3", ...
local function collectAuthors(args, storyIndex)
	local authors = {}
	local primary = args['author' .. storyIndex]
	if not primary or primary == '' then
		return authors
	end
	authors[1] = primary
	local j = 2
	while true do
		local a = args['author' .. storyIndex .. '-' .. j]
		if not a or a == '' then break end
		authors[#authors + 1] = a
		j = j + 1
	end
	return authors
end

local function collectStories(args)
	local t = {}
	local i = 1
	while args['headline' .. i] do
		t[#t + 1] = {
			headline = args['headline' .. i],
			authors  = collectAuthors(args, i),
			story    = args['story' .. i]
		}
		i = i + 1
	end
	return t
end

local function collectQA(args)
	local t = {}
	local i = 1
	while args['q' .. i] do
		t[#t + 1] = {
			q = args['q' .. i],
			u = args['u' .. i],
			a = args['a' .. i]
		}
		i = i + 1
	end
	return t
end

local function collectLogs(args)
	local t = {}
	for i = 1, 5 do
		t[i] = args['log' .. i]
	end
	return t
end

local function collectVFH(args)
	if not args.vfh1 then
		return nil
	end

	return {
		top = {
			{args.vfh1, args.for1, args.against1},
			{args.vfh2, args.for2, args.against2},
			{args.vfh3, args.for3, args.against3}
		},
		highlight = {args.vfh4, args.for4, args.against4}
	}
end

-- ==================================================
-- Renderers
-- ==================================================

local function renderStories(frame, parent, stories)
	for _, s in ipairs(stories) do
		parent:tag('div')
			:addClass('unsignpost-headline')
			:wikitext(s.headline)

		local byline = formatAuthors(s.authors)
		if byline then
			parent:tag('div')
				:addClass('unsignpost-author')
				:wikitext(byline)
		end

		parent:tag('div')
			:addClass('unsignpost-story')
			:wikitext('\n' .. (s.story or '') .. '\n')
	end
end

local function renderBiopic(parent, args)
	if not args.biopic then return end

	local section = parent:tag('div')
		:addClass('unsignpost-section unsignpost-biopic')

	section:tag('div')
		:addClass('unsignpost-headline')
		:wikitext('Biopic')

	if args['biopic-about'] then
		section:tag('div')
			:addClass('unsignpost-author')
			:wikitext('Who is ' .. args['biopic-about'] .. '?')
	end

	section:tag('div')
		:addClass('unsignpost-story')
		:wikitext('\n' .. args.biopic .. '\n')
end

local function renderQA(frame, parent, args)
	local qa = collectQA(args)
	if #qa == 0 then return end

	local section = parent:tag('div')
		:addClass('unsignpost-section unsignpost-ask')

	section:tag('div')
		:addClass('unsignpost-headline')
		:wikitext(args.ask or '[[Forum:Ask Turb0|Ask Turb0]]')

	local story = section:tag('div')
		:addClass('unsignpost-story')

	local ul = story:tag('ul')

	for i, item in ipairs(qa) do
		ul:tag('li')
			:wikitext(item.q .. ' — ' .. noPing(item.u))
		ul:tag('li')
			:css('margin-left', '1rem')
			:tag('b')
				:wikitext(item.a or '')

		if i < #qa then
			ul:wikitext('\n'):tag('hr')
			ul:wikitext('\n')
		end
	end
end

local function renderLogs(parent, args)
	local section = parent:tag('div')
		:addClass('unsignpost-section unsignpost-logs')

	section:tag('div')
		:addClass('unsignpost-headline')
		:wikitext('From The Logs')

	local story = section:tag('div')
		:addClass('unsignpost-story')

	local logs = collectLogs(args)
	local defaults = {
		'[[File:Tumbleweed01.gif|120px]]',
		'[[File:Tumbleweed01.gif|120px]]',
		'[[File:tumbleweed01.gif|120px]]',
		'[[File:tumbleweed01.gif|120px]]',
		'[[File:tumbleweed01.gif|120px]]'
	}

	story:wikitext('\n')

	for i = 1, 5 do
		story:wikitext('* ' .. (logs[i] or defaults[i]) .. '\n')

		if i < 5 then
			story:wikitext('<hr>\n')
		end
	end

	story:wikitext('\n')
end

local function renderDeemox(parent, args)
	if not args.deemox then return end

	local section = parent:tag('div')
		:addClass('unsignpost-section unsignpost-deemox')

	section:tag('div')
		:addClass('unsignpost-headline')
		:wikitext("Deemox's Gossip Corner")

	section:tag('div')
		:addClass('unsignpost-story')
		:wikitext('\n' .. args.deemox .. '\n')
end

local function renderVFH(parent, args)
	local vfh = collectVFH(args)
	if not vfh then return end

	local section = parent:tag('div')
		:addClass('unsignpost-section unsignpost-vfh')

	section:tag('div')
		:addClass('unsignpost-headline')
		:wikitext('Top VFH Competitors')

	local story = section:tag('div')
		:addClass('unsignpost-story')

	story:wikitext('\n')

	for _, item in ipairs(vfh.top) do
		if item[1] then
			story:wikitext('* [[' .. item[1] .. ']] (' ..
				(item[2] or '') .. '/' .. (item[3] or '') .. ')\n')
		end
	end

	section:tag('div')
		:addClass('unsignpost-headline')
		:wikitext('VFH Highlight Of The Week')

	local highlight = section:tag('div')
		:addClass('unsignpost-story')

	highlight:wikitext('\n')

	if vfh.highlight[1] then
		highlight:wikitext('* [[' .. vfh.highlight[1] .. ']] (' ..
			(vfh.highlight[2] or '') .. '/' ..
			(vfh.highlight[3] or '') .. ')\n')
	end

	highlight:wikitext('\n')
end

local function renderForums(parent, args)
	local forums = collectNumbered(args, 'forum')
	if #forums == 0 then return end

	local section = parent:tag('div')
		:addClass('unsignpost-section unsignpost-forum')

	section:tag('div')
		:addClass('unsignpost-headline')
		:wikitext('From The Forums')

	local story = section:tag('div')
		:addClass('unsignpost-story')

	story:wikitext('\n')

	for _, f in ipairs(forums) do
		story:wikitext('* [[' .. f .. ']]\n')
	end

	story:wikitext('\n')
end

local function renderSignpostNews(parent, args)
	if not args.signpostnews then return end

	local section = parent:tag('div')
		:addClass('unsignpost-section unsignpost-meta')

	section:tag('div')
		:addClass('unsignpost-headline')
		:wikitext('UnSignpost News')

	section:tag('div')
		:addClass('unsignpost-story')
		:wikitext('\n' .. args.signpostnews .. '\n')
end

local function renderQuote(frame, parent, args)
	local section = parent:tag('div')
		:addClass('unsignpost-section unsignpost-quotes')

	section:tag('div')
		:addClass('unsignpost-headline')
		:wikitext('Quote(s) of the Week')

	local quoteText = args.quote
	if not quoteText or quoteText == '' then
		quoteText = args.ircquote
		if not quoteText or quoteText == '' then
			-- Default: {{Q|{{WildeQuotes}}|[[Oscar Wilde]]}}
			local wildeQuote = frame:expandTemplate{
				title = 'WildeQuotes'
			}
			quoteText = frame:expandTemplate{
				title = 'Q',
				args = { wildeQuote, '[[Oscar Wilde]]' }
			}
		end
	end

	section:tag('div')
		:addClass('unsignpost-story')
		:wikitext('\n' .. quoteText .. '\n')
end

local function renderThing(parent, args)
	if not args.thing then return end

	local section = parent:tag('div')
		:addClass('unsignpost-section unsignpost-thing')

	section:tag('div')
		:addClass('unsignpost-headline')
		:wikitext(args.thing .. ' of the week #' .. (args.thingnumber or '1'))

	section:tag('div')
		:addClass('unsignpost-story')
		:wikitext('\n' .. (args.thing2 or 'Because this is here now') .. '\n')
end

local function renderFootnotes(frame, parent)
	local section = parent:tag('div')
		:addClass('unsignpost-section unsignpost-footnotes')

	section:tag('div')
		:addClass('unsignpost-headline')
		:wikitext('Notes')

	local refs = frame:expandTemplate{
		title = 'reflist',
		args = { group = 'note' }
	}

	section:tag('div')
		:addClass('unsignpost-story')
		:wikitext('\n' .. (refs or '') .. '\n')
end

-- ==================================================
-- Main
-- ==================================================

function p.main(frame)
	local args = getArgs(frame)
	local stories = collectStories(args)

	local styles = frame:extensionTag(
		'templatestyles',
		'',
		{ src = 'Template:UnSignpost wrapper/styles.css' }
	)

	-- Use expandTemplate for the slogan
	local slogan = frame:expandTemplate{
		title = 'Uncyclopedia:UnSignpost/slogan',
		args = { '1' }
	}

	-- Default for funny param matches template: {{Uncyclopedia:UnSignpost/slogan}}
	local funny = args.funny
	if not funny or funny == '' then
		funny = frame:expandTemplate{
			title = 'Uncyclopedia:UnSignpost/slogan'
		}
	end

	local root = mw.html.create('div')
		:addClass('unsignpost-container')

	root:tag('div')
		:addClass('unsignpost-banner')
		:wikitext('[[Uncyclopedia:UnSignpost|The UnSignpost]]')

	root:tag('div')
		:addClass('unsignpost-slogan')
		:wikitext(slogan)

	local body = root:tag('div')
		:addClass('unsignpost-body NavFrame')

	body:tag('div')
		:addClass('unsignpost-head NavHead')
		:wikitext((args.date or 'January 1, 1970') ..
			' • Issue #' .. (args.number or '') ..
			' • ' .. funny ..
			'<hr>' ..
			'[[Uncyclopedia:UnSignpost/current|Current issue]]  • ' ..
			'[[Uncyclopedia:UnSignpost/Archives|Archives]] • ' ..
			'[[Uncyclopedia:UnSignpost/Press Room|Press Room]]')

	local content = body:tag('div')
		:addClass('unsignpost-content NavContent')
		:css('scrollbar-width', 'thin')

	local storiesSection = content:tag('div')
		:addClass('unsignpost-section unsignpost-stories')

	renderStories(frame, storiesSection, stories)
	renderBiopic(content, args)
	renderQA(frame, content, args)
	renderLogs(content, args)
	renderDeemox(content, args)
	renderVFH(content, args)
	renderForums(content, args)
	renderSignpostNews(content, args)
	renderQuote(frame, content, args)
	renderThing(content, args)
	renderFootnotes(frame, content)

	return styles .. tostring(root)
end

return p