# Module:Spoken Wikipedia

local getArgs = require('Module:Arguments').getArgs
local yesno = require('Module:Yesno')
local Date = require('Module:Date')._Date
local lang = mw.language.new('en')
local cfg = mw.loadData('Module:Spoken Wikipedia/configuration')  
p = {}  
local function wikiError(message)
local ret = mw.html.create('div')
:addClass(cfg.i18n.class.err)
:wikitext(message)
:done
return tostring(ret)
end  
local function category(c, nocat)
if nocat then
return ''
else
return c
end
end  
local function formatPageText(page)
if page then
return '<span>' .. page .. '</span>'
end
if mw.title.getCurrentTitle.namespace == 0 then
return cfg.i18n.this_article
else
return cfg.i18n.this_page
end
end  
local function formatFileLength(filenames)
local length = 0
for _, filename in ipairs(filenames) do
local fileTitle = mw.title.new(filename, 'Media')
if fileTitle and fileTitle.file and fileTitle.file.exists then
length = length + fileTitle.file.length
end
end  
-- Add 30 to offset the rounding down
local intervals = lang:getDurationIntervals(length + 30, { 'hours', 'minutes' })
local ret = string.format(
'<span>%s</span> %s',
intervals.minutes or 0,
intervals.minutes == 1 and cfg.i18n.minute or cfg.i18n.minutes
if intervals.hours then
ret = string.format(
'<span>%s</span> %s and %s',
intervals.hours,
intervals.hours == 1 and cfg.i18n.hour or cfg.i18n.hours,
ret
end
return '<span>' .. ret .. '</span>'
end  
local function formatHeader(filenames, page)
local listento = mw.html.create('span')
:addClass(cfg.i18n.class.listento)
:wikitext(string.format(
cfg.i18n.listento,
formatPageText(page)
))
:done  
local file_length
if #filenames > 1 then
file_length = string.format(
cfg.i18n.n_files_length,
tostring(#filenames),
formatFileLength(filenames)
else
file_length = string.format(
cfg.i18n.one_file_length,
formatFileLength(filenames)
end
return mw.html.create('div')
:addClass(cfg.i18n.class.header)
:node(listento)
:wikitext(file_length)
:done
end  
local function formatIcon
return mw.html.create('div')
:addClass(cfg.i18n.class.icon)
:wikitext(cfg.i18n.icon)
:done
end  
local function formatFiles(filenames, nocat)
if #filenames == 0 then
return wikiError(cfg.i18n.err.no_filename) ..
category(cfg.i18n.cat.no_filename, nocat)
end  
-- TODO: the else branch really wants to be a mw.html <ol> object rather than wikitext
-- version of the same, so that we can style the numbers nicer
local files = {}
if #filenames == 1 then
table.insert(files, string.format(cfg.i18n.one_file, filenames[1]))
else
for i, filename in ipairs(filenames) do
table.insert(files, string.format(cfg.i18n.n_files, filename, i))
end
end  
return mw.html.create('div')
:addClass(cfg.i18n.class.files)
:wikitext(table.concat(files))
:done
:newline
end  
local function formatDateText(, dateArg, nocat)
local d = dateArg and Date(dateArg) or nil
return d and :expandTemplate{
title = 'Start date', args = {
d.year,
d.month,
d.day,
df='y'
}
} or (wikiError(cfg.i18n.err.no_date) .. category(cfg.i18n.cat.no_date, nocat))
end  
local function formatDisclaimer(, filenames, page, dateArg, nocat)
local thisFileText = ''
local disclaimer
if #filenames == 1 then
thisFileText = filenames[1]
disclaimer = cfg.i18n.one_file_disclaimer
else
disclaimer = cfg.i18n.n_files_disclaimer
end
return mw.html.create('div')
:addClass(cfg.i18n.class.disclaimer)
:wikitext(string.format(
disclaimer,
thisFileText,
formatPageText(page),
formatDateText(, dateArg, nocat)
))
:done
end  
local function formatFooter
return mw.html.create('div')
:addClass(cfg.i18n.class.footer)
:wikitext(cfg.i18n.footer)
:done
end  
local function formatTopicon(, filenames)
local wikilink
if #filenames > 0 then
wikilink = 'File:' .. filenames[1]
else
wikilink = cfg.i18n.topicon_multiwikilink
end
return :expandTemplate{
title = "Top icon",
args = {
imagename = 'Sound-icon.svg',
wikilink = wikilink,
text = 'Listen to this article',
id = 'spoken-icon'
}
}
end  
local function extractFilenames(args)
local filenames = {}
for key, rawValue in ipairs(args) do
local value = mw.text.trim(rawValue)
if type(key) == "number" and value ~= '' then
table.insert(filenames, value)
end
end
return filenames
end  
local function sidebox(nodes)
root = mw.html.create('div')
:addClass(cfg.i18n.class.box)
for _, node in ipairs(nodes) do
root:node(node)
end
return root
end  
function main
local args = getArgs  
-- Mandatory parameters
local filenames = extractFilenames(args)
local dateArg = args['date']
-- Optional parameters
local page = args['page']
local nocat = yesno(args['nocat'], false) or false  
local root = sidebox({
formatHeader(filenames, page),
formatFiles(filenames, nocat),
formatIcon,
formatDisclaimer(, filenames, page, dateArg, nocat),
formatFooter
})  
if mw.title.getCurrentTitle.namespace == 0 then
root:wikitext(formatTopicon(, filenames))
root:wikitext(category(cfg.i18n.cat.articles, nocat))
end  
return :extensionTag{
name = 'templatestyles', args = { src = cfg.templatestyles }
} .. tostring(root)
end  
p.main = main  
return p