Module:gloss grid

Revision as of 21:57, 16 April 2025 by TheNightAvl (talk | contribs)

Underlies {{gloss grid}}.


local export = {}
local getArgs = require('Module:Arguments').getArgs

local m_inline = require("Module:inline")
local m_languages = require("Module:languages")

local table_style = "padding: 1em 0 1em 0" -- top right bottom left
local cell_style = "padding: 0 1em 0.2em 0"
local punctuation_regex = '[%.%,%(%)%—%!%?%"%:%;%*%/%&%_“”‘’%s]' -- specified because the %p pattern would include the apostrophe, which is still needed in links 

function build_grid(data)
	local grid = ""
	
	local function build(new)
		grid = grid .. new
	end
	
	local term_count = #data.terms
	
	if term_count > 10 then mw.addWarning("<div class=\"noprint maintenance-box maintenance-box-red\" style=\"background:#FFE7DD; width:90%; margin: 0.75em auto; border:1px dashed #884444; padding: 0.25em;\"><table><tr><td rowspan=\"2\">[[File:Nuvola_apps_important_yellow.svg|48px]]</td><th style=\"text-align: left;\">There are more than ten terms in the gloss grid!</th></tr><tr><td>You may want to consider splitting it up into multiple lines.</td></tr></table></div>") end
	
	build('<table class="blacklinks" style="' .. table_style .. '">')
		
		-- build term row
		build("<tr>")
			for _, term in ipairs(data.terms) do
				local cell_type = data.bold and "th" or "td"
				build('<'.. cell_type ..' style="' .. cell_style .. (data.bold and '; text-align: left' or '') .. '"><i>' .. term .. '</i></'.. cell_type ..'>')
			end
		build("</tr>")
		
		-- build split IPA row
		if data.IPAs then
			build("<tr>")
				for i = 1, term_count do
					if data.IPAs[i] then
						build('<td style="' .. cell_style .. '" class="IPA">' .. data.IPAs[i] .. '</td>')
					else
						build('<td />')
					end
				end
			build("</tr>")
		end
		
		-- build gloss row
		if data.glosses then
			build("<tr>")
				for i = 1, term_count do
					if data.glosses[i] then
						build('<td style="' .. cell_style .. '"><small>' .. data.glosses[i] .. '</small></td>')
					else
						build('<td />')
					end
				end
			build("</tr>")
		end
		
		-- build split translation row
		if data.translations then
			build("<tr>")
				for i = 1, term_count do
					if data.translations[i] then
						build('<td style="' .. cell_style .. '">' .. data.translations[i] .. '</td>')
					else
						build('<td />')
					end
				end
			build("</tr>")
		end
		
		-- build combined IPA row
		if data.s_IPA then
			build('<tr><td style="' .. cell_style .. '" class="IPA" colspan=' .. term_count .. '>' .. data.s_IPA .. '</td></tr>')
		end
		
		-- build combined translation row
		if data.s_translation then
			build('<tr><td style="' .. cell_style .. '" colspan=' .. term_count .. '>“' .. data.s_translation .. '”</td></tr>')
		end
	build("</table>")
	
	--[[

	|-
	| style="padding: 0em 1em 0.2em 0em; text-align: left" colspan=7 | ''A sheep that had no wool saw horses,''
	|}
	]]--
	return grid
end

function export.show(frame)
	local args = getArgs(frame)
	local lang = m_languages.find_by_code(args[1]).code
	
	local terms, glosses, translations, IPAs = {}, {}, {}, {}
	local nolinks = args["nolinks"] or args["nolink"] or false
	
	for i, arg in ipairs(args) do
		if i > 1 then
			if mw.ustring.match(arg, "^[^<]+:[^<]+") then arg = mw.ustring.gsub(arg, "^([^<]+):([^<]+)", "%2<alt:%1>") end
			local term, term_args = m_inline.parse(arg)
			
			if term_args["t"] then
				translations[i-1] = term_args["t"]
				term_args["t"] = nil
			end
			if term_args["gl"] or term_args["g"] then
				glosses[i-1] = term_args["gl"] or term_args["g"]
				term_args["gl"], term_args["g"] = nil, nil
			end
			if term_args["pr"] or term_args["p"] or term_args["ipa"] then
				IPAs[i-1] = term_args["pr"] or term_args["p"] or term_args["ipa"]
				term_args["pr"], term_args["p"], term_args["ipa"] = nil, nil, nil
			end
			
			if nolinks or term_args["nolink"] then
				terms[i-1] = term
			else
				-- allow manual bolding
				if mw.ustring.match(term, "'''") and term_args["alt"] == nil then
					term_args["alt"] = term
					term = mw.ustring.gsub(term, "'''", "")
				end
				
				--- unlink punctuation at start or end of term
				local pre, post
				if term_args["alt"] then
					pre = mw.ustring.match(term_args["alt"], "^(" .. punctuation_regex .. "+)") or ""
					post = mw.ustring.match(term_args["alt"], "(" .. punctuation_regex .. "+)$") or ""
					term_args["alt"] = mw.ustring.gsub(term_args["alt"], "^(" .. punctuation_regex .. "+)", "")
					term_args["alt"] = mw.ustring.gsub(term_args["alt"], "(" .. punctuation_regex .. "+)$","")
				else
					pre = mw.ustring.match(term, "^(" .. punctuation_regex .. "+)") or ""
					post = mw.ustring.match(term, "(" .. punctuation_regex .. "+)$") or ""
					term = mw.ustring.gsub(term, "^(" .. punctuation_regex .. "+)", "")
					term = mw.ustring.gsub(term, "(" .. punctuation_regex .. "+)$","")
				end
				
				if #term == 0 then
					terms[i-1] = pre .. post
				else
					term_args[1], term_args[2] = lang, term
					terms[i-1] = pre .. frame:expandTemplate{title = "l", args = term_args} .. post
				end
			end
		end
	end
	
	return build_grid{
		terms = terms,
		IPAs = IPAs,
		glosses = glosses,
		translations = translations,
		s_IPA = args["pr"] or args["p"] or args["ipa"],
		s_translation = args["t"],
		bold = (args["bold"] ~= nil)
	}
end

return export

--[[
Debug console test string:
=p.show(mw.getCurrentFrame():newChild{title="whatever",args={"rad", "Gaks,<ipa:[ˈɡaks><g:sheep-NOM.SG>", "vân<pr:vɤn><g:3S.ANIM-DAT>", "gjeș<ipa:jɛʃ><t:relativising particle>", "hreņuog<ipa:ˈxrɛŋuoɡ><g:wool-GEN.SG>", "húe<alt:húe,><ipa:ˈhuːɛ]><g:NEG.PST-DISJ.SG>", ["t"] = "A sheep which had no wool"}})
]]