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/sandbox')
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 class="fn">[[' .. 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 class="min">%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 class="h">%s</span> %s and %s',
intervals.hours,
intervals.hours == 1 and cfg.i18n.hour or cfg.i18n.hours,
ret
)
end
return '<span class="duration">' .. 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
local header = mw.html.create('div')
:addClass(cfg.i18n.class.header)
:node(listento)
:wikitext(file_length)
if #filenames > 0 then
header:attr('id', string.format(cfg.i18n.fragment.id, filenames[1]))
end
return header: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(frame, dateArg, nocat)
local d = dateArg and Date(dateArg) or nil
return d and frame: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(frame, 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(frame, 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(frame, filenames)
local wikilink
if #filenames > 0 then
wikilink = string.format(cfg.i18n.fragment.id, filenames[1])
else
wikilink = cfg.i18n.topicon_multiwikilink
end
return frame: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(frame)
local args = getArgs(frame)
-- 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(frame, filenames, page, dateArg, nocat),
formatFooter()
})
if mw.title.getCurrentTitle().namespace == 0 then
root:wikitext(formatTopicon(frame, filenames))
root:wikitext(category(cfg.i18n.cat.articles, nocat))
end
return frame:extensionTag{
name = 'templatestyles', args = { src = cfg.templatestyles }
} .. tostring(root)
end
p.main = main
return p