Module:nyms: Difference between revisions

From Linguifex
Jump to navigation Jump to search
No edit summary
No edit summary
 
Line 1: Line 1:
local export = {}
local export = {}


local m_languages = require("Module:languages")
local labels_module = "Module:labels"
local m_links = require("Module:links")
local links_module = "Module:links"
local m_qual = require("Module:qualifier")
local parameter_utilities_module = "Module:parameter utilities"
local rsplit = mw.text.split
local parse_utilities_module = "Module:parse utilities"
local pron_qualifier_module = "Module:pron qualifier"


local function wrap_span(text, lang, sc)
local function wrap_span(text, lang, sc)
return '<span class="' .. sc .. '" lang="' .. lang .. '">' .. text .. '</span>'
return '<span class="' .. sc .. '" lang="' .. lang .. '">' .. text .. '</span>'
end
end


local function get_thesaurus_text(lang, args, maxindex)
 
local thesaurus
local function term_already_linked(term)
local thesaurus_links = {}
-- optimization to avoid unnecessarily loading [[Module:parse utilities]]
return term:find("[<{]") and require(parse_utilities_module).term_already_linked(term)
while args[2][maxindex] and args[2][maxindex]:find("^Thesaurus:") do
end
if args["alt"][maxindex] or args["g"][maxindex] or args["q"][maxindex]
 
or args["tr"][maxindex] or args["ts"][maxindex] or args["id"][maxindex]
 
or args["lit"][maxindex] or args["pos"][maxindex] then
function export.nyms(frame)
error("You cannot use named parameters with Thesaurus links.")
local parent_args = frame:getParent().args
 
-- FIXME: Temporary error message and tracking.
for arg, _ in pairs(parent_args) do
if type(arg) == "string" and arg:find("^lb[0-9]*$") then
local llarg = arg:gsub("^lb", "ll")
error(("%s= is deprecated; use %s= instead, per the documentation"):format(arg, llarg))
end
end
local link
if type(arg) == "string" and arg:find("^tag[0-9]*$") then
local term = args[2][maxindex]:sub(11) -- remove Thesaurus: from beginning
local larg = arg:gsub("^tag", "l")
local sc = require("Module:scripts").findBestScript(term, lang):getCode()
local llarg = arg:gsub("^tag", "ll")
local fragment = term:find("#")
error(("Use %s= (on the left) or %s= (on the right) instead of %s="):format(larg, llarg, arg))
if fragment then
link = "[[" .. args[2][maxindex] .. "|Thesaurus:" .. wrap_span(term:sub(1, fragment-1), lang:getCode(), sc) .. "]]"
else
link = "[[" .. args[2][maxindex] .. "|Thesaurus:" .. wrap_span(term, lang:getCode(), sc) .. "]]"
end
end
table.insert(thesaurus_links, 1, link)
maxindex = maxindex - 1
end
if #thesaurus_links > 0 then
thesaurus = (maxindex == 0 and "''see'' " or "; ''see also'' ")
.. table.concat(thesaurus_links, ", ")
end
end
return thesaurus or "", maxindex
end


function export.nyms(frame)
local list_with_holes = {list = true, allow_holes = true}
local params = {
local params = {
[1] = {required = true, default = "und"},
[1] = {required = true, type = "language", default = "und"},
[2] = {list = true, allow_holes = true, required = true},
[2] = {list = true, allow_holes = true, required = true},
}
["alt"] = list_with_holes,
 
["tr"] = list_with_holes,
    local m_param_utils = require(parameter_utilities_module)
["ts"] = list_with_holes,
 
["t"] = list_with_holes,
local param_mods = m_param_utils.construct_param_mods {
["id"] = list_with_holes,
{group = {"link", "ref", "l"}},
["q"] = list_with_holes,
-- For compatibility, we don't distinguish q= from q1= and qq= from q1=. FIXME: Maybe we should change this.
["lit"] = list_with_holes,
{group = "q", separate_no_index = false},
["pos"] = list_with_holes,
{param = "lb", deprecated = true},
["g"] = list_with_holes,
}
}
local args = require("Module:parameters").process(frame:getParent().args, params)
local special_separators = mw.clone(m_param_utils.default_special_separators)
special_separators["<"] = " < "
 
local items, args = m_param_utils.parse_list_with_inline_modifiers_and_separate_params {
params = params,
param_mods = param_mods,
raw_args = parent_args,
termarg = 2,
parse_lang_prefix = true,
lang = 1,
special_separators = special_separators,
sc = "sc.default",
}
 
