local export = {}
local force_cat = false -- for testing
local rhymes_styles_css_module = "Module:rhymes/styles.css"
local IPA_module = "Module:IPA"
local parameters_module = "Module:parameters"
local parameter_utilities_module = "Module:parameter utilities"
local pron_qualifier_module = "Module:pron qualifier"
local script_utilities_module = "Module:script utilities"
local string_utilities_module = "Module:string utilities"
local TemplateStyles_module = "Module:TemplateStyles"
local utilities_module = "Module:utilities"
local concat = table.concat
local insert = table.insert
local function rsplit(text, pattern)
return require(string_utilities_module).split(text, pattern)
end
local function track(page)
require("Module:debug/track")("rhymes/" .. page)
return true
end
local function tag_rhyme(rhyme, lang)
local formatted_rhyme, cats
-- FIXME, should not be here. Telugu should use IPA as well.
if lang:getCode() == "te" then
formatted_rhyme = require(script_utilities_module).tag_text(rhyme, lang)
cats = {}
else
formatted_rhyme, cats = require(IPA_module).format_IPA(lang, rhyme, "raw")
end
return formatted_rhyme, cats
end
local function make_rhyme_link(lang, link_rhyme, display_rhyme)
local retval, cats
if not link_rhyme then
retval = concat{"[[Rhymes:", lang:getCanonicalName(), "|", lang:getCanonicalName(), "]]"}
cats = {}
else
local formatted_rhyme
formatted_rhyme, cats = tag_rhyme(display_rhyme or link_rhyme, lang)
retval = concat{"[[Rhymes:", lang:getCanonicalName(), "/", link_rhyme, "|", formatted_rhyme, "]]"}
end
return retval, cats
end
--[==[
Implementation of {{tl|rhymes row}}.
]==]
function export.show_row(frame)
local args = require(parameters_module).process(
frame.getParent and frame:getParent().args or frame,
{
[1] = {required = true, type = "full language"},
[2] = {required = true},
[3] = {},
}
)
if not args[1] then
return "[[Rhymes:英語/aɪmz|<span class=\"IPA\">-aɪmz</span>]]"
end
-- Discard cleanup categories from make_rhyme_link().
return (make_rhyme_link(args[1], args[2], "-" .. args[2])) .. (args[3] and (" (''" .. args[3] .. "'')") or "")
end
do
local function add_syllable_categories(categories, lang, rhyme, num_syl)
local prefix = "Rhymes:" .. lang .. "/" .. rhyme
insert(categories, prefix)
if num_syl then
for _, n in ipairs(num_syl) do
local c
if n > 1 then
c = prefix .. "/" .. n .. "音節"
else
c = prefix .. "/1音節"
end
insert(categories, c)
end
end
end
--[==[
Meant to be called from a module. `data` is a table containing the following fields:
* `lang`: language object for the rhymes;
* `rhymes`: a list of rhymes, each described by an object which specifies the rhyme, optional number of syllables, and
optional left and right regular and accent qualifier fields:
** `rhyme`: the rhyme itself;
** `num_syl`: {nil} or a list of numbers, specifying the number of syllables of the word with this rhyme; optional and
currently used only for categorization; if omitted, defaults to the top-level `num_syl`;
** `separator`: {nil} or the string used to separate this rhyme from the preceding one when displayed; defaults to the
top-level `separator`;
** `q`: {nil} or a list of left regular qualifier strings, formatted using {format_qualifier()} in [[Module:qualifier]]
and displayed directly before the rhyme in question;
** `qq`: {nil} or a list of right regular qualifier strings, displayed directly after the rhyme in question;
** `qualifiers`: {nil} or a list of qualifier strings; also displayed on the left; for compatibility purposes only, do
not use in new code;
** `a`: {nil} or a list of left accent qualifier strings, formatted using {format_qualifiers()} in
[[Module:accent qualifier]] and displayed directly before the rhyme in question;
** `aa`: {nil} or a list of right accent qualifier strings, displayed directly after the rhyme in question;
** `refs`: {nil} or a list of references or reference specs to add directly after the rhyme; 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;
** `nocat`: if {true}, suppress categorization for this rhyme only;
* `num_syl`: {nil} or a list of numbers, specifying the number of syllables for all rhymes; optional and currently used
only for categorization; overridable at the individual rhyme level;
* `separator`: {nil} or a string, specifying the separator displayed before all rhymes but the first; by default,
{", "}; overridable at the individual rhyme level;
* `q`: {nil} or a list of left regular qualifier strings, formatted using {format_qualifier()} in [[Module:qualifier]]
and displayed before the initial caption;
* `qq`: {nil} or a list of right regular qualifier strings, displayed after all rhymes;
* `qualifiers`: {nil} or a list of left regular qualifier strings; for compatibility purposes only, do not use in new
code;
* `a`: {nil} or a list of left accent qualifier strings, formatted using {format_qualifiers()} in
[[Module:accent qualifier]] and dispalyed before the initial caption;
* `aa`: {nil} or a list of right accent qualifier strings, displayed after all rhymes;
* `sort`: {nil} or sort key;
* `caption`: {nil} or string specifying the caption to use, in place of {"Rhymes"}; a colon and space is automatically
added after the caption;
* `nocaption`: if {true}, suppress the caption display;
* `nocat`: if {true}, suppress categorization;
* `force_cat`: if {true}, force categorization even on non-mainspace pages.
If both regular and accent qualifiers on the same side and at the same level are specified, the accent qualifiers
precede the regular qualifiers on both left and right.
'''WARNING''': Destructively modifies the objects inside the `rhymes` field.
Note that the number of syllables is currently used only for categorization; if present, an extra category will
be added such as [[Category:Rhymes:Italian/ino/3 syllables]] in addition to [[Category:Rhymes:Italian/ino]].
]==]
function export.format_rhymes(data)
local langname = data.lang:getFullName()
local parts = {}
local categories = {}
local overall_sep = data.separator or ", "
for i, r in ipairs(data.rhymes) do
local rhyme = r.rhyme
local link, link_cats = make_rhyme_link(data.lang, rhyme, "-" .. rhyme)
if not r.nocat and not data.nocat then
for _, cat in ipairs(link_cats) do
insert(categories, cat)
end
end
if r.q and r.q[1] or r.qq and r.qq[1] or r.qualifiers and r.qualifiers[1]
or r.a and r.a[1] or r.aa and r.aa[1] or r.refs and r.refs[1] then
link = require(pron_qualifier_module).format_qualifiers {
lang = data.lang,
text = link,
q = r.q,
qq = r.qq,
qualifiers = r.qualifiers,
a = r.a,
aa = r.aa,
refs = r.refs,
}
end
insert(parts, r.separator or i > 1 and overall_sep or "")
insert(parts, link)
if not r.nocat and not data.nocat then
add_syllable_categories(categories, langname, rhyme, r.num_syl or data.num_syl)
end
end
local text = concat(parts)
if not data.nocaption then
text = (data.caption or "韻部") .. ":" .. text
end
if data.q and data.q[1] or data.qq and data.qq[1] or data.a and data.a[1] or data.aa and data.aa[1] then
text = require(pron_qualifier_module).format_qualifiers {
lang = data.lang,
text = text,
q = data.q,
qq = data.qq,
a = data.a,
aa = data.aa,
}
end
if categories[1] then
local categories = require(utilities_module).format_categories(categories, data.lang, data.sort, nil,
force_cat or data.force_cat)
text = text .. categories
end
return text
end
end
--[==[
Implementation of {{tl|rhymes}}.
]==]
function export.show(frame)
local parent_args = frame:getParent().args
local compat = parent_args.lang
local offset = compat and 0 or 1
local lang_param = compat and "lang" or 1
local plain = {}
local boolean = {type = "boolean"}
local params = {
[lang_param] = {required = true, type = "language", default = "en"},
[1 + offset] = {list = true, required = true, disallow_holes = true, default = "aɪmz"},
["caption"] = plain,
["nocaption"] = boolean,
["nocat"] = boolean,
["sort"] = plain,
}
local m_param_utils = require(parameter_utilities_module)
local param_mods = m_param_utils.construct_param_mods {
{
param = "s",
item_dest = "num_syl",
separate_no_index = true,
type = "number",
sublist = true,
},
{group = {"q", "a", "ref"}},
}
local rhymes, args = m_param_utils.process_list_arguments {
params = params,
param_mods = param_mods,
raw_args = parent_args,
termarg = 1 + offset,
term_dest = "rhyme",
track_module = "rhymes",
}
local lang = args[lang_param]
local data = {
lang = lang,
rhymes = rhymes,
num_syl = args.s.default,
caption = args.caption,
nocaption = args.nocaption,
nocat = args.nocat,
sort = args.sort,
q = args.q.default,
qq = args.qq.default,
a = args.a.default,
aa = args.aa.default,
}
return export.format_rhymes(data)
end
--[==[
Implementation of {{tl|rhymes nav}}.
]==]
function export.show_nav(frame)
local args = require(parameters_module).process(
frame:getParent().args,
{
[1] = {required = true, type = "full language", default = "und"},
[2] = {list = true, allow_holes = true},
["nocat"] = {type = "boolean"},
}
)
local lang = args[1]
local langname = lang:getCanonicalName()
local parts = args[2]
-- Create steps
-- FIXME: We should probably use format_categories() in [[Module:utilities]] rather than constructing categories
-- manually.
local categories = {}
-- Here and below, we ignore any cleanup categories coming out of make_rhyme_link() by adding an extra set of parens
-- around the call to make_rhyme_link() to cause the second argument (the categories) to be ignored. {{rhymes nav}}
-- is run on a rhymes page so it's not clear we want the page to be added to any such categories, if they exist.
local steps = {"[[Wiktionary:韻部|韻部]]", (make_rhyme_link(lang))}
if #parts > 0 then
local last = parts[#parts]
parts[#parts] = nil
local prefix = ""
for i, part in ipairs(parts) do
prefix = prefix .. part
parts[i] = prefix
end
for _, part in ipairs(parts) do
insert(steps, (make_rhyme_link(lang, part .. "-", "-" .. part .. "-")))
end
if last == "-" then
insert(steps, (make_rhyme_link(lang, prefix, "-" .. prefix)))
insert(categories, "[[Category:" .. langname .. "韻部" .. (prefix == "" and "" or "/" .. prefix .. "-") .. "| ]]")
elseif mw.title.getCurrentTitle().text == langname .. "/" .. prefix .. last .. "-" then
insert(steps, (make_rhyme_link(lang, prefix .. last .. "-", "-" .. prefix .. last .. "-")))
insert(categories, "[[Category:" .. langname .. "韻部/" .. prefix .. last .. "-|-]]")
else
insert(steps, (make_rhyme_link(lang, prefix .. last, "-" .. prefix .. last)))
insert(categories, "[[Category:" .. langname .. "韻部" .. (prefix == "" and "" or "/" .. prefix .. "-") .. "|" .. last .. "]]")
end
elseif lang:getCode() ~= "und" then
insert(categories, "[[Category:" .. langname .. "韻部| ]]")
end
if mw.title.getCurrentTitle().nsText == "Rhymes" then
frame:callParserFunction("DISPLAYTITLE",
mw.title.getCurrentTitle().fullText:gsub(
"/(.+)$",
function (rhyme)
return "/" .. (tag_rhyme(rhyme, lang)) -- ignore cleanup categories
end))
end
local templateStyles = require(TemplateStyles_module)(rhymes_styles_css_module)
local ol = mw.html.create("ol")
for _, step in ipairs(steps) do
ol:node(mw.html.create("li"):wikitext(step))
end
local div = mw.html.create("div")
:attr("role", "navigation")
:attr("aria-label", "Breadcrumb")
:addClass("ts-rhymesBreadcrumbs")
:node(ol)
local formatted_cats = args.nocat and "" or concat(categories)
return templateStyles .. tostring(div) .. formatted_cats
end
return export