Puzzle Potato Dry Brush.png
UnNews Logo Potato1.png

Welcome to the Mother Ship of amateur comedy writing! (Amateur means we don't pay you to do it.)

This is where the original Uncyclopedia wound up. You might as well pick a user name. We have no "partners" that want to sell you stuff. Giving your email simply lets you recover your password; we don't send spam. Uncyclopedians get a talk page, private edit area, and a welcome, maybe, if you actually edit; and we won't de-platform you for your views, if they're funny.


Module:Listen

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

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

-- This module implements {{listen}}.

local mFileLink = require('Module:File link')
local mTableTools = require('Module:TableTools')
local mSideBox = require('Module:Side box')
local lang = mw.language.new('en')

local p = {}

function p.main(frame)
	local origArgs = frame:getParent().args
	local args = {}
	for k, v in pairs(origArgs) do
		if v ~= '' then
			args[k] = v
		end
	end
	return p._main(args)
end

function p._main(args)
	-- Find whether we are outputting a plain or an embedded box.
	local isPlain = args.plain == 'yes'
	local isEmbedded = args.embed and true
	local hasMissing, previewWarning

	-- Organise the arguments by number.
	local numArgs, missingFiles = {}, {}
	do
		local origNumArgs = mTableTools.numData(args)
		origNumArgs[1] = origNumArgs.other -- Overwrite args.filename1 etc. with args.filename etc.
		origNumArgs = mTableTools.compressSparseArray(origNumArgs)
		for i, t in ipairs(origNumArgs) do
			-- Check if the files exist.
			local obj = t.filename and mw.title.new('Media:' .. t.filename)
			if obj and obj.exists then
				t.length = t.length ~= 'hide' and obj.file.length
				numArgs[#numArgs + 1] = t
			else
				missingFiles[#missingFiles + 1] = t.filename or i
			end
		end
	end

	-- Render warning
	hasMissing = #missingFiles ~= 0
	if hasMissing then
		for i, v in ipairs(missingFiles) do
			missingFiles[i] = type(v) == 'string'
				and string.format('missing file "%s"', v)
				or string.format('empty filename #%s', v)
		end
		previewWarning = string.format(
			'Page using [[Template:Listen]] with %s',
			mw.text.listToText(missingFiles)
		)
		previewWarning = require('Module:If preview')._warning({previewWarning})
	else
		previewWarning = ''
	end

	-- Exit early if none exist.
	if #numArgs == 0 then
		return previewWarning .. p.renderTrackingCategories(isPlain, hasMissing, true)
	end

	-- Build the arguments for {{side box}}
	local sbArgs = {}
	sbArgs.class = 'noprint'
	sbArgs.metadata = 'no'
	sbArgs.position = args.pos

	-- Style arguments
	do
		local style = {}
		if isPlain then
			style[#style + 1] = 'border:none'
			style[#style + 1] = 'background:transparent'
			style[#style + 1] = 'float:none'
		end
		if isEmbedded then
			style[#style + 1] = 'border-collapse:collapse'
			style[#style + 1] = 'border-width:1px 0 0 0'
			style[#style + 1] = 'background:transparent'
			style[#style + 1] = 'float:none'
			style[#style + 1] = 'margin:0 -5px'
		end
		if args.pos == 'left' then
			style[#style + 1] = 'float:left'
			style[#style + 1] = 'overflow:visible'
		elseif args.pos == 'center' then
			style[#style + 1] = 'float:none'
			style[#style + 1] = 'margin-left:auto'
			style[#style + 1] = 'margin-right:auto'
		end
		
		style[#style + 1] = args.style
		sbArgs.style = table.concat(style, '; ')
	end
	sbArgs.textstyle = 'line-height:1.1em'

	-- Image
	if not isPlain and not isEmbedded then
		if args.image then
			sbArgs.image = args.image
		else
			local images = {
				speech = 'Audio-input-microphone.svg',
				music = 'Gnome-mime-audio-openclipart.svg'
			}
			local image = args.type
				and images[args.type]
				or 'Gnome-mime-sound-openclipart.svg'
			sbArgs.image = mFileLink._main{
				file = image,
				size = '65x50px',
				location = 'center',
				link = '',
				alt = ''
			}
		end
	end

	-- Text
	do
		local header
		if args.header then
			header = mw.html.create('div')
			header:css{
				background = 'transparent',
				['text-align'] = 'left',
				padding = args.embed and '2px 0' or '2px'
			}
				:wikitext(args.header)
			header = tostring(header)
			header = header .. '\n'
		else
			header = ''
		end
		local text = {}
		for i, t in ipairs(numArgs) do
			text[#text + 1] = p.renderRow(
				t.filename, t.title, t.play, t.alt, t.description, t.start, t.length
			)
			if numArgs[i + 1] then
				text[#text + 1] = '<hr/>'
			end
		end
		sbArgs.text = header .. table.concat(text)
	end

	-- Below
	if not isPlain and not isEmbedded and args.help ~= 'no' then
		sbArgs.below = string.format(
			'<hr/><i class="selfreference">Problems playing %s? See [[Help:Media|media help]].</i>',
			#numArgs == 1 and 'this file' or 'these files'
		)
	end

	-- Render the side box.
	local sideBox = mSideBox._main(sbArgs)

	-- Render the tracking categories.
	local trackingCategories = p.renderTrackingCategories(isPlain, hasMissing)

	return previewWarning .. sideBox .. trackingCategories
end

function p.renderRow(filename, title, play, alt, description, start, length)
	-- Renders the HTML for one file description row.
	if not filename then
		return nil
	end

	length = p.formatLength(length)
	length = length and string.format(' (%s)', length) or ''

	local root = mw.html.create('')
	root:tag('div')
		:addClass('haudio')
		:newline()
		:tag('div')
			:css('padding', '4px 0')
			:wikitext(string.format('[[:File:%s|%s]]%s', filename, title or '', length))
			:done()
		:newline()
		:tag('div')
			:wikitext(
				play ~= 'no'
					and mFileLink._main{
						file = filename,
						size = '233px',
						alt = alt,
						start = start
					}
					or nil
			)
			:done()
		:newline()
		:tag('div')
			:css('padding', '2px 0 0 0')
			:addClass('description')
			:wikitext(description)
			:done()
		:done()
	return tostring(root)
end

function p.formatLength(length)
	-- Formats a duration in seconds in "(h:)mm:ss" (minutes are zero-padded
	-- only if there are hours).
	if not length or length == 0 then
		return nil
	end

	-- Add 0.5 to offset the rounding down
	local t = lang:getDurationIntervals(length + 0.5, { 'hours', 'minutes', 'seconds' })
	local s = t.seconds and string.format('%02d', t.seconds) or '00'
	local m = t.minutes or 0

	local span = mw.html.create('span'):addClass('duration')
	if t.hours then
		span
			:tag('span')
				:addClass('h')
				:wikitext(t.hours)
				:done()
			:wikitext(':')
		m = string.format('%02d', m)
	end
	span
		:tag('span')
			:addClass('min')
			:wikitext(m)
			:done()
		:wikitext(':')
		:tag('span')
			:addClass('s')
			:wikitext(s)
			:done()
	return tostring(span)
end

function p.renderTrackingCategories(isPlain, hasMissing, isEmpty, titleObj)
	-- Renders all tracking categories produced by the template.
	-- isPlain, hasMissing and isEmpty are passed through from p._main,
	-- and the titleObj is only used for testing purposes.
	local cats = {}
	local currentTitle = titleObj or mw.title.getCurrentTitle()
	if currentTitle.namespace == 0 then
		-- We are in mainspace.
		if not isEmpty then
			cats[#cats + 1] = 'Articles with hAudio microformats'
		end
		if hasMissing then
			cats[#cats + 1] = 'Articles with empty listen template'
		end
	end
	if isPlain then
		cats[#cats + 1] = 'Listen template using plain parameter'
	end
	for i, cat in ipairs(cats) do
		cats[i] = string.format('[[Category:%s]]', cat)
	end
	return table.concat(cats)
end

return p