Module: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 = {}local function 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 thenreturn nilend-- Add 0.5 to offset the rounding downlocal 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 0local span = mw.html.create('span'):addClass('duration')if t.hours thenspan:tag('span'):addClass('h'):wikitext(t.hours):done():wikitext(':')m = string.format('%02d', m)endspan:tag('span'):addClass('min'):wikitext(m):done():wikitext(':'):tag('span'):addClass('s'):wikitext(s):done()return tostring(span)endlocal function renderRow(filename, title, play, alt, description, start, length, hasImage)-- Renders the HTML for one file description row.if not filename thenreturn nilendlength = formatLength(length)length = length and string.format(' (%s)', length) or ''local root = mw.html.create('')root:tag('div'):addClass('haudio'):newline():tag('div'):addClass('listen-file-header'):wikitext(string.format('[[:File:%s|%s]]%s',filename,title or '',length)):done():newline():tag('div'):wikitext(play ~= 'no' and mFileLink._main{file = filename,size = hasImage and '232px' or '215px',alt = alt,start = start}or nil):done():newline():tag('div'):addClass('description'):wikitext(description):done():done()return tostring(root)endlocal function 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 thencats[#cats + 1] = 'Articles with hAudio microformats'endif hasMissing thencats[#cats + 1] = 'Articles with empty listen template'endendif isPlain thencats[#cats + 1] = 'Listen template using plain parameter'endfor i, cat in ipairs(cats) docats[i] = string.format('[[Category:%s]]', cat)endreturn table.concat(cats)endfunction p._main(args)-- Organise the arguments by number.local isPlain = args.plain == 'yes'local isEmbedded = args.embed and truelocal hasImage = not isPlain and not isEmbedded and args.image ~= 'none'local numArgs, missingFiles = {}, {}dolocal 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.makeTitle(-2, t.filename)if obj and obj.exists thenif t.length == 'yes' or-- Show length if the video height would be less than 150pxobj.file.width / obj.file.height > (hasImage and 1.547 or 1.434)thent.length = obj.file.lengthelset.length = nilendnumArgs[#numArgs + 1] = telsemissingFiles[#missingFiles + 1] = t.filename or iendendend-- Render warninglocal hasMissing = #missingFiles ~= 0local previewWarning = ''if hasMissing thenfor i, v in ipairs(missingFiles) domissingFiles[i] = type(v) == 'string'and string.format('missing file "%s"', v)or string.format('empty filename #%s', v)endpreviewWarning = string.format('Page using [[Template:Listen]] with %s',mw.text.listToText(missingFiles))previewWarning = require('Module:If preview')._warning({previewWarning})end-- Exit early if none exist.if #numArgs == 0 thenreturn previewWarning .. renderTrackingCategories(isPlain, hasMissing, true)end-- Build the arguments for {{side box}}local sbArgs = {metadata = 'no',position = (isPlain or isEmbedded) and 'left' or args.pos,style = args.style,templatestyles = 'Module:Listen/styles.css'}-- Class argumentsdolocal class = {'listen','noprint'}if isPlain thentable.insert(class, 'listen-plain')endif isEmbedded thentable.insert(class, 'listen-embedded')endif not hasImage thentable.insert(class, 'listen-noimage')endif args.pos == 'left' and not isPlain and not isEmbedded thentable.insert(class, 'listen-left')elseif args.pos == 'center' thentable.insert(class, 'listen-center')endsbArgs.class = table.concat(class, ' ')end-- Imageif not isPlain and not isEmbedded thenif args.image thensbArgs.image = args.imageelselocal images = {speech = 'Audio-input-microphone.svg',music = 'Gnome-mime-audio-openclipart.svg',default = 'Gnome-mime-sound-openclipart.svg'}sbArgs.image = mFileLink._main{file = args.type and images[args.type] or images.default,size = '65x50px',location = 'center',link = '',alt = ''}endend-- Textdolocal headerif args.header thenheader = mw.html.create('div')header:addClass('listen-header'):wikitext(args.header)header = tostring(header) .. '\n'elseheader = ''endlocal text = {}for i, t in ipairs(numArgs) dotext[#text + 1] = renderRow(t.filename, t.title, t.play, t.alt, t.description, t.start,t.length, hasImage)if numArgs[i + 1] thentext[#text + 1] = '<hr/>'endendsbArgs.text = header .. table.concat(text)end-- Belowif not isPlain and not isEmbedded and args.help ~= 'no' thensbArgs.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 = renderTrackingCategories(isPlain, hasMissing)return previewWarning .. sideBox .. trackingCategoriesendfunction p.main(frame)local origArgs = frame:getParent().argslocal args = {}for k, v in pairs(origArgs) doif v ~= '' thenargs[k] = vendendreturn p._main(args)endreturn p