Module:audio
Dehra
Documentation for this module may be created at Module:audio/doc
local export = {}
local headword_data_module = "Module:headword/data"
local IPA_module = "Module:IPA"
local labels_module = "Module:labels"
local links_module = "Module:links"
local parameters_module = "Module:parameters"
local qualifier_module = "Module:qualifier"
local references_module = "Module:references"
local string_utilities_module = "Module:string utilities"
local table_module = "Module:table"
local template_styles_module = "Module:TemplateStyles"
local utilities_module = "Module:utilities"
local audio_styles_css = "audio/styles.css"
local function track(page)
require("Module:debug/track")("audio/" .. page)
return true
end
local function wrap_qualifier_css(text, suffix)
return require(qualifier_module).wrap_qualifier_css(text, suffix)
end
--[==[
Display a box that can be used to play an audio file. `data` is a table containing the following fields:
* `lang` ('''required'''): language object for the audio files;
* `file` ('''required'''): file containing the audio;
* `caption`: Caption to display before the audio box; normally {"Audio"}, and does not usually need to be changed;
* `nocaption`: If specified, don't display the caption;
* `q`: {nil} or a list of left regular qualifier strings, formatted using {format_qualifier()} in [[Module:qualifier]]
and displayed before the audio box and after the caption (and any accent qualifiers);
* `qq`: {nil} or a list of right regular qualifier strings, displayed directly after the audio box (and after any
accent qualifiers);
* `a`: {nil} or a list of left accent qualifier strings, formatted using {format_qualifiers()} in
[[Module:accent qualifier]] and displayed before the audio box and after the caption;
* `aa`: {nil} or a list of right accent qualifier strings, displayed directly after the homophone in question;
* `refs`: {nil} or a list of references or reference specs to add directly after the audio box; the value of a list item
is either a string containing the reference text (typically a call to a citation template such as {{tl|cite-book}}, or
a template wrapping such a call), or an object with fields `text` (the reference text), `name` (the name of the
reference, as in {{cd|<nowiki><ref name="foo">...</ref></nowiki>}} or {{cd|<nowiki><ref name="foo" /></nowiki>}})
and/or `group` (the group of the reference, as in {{cd|<nowiki><ref name="foo" group="bar">...</ref></nowiki>}} or
{{cd|<nowiki><ref name="foo" group="bar"/></nowiki>}}); this uses a parser function to format the reference
appropriately and insert a footnote number that hyperlinks to the actual reference, located in the
{{cd|<nowiki><references /></nowiki>}} section;
* `text`: Text of the audio snippet; if specified, should be an object of the form passed to {full_link()} in
[[Module:links]], including a `lang` field containing the language of the text (usually the same as `data.lang`);
displayed before the audio box, after any regular and accent qualifiers;
* `IPA`: IPA of the audio snippet, or a list of IPA specs; if specified, should be surrounded by slashes or brackets,
and will be processed using {format_IPA_multiple()} in [[Module:IPA]] and displayed before the audio box, after any
regular and accent qualifiers and after the text of the audio snippet, if given;
* `nocat`: If true, suppress categorization;
* `sort`: Sort key for categorization.
]==]
function export.format_audio(data)
local cats = { "Awdjo (".. data.lang:getFullName() ..")" }
local function format_a(a)
if a and a[1] then
return require(labels_module).show_labels {
lang = data.lang,
labels = a,
mode = "accent",
nocat = true,
open = false,
close = false,
no_track_already_seen = true,
}
end
return nil
end
local function format_q(q)
if q and q[1] then
return require(qualifier_module).format_qualifier(q, false, false)
end
return nil
end
local function make_td_if(text)
if text == "" then
return text
end
return "<td>" .. text .. "</td>"
end
-- Generate the full text preceding the audio box.
local pretext_parts = {}
local function ins(text)
table.insert(pretext_parts, text)
end
local formatted_accent_labels, formatted_qualifiers, formatted_text, formatted_ipa
formatted_accent_labels = format_a(data.a)
formatted_qualifiers = format_q(data.q)
if data.text then
formatted_text = require(links_module).full_link(data.text, "term", true)
end
if data.IPA then
local ipa_cats
local ipa = data.IPA
if type(ipa) == "string" then
ipa = {ipa}
end
local ipa_items = {}
for _, ipa_item in ipairs(ipa) do
table.insert(ipa_items, {pron = ipa_item})
end
formatted_ipa, ipa_cats = require(IPA_module).format_IPA_multiple(data.lang, ipa_items, nil, "no count", "raw")
if ipa_cats[1] then
require(table_module).extendList(cats, ipa_cats)
end
end
local has_qual = formatted_accent_labels or formatted_qualifiers
if not data.nocaption then
-- Track uses of caption (3=). Over time as we eliminate most of them, we can use this to find and
-- eliminate the remainder.
if data.caption then
track("caption")
end
ins(data.caption or "Awdjo")
if has_qual then
ins(" " .. wrap_qualifier_css("(", "brac"))
end
end
if formatted_accent_labels then
ins(formatted_accent_labels)
if formatted_qualifiers then
ins(wrap_qualifier_css(",", "comma") .. " ")
end
end
if formatted_qualifiers then
ins(formatted_qualifiers)
end
if has_qual then
if not data.nocaption then
ins(wrap_qualifier_css(")", "brac"))
end
end
if (formatted_text or formatted_ipa) and (has_qual or not data.nocaption) then
ins(wrap_qualifier_css(";", "semicolon") .. " ")
end
if formatted_text then
ins(formatted_text)
if formatted_ipa then
ins(" ")
end
end
ins(formatted_ipa)
if not data.nocaption then
ins(wrap_qualifier_css(":", "colon"))
end
local pretext = make_td_if(table.concat(pretext_parts))
-- Generate the full text following the audio box.
local posttext_parts = {}
local function ins(text)
table.insert(posttext_parts, text)
end
local formatted_post_accent_labels = format_a(data.aa)
local formatted_post_qualifiers = format_q(data.qq)
local formatted_references = data.refs and require(references_module).format_references(data.refs) or nil
if formatted_references then
ins(formatted_references)
end
if formatted_post_accent_labels or formatted_post_qualifiers then
if formatted_references then
ins(" ")
end
ins(wrap_qualifier_css("(", "brac"))
if formatted_post_accent_labels then
ins(formatted_post_accent_labels)
if formatted_post_qualifiers then
ins(wrap_qualifier_css(",", "comma") .. " ")
end
end
if formatted_post_qualifiers then
ins(formatted_post_qualifiers)
end
ins(wrap_qualifier_css(")", "brac"))
end
if data.bad then
track("bad-audio")
track("bad-audio/" .. data.lang:getCode())
ins(" " .. require(qualifier_module).wrap_css("Note: this pronuncation may be nonstandard or incorrect: " .. data.bad, "bad-audio-note"))
end
local posttext = make_td_if(table.concat(posttext_parts))
local template = [=[
<tr>%s<td class="audiofile">[[File:%s|noicon|175px]]</td><td class="audiometa" style="font-size: 80%%;">([[:File:%s|fajl]])</td>%s</tr>]=]
local text = template:format(pretext, data.file, data.file, posttext)
text = '<table class="audiotable" style="vertical-align: middle; display: inline-block; list-style: none; line-height: 1em; border-collapse: collapse; margin: 0;">' .. text .. "</table>"
local stylesheet = require(template_styles_module)(audio_styles_css)
local categories =
data.nocat and "" or
cats[1] and require(utilities_module).format_categories(cats, data.lang, data.sort) or ""
return stylesheet .. text .. categories
end
--[==[
FIXME: Old entry point for formatting multiple audios in a single table. Not used anywhere and needs rewriting to the
standard of format_audio().
Meant to be called from a module. `data` is a table containing the following fields:
<pre>
{
lang = LANGUAGE_OBJECT,
audios = {{file = "FILENAME", qualifiers = nil or {"QUALIFIER", "QUALIFIER", ...}}, ...},
caption = nil or "CAPTION"
}
</pre>
Here:
* `lang` is a language object.
* `audios` is the list of audio files to display. FILENAME is the name of the audio file without a namespace.
QUALIFIER is a qualifier string to display after the specific audio file in question, formatted using
{format_qualifier()} in [[Module:qualifier]].
* `caption`, if specified, adds a caption before the audio file.
]==]
function export.format_multiple_audios(data)
local audiocats = { "Awdjo (".. data.lang:getFullName() ..")" }
local rows = { }
local caption = data.caption
for _, audio in ipairs(data.audios) do
local qualifiers = audio.qualifiers
local function repl(key)
if key == "file" then
return audio.file
elseif key == "caption" then
if not caption then return "" end
return "<td rowspan=" .. #data.audios .. ">" .. caption .. ":</td>"
elseif key == "qualifiers" then
if not qualifiers or not qualifiers[1] then return "" end
return "<td>" .. require(qualifier_module).format_qualifier(qualifiers) .. "</td>"
end
end
local template = [=[
<tr>{{{caption}}}
<td class="audiofile">[[File:{{{file}}}|noicon|175px]]</td>
<td class="audiometa" style="font-size: 80%;">([[:File:{{{file}}}|file]])</td>
{{{qualifiers}}}</tr>]=]
local text = (mw.ustring.gsub(template, "{{{([a-z0-9_:]+)}}}", repl))
table.insert(rows, text)
caption = nil
end
local function repl(key)
if key == "rows" then
return table.concat(rows, "\n")
end
end
local template = [=[
<table class="audiotable" style="vertical-align: middle; display: inline-block; list-style: none; line-height: 1em; border-collapse: collapse;">
{{{rows}}}
</table>
]=]
local stylesheet = require(template_styles_module)(audio_styles_css)
local text = mw.ustring.gsub(template, "{{{([a-z0-9_:]+)}}}", repl)
local categories =
data.nocat and "" or
#audiocats > 0 and require(utilities_module).format_categories(audiocats, data.lang, data.sort) or ""
-- remove newlines due to HTML generator bug in MediaWiki(?) - newlines in tables cause list items to not end correctly
text = mw.ustring.gsub(text, "\n", "")
return stylesheet .. text .. categories
end
--[==[
Construct the `text` object passed into {format_audio()}, from raw-ish arguments (essentially, the output of {process()}
in [[Module:parameters]]). On entry, `args` contains the following fields:
* `lang` ('''required'''): Language object.
* `text`: Text. If this isn't defined and neither are any of `gloss`, `tr`, `ts`, `pos`, `lit` or `genders`, the
function returns {nil}.
* `gloss`: Gloss of text.
* `tr`: Manual transliteration of text.
* `ts`: Transcription of text.
* `pos`: Part of speech of text.
* `lit`: Literal meaning of text.
* `genders`: List of gender/number spec(s) of text.
* `sc`: Optional script object of text (rarely needs to be set).
* `pagename`: Pagename; used in place of `text` when `text` is unset but other text-related parameters are set.
If not specified, taken from the actual pagename.
]==]
function export.construct_audio_textobj(args)
local textobj
if args.text or args.gloss or args.tr or args.ts or args.pos or args.lit or args.genders and args.genders[1] then
local text = args.text or args.pagename or mw.loadData("Module:headword/data").pagename
textobj = {
lang = args.lang,
alt = wrap_qualifier_css("“", "quote") .. text .. wrap_qualifier_css("”", "quote"),
gloss = args.gloss,
tr = args.tr,
ts = args.ts,
pos = args.pos,
lit = args.lit,
genders = args.genders,
sc = args.sc,
}
end
return textobj
end
--[==[
Entry point for {{tl|audio}} template.
]==]
function export.show(frame)
local parent_args = frame:getParent().args
local compat = parent_args.lang
local offset = compat and 0 or 1
local params = {
[compat and "lang" or 1] = {required = true, type = "language", default = "en"},
[1 + offset] = {required = true, default = "Example.ogg"},
[2 + offset] = {},
["q"] = {type = "qualifier"},
["qq"] = {type = "qualifier"},
["a"] = {type = "labels"},
["aa"] = {type = "labels"},
["ref"] = {type = "references"},
["IPA"] = {sublist = true},
["text"] = {},
["t"] = {},
["gloss"] = {alias_of = "t"},
["tr"] = {},
["ts"] = {},
["pos"] = {},
["lit"] = {},
["g"] = {sublist = true},
["sc"] = {type = "script"},
["bad"] = {},
["nocat"] = {type = "boolean"},
["sort"] = {},
["pagename"] = {},
}
local args = require(parameters_module).process(parent_args, params)
local lang = args[compat and "lang" or 1]
-- Needed in construct_audio_textobj().
args.lang = lang
local textobj = export.construct_audio_textobj(args)
local caption = args[2 + offset]
local nocaption
if caption == "-" then
caption = nil
nocaption = true
end
if caption then
-- Remove final colon if given, to avoid two colons.
caption = caption:gsub(":$", "")
end
local data = {
lang = lang,
file = args[1 + offset],
caption = caption,
nocaption = nocaption,
q = args.q,
qq = args.qq,
a = args.a,
aa = args.aa,
refs = args.ref,
text = textobj,
IPA = args.IPA,
bad = args.bad,
nocat = args.nocat,
sort = args.sort,
}
return export.format_audio(data)
end
return export