local nym_type = frame.args[1]
local nym_type = frame.args[1]
local nym_type_class = string.gsub(nym_type, "%s", "-")
local nym_type_class = string.gsub(nym_type, "%s", "-")
local lang = m_languages.getByCode(args[1]) or m_languages.err(args[1], 1)
local lang = args[1]
local langcode = lang:getCode()
local maxindex = math.max(args[2].maxindex, args["alt"].maxindex, args["tr"].maxindex)
 
local thesaurus, link_maxindex = get_thesaurus_text(lang, args, maxindex)
local data = {
lang = lang,
local items = {}
items = items,
local use_semicolon = false
sc = args.sc.default,
l = args.l.default,
for i = 1, link_maxindex do
ll = args.ll.default,
if args[2][i] then
q = args.q.default,
if args[2][i]:find("^Thesaurus:") then
qq = args.qq.default,
error("A link to Thesaurus must be the last in the list")
}
 
local parts = {}
local thesaurus_parts = {}
for i, item in ipairs(data.items) do
if item.lb then
error("Inline modifier <lb:...> is deprecated; use <ll:...> per the documentation")
end
local explicit_item_lang = item.lang
item.lang = item.lang or data.lang
item.sc = item.sc or data.sc
local text
local is_thesaurus
if item.term and item.term:find("^Thesaurus:") then
is_thesaurus = true
for k, _ in pairs(item) do
if m_param_utils.item_key_is_property(k) and k ~= "lang" and k ~= "sc" and k ~= "q" and k ~= "qq" and
k ~= "l" and k ~= "ll" and k ~= "refs" then
error(("You cannot use most named parameters and inline modifiers with Thesaurus links, but saw %s%s= or its equivalent inline modifier <%s:...>"):format(
k, item.itemno, k))
end
end
local term = item.term:match("^Thesaurus:(.*)$")
-- Chop off fragment
term = term:match("^(.-)#.*$") or term
local lang = item.lang
local sccode = (item.sc or lang:findBestScript(term)):getCode()
-- FIXME: I assume it's better to include full-language codes in the CSS rather than etym-language codes,
-- which are generally specific to Wiktionary. However, we should probably instead be using the functions
-- from [[Module:script utilities]] in preference to rolling our own.
text = "[[" .. item.term .. "#" .. lang:getFullName() .. "|Thesaurus:" .. wrap_span(term, lang:getFullCode(), sccode) .. "]]"
else
if thesaurus_parts[1] then
error("Links to the Thesaurus must follow all non-Thesaurus links")
end
local raw_term = item.alt or item.term
if raw_term and term_already_linked(raw_term) then
text = raw_term
else
text = require(links_module).full_link(item)
end
end
if args[2][i]:find(",", 1, true) then
end
use_semicolon = true
local qq = item.qq
-- If a separate language code was given for the term, display the language name as a right qualifier.
-- Otherwise it may not be obvious that the term is in a separate language (e.g. if the main language is 'zh'
-- and the term language is a Chinese lect such as Min Nan). But don't do this for Translingual terms, which
-- are often added to the list of English and other-language terms.
if explicit_item_lang then
local explicit_code = explicit_item_lang:getCode()
if explicit_code ~= langcode and explicit_code ~= "mul" then
qq = mw.clone(qq) or {}
table.insert(qq, 1, explicit_item_lang:getCanonicalName())
end
end
end
end
if item.q and item.q[1] or qq and qq[1] or item.l and item.l[1] or item.ll and item.ll[1] or
local item = m_links.full_link{
item.refs and item.refs[1] then
lang = lang, term = args[2][i], id = args["id"][i],
text = require(pron_qualifier_module).format_qualifiers {
alt = args["alt"][i], tr = args["tr"][i], ts = args["ts"][i],
lang = item.lang,
gloss = args["t"][i], lit = args["lit"][i], pos = args["pos"][i],
text = text,
genders = args["g"][i] and rsplit(args["g"][i], ",") or {},
q = item.q,
qq = qq,
l = item.l,
ll = item.ll,
refs = item.refs,
}
end
local insert_place = is_thesaurus and thesaurus_parts or parts
-- Don't include the separator if this is the first item of this class that we're inserting.
table.insert(insert_place, insert_place[1] and item.separator or "")
table.insert(insert_place, text)
end
 
local text = table.concat(parts)
local thesaurus_text = table.concat(thesaurus_parts)
 
local caption = "<span style=\"font-size: smaller\">" .. mw.getContentLanguage():ucfirst(nym_type) ..
((#items > 1 or thesaurus_text ~= "") and "s" or "") .. ":</span> "
text = caption .. text
local function qualifier_error_if_no_terms()
if not parts[1] then
error("Cannot specify overall qualifiers if no non-Thesaurus terms given")
end
end
if data.q and data.q[1] or data.qq and data.qq[1] or data.l and data.l[1] then
qualifier_error_if_no_terms()
text = require(pron_qualifier_module).format_qualifiers {
lang = data.lang,
text = text,
q = data.q,
qq = data.qq,
l = data.l,
-- ll handled specially for compatibility's sake
}
end
if data.ll and data.ll[1] then
qualifier_error_if_no_terms()
text = text .. " &mdash; " .. require(labels_module).show_labels {
lang = data.lang,
labels = data.ll,
nocat = true,
open = false,
close = false,
}
}
if args["q"][i] then
item = m_qual.format_qualifier({args["q"][i]}) .. " " .. item
end
table.insert(items, item)
end
end
if thesaurus_text ~= "" then
return "<span class=\"nyms " .. nym_type_class .. "\"><span class=\"defdate\" style=\"font-size: smaller;\">" ..
local thesaurus_intro = parts[1] and "; ''see also'' " or "''see'' "
mw.getContentLanguage():ucfirst(nym_type) .. ((#items > 1 or thesaurus ~= "") and "s" or "") ..
text = text .. thesaurus_intro .. thesaurus_text
":</span> " .. table.concat(items, use_semicolon and "; " or ", ") .. thesaurus .. "</span>"
end
return "<span class=\"nyms " .. nym_type_class .. "\">" .. text .. "</span>"
end
end




return export
return export

Latest revision as of 00:53, 20 February 2026



local export = {}

local labels_module = "Module:labels"
local links_module = "Module:links"
local parameter_utilities_module = "Module:parameter utilities"
local parse_utilities_module = "Module:parse utilities"
local pron_qualifier_module = "Module:pron qualifier"

	
local function wrap_span(text, lang, sc)
	return '<span class="' .. sc .. '" lang="' .. lang .. '">' .. text .. '</span>'
end


local function term_already_linked(term)
	-- optimization to avoid unnecessarily loading [[Module:parse utilities]]
	return term:find("[<{]") and require(parse_utilities_module).term_already_linked(term)
end


function export.nyms(frame)
	local parent_args = frame:getParent().args

	-- FIXME: Temporary error message and tracking.
	for arg, _ in pairs(parent_args) do
		if type(arg) == "string" and arg:find("^lb[0-9]*$") then
			local llarg = arg:gsub("^lb", "ll")
			error(("%s= is deprecated; use %s= instead, per the documentation"):format(arg, llarg))
		end
		if type(arg) == "string" and arg:find("^tag[0-9]*$") then
			local larg = arg:gsub("^tag", "l")
			local llarg = arg:gsub("^tag", "ll")
			error(("Use %s= (on the left) or %s= (on the right) instead of %s="):format(larg, llarg, arg))
		end
	end

	local params = {
		[1] = {required = true, type = "language", default = "und"},
		[2] = {list = true, allow_holes = true, required = true},
	}

    local m_param_utils = require(parameter_utilities_module)

	local param_mods = m_param_utils.construct_param_mods {
		{group = {"link", "ref", "l"}},
		-- For compatibility, we don't distinguish q= from q1= and qq= from q1=. FIXME: Maybe we should change this.
		{group = "q", separate_no_index = false},
		{param = "lb", deprecated = true},
	}
	
	local special_separators = mw.clone(m_param_utils.default_special_separators)
	special_separators["<"] = " < "

	local items, args = m_param_utils.parse_list_with_inline_modifiers_and_separate_params {
		params = params,
		param_mods = param_mods,
		raw_args = parent_args,
		termarg = 2,
		parse_lang_prefix = true,
		lang = 1,
		special_separators = special_separators,
		sc = "sc.default",
	}

	local nym_type = frame.args[1]
	local nym_type_class = string.gsub(nym_type, "%s", "-")
	local lang = args[1]
	local langcode = lang:getCode()

	local data = {
		lang = lang,
		items = items,
		sc = args.sc.default,
		l = args.l.default,
		ll = args.ll.default,
		q = args.q.default,
		qq = args.qq.default,
	}

	local parts = {}
	local thesaurus_parts = {}
	for i, item in ipairs(data.items) do
		if item.lb then
			error("Inline modifier <lb:...> is deprecated; use <ll:...> per the documentation")
		end
		local explicit_item_lang = item.lang
		item.lang = item.lang or data.lang
		item.sc = item.sc or data.sc
		local text
		local is_thesaurus
		if item.term and item.term:find("^Thesaurus:") then
			is_thesaurus = true
			for k, _ in pairs(item) do
				if m_param_utils.item_key_is_property(k) and k ~= "lang" and k ~= "sc" and k ~= "q" and k ~= "qq" and
					k ~= "l" and k ~= "ll" and k ~= "refs" then
					error(("You cannot use most named parameters and inline modifiers with Thesaurus links, but saw %s%s= or its equivalent inline modifier <%s:...>"):format(
						k, item.itemno, k))
				end
			end
			local term = item.term:match("^Thesaurus:(.*)$")
			-- Chop off fragment
			term = term:match("^(.-)#.*$") or term
			local lang = item.lang
			local sccode = (item.sc or lang:findBestScript(term)):getCode()
			-- FIXME: I assume it's better to include full-language codes in the CSS rather than etym-language codes,
			-- which are generally specific to Wiktionary. However, we should probably instead be using the functions
			-- from [[Module:script utilities]] in preference to rolling our own.
			text = "[[" .. item.term .. "#" .. lang:getFullName() .. "|Thesaurus:" .. wrap_span(term, lang:getFullCode(), sccode) .. "]]"
		else
			if thesaurus_parts[1] then
				error("Links to the Thesaurus must follow all non-Thesaurus links")
			end
			local raw_term = item.alt or item.term
			if raw_term and term_already_linked(raw_term) then
				text = raw_term
			else
				text = require(links_module).full_link(item)
			end
		end
		local qq = item.qq
		-- If a separate language code was given for the term, display the language name as a right qualifier.
		-- Otherwise it may not be obvious that the term is in a separate language (e.g. if the main language is 'zh'
		-- and the term language is a Chinese lect such as Min Nan). But don't do this for Translingual terms, which
		-- are often added to the list of English and other-language terms.
		if explicit_item_lang then
			local explicit_code = explicit_item_lang:getCode()
			if explicit_code ~= langcode and explicit_code ~= "mul" then
				qq = mw.clone(qq) or {}
				table.insert(qq, 1, explicit_item_lang:getCanonicalName())
			end
		end
		if item.q and item.q[1] or qq and qq[1] or item.l and item.l[1] or item.ll and item.ll[1] or
			item.refs and item.refs[1] then
			text = require(pron_qualifier_module).format_qualifiers {
				lang = item.lang,
				text = text,
				q = item.q,
				qq = qq,
				l = item.l,
				ll = item.ll,
				refs = item.refs,
			}
		end
		local insert_place = is_thesaurus and thesaurus_parts or parts
		-- Don't include the separator if this is the first item of this class that we're inserting.
		table.insert(insert_place, insert_place[1] and item.separator or "")
		table.insert(insert_place, text)
	end

	local text = table.concat(parts)
	local thesaurus_text = table.concat(thesaurus_parts)

	local caption = "<span style=\"font-size: smaller\">" .. mw.getContentLanguage():ucfirst(nym_type) ..
		((#items > 1 or thesaurus_text ~= "") and "s" or "") .. ":</span> "
	text = caption .. text
	local function qualifier_error_if_no_terms()
		if not parts[1] then
			error("Cannot specify overall qualifiers if no non-Thesaurus terms given")
		end
	end
	if data.q and data.q[1] or data.qq and data.qq[1] or data.l and data.l[1] then
		qualifier_error_if_no_terms()
		text = require(pron_qualifier_module).format_qualifiers {
			lang = data.lang,
			text = text,
			q = data.q,
			qq = data.qq,
			l = data.l,
			-- ll handled specially for compatibility's sake
		}
	end
	if data.ll and data.ll[1] then
		qualifier_error_if_no_terms()
		text = text .. " &mdash; " .. require(labels_module).show_labels {
			lang = data.lang,
			labels = data.ll,
			nocat = true,
			open = false,
			close = false,
		}
	end
	if thesaurus_text ~= "" then
		local thesaurus_intro = parts[1] and "; ''see also'' " or "''see'' "
		text = text .. thesaurus_intro .. thesaurus_text
	end
	return "<span class=\"nyms " .. nym_type_class .. "\">" .. text .. "</span>"
end


return export