Module:gloss grid

From Laenkea
Jump to navigation Jump to search

Underlies {{gloss grid}}.


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

local m_gloss = require('Module:gloss')
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; vertical-align: top"
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 term_count = #data.terms
	local function build(new)
		grid = grid .. new
	end
	
	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>")
			if data.IPAs and data.IPAs[1] then build("<td />") end -- extra column for alignment
			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>")
				if data.IPAs[1] then
					build('<td style="' .. mw.ustring.gsub(cell_style, "padding: (%S+) %S+ (%S+)", "padding: %1 %2 %2") .. '" class="IPA nolarge">' .. (data.phonemic and "/" or "[") .. "</td>")
				end
				for i = 1, term_count do
					if data.IPAs[i] then
						local ipa_temp = data.IPAs[i]
						if i == term_count then
							ipa_temp = ipa_temp .. (data.phonemic and " /" or " ]")
						end
						build('<td style="' .. cell_style .. '" class="IPA nolarge">' .. ipa_temp .. '</td>')
					elseif i == 1 then
						build('<td style="' .. cell_style .. '; text-align:right" class="IPA nolarge">' .. (data.phonemic and "/" or "[") .. '</td>')
					elseif i == term_count then
						build('<td style="' .. cell_style .. '; text-align:right" class="IPA nolarge">' .. (data.phonemic and "/" or "]") .. '</td>')
					else
						build('<td />')
					end
				end
			build("</tr>")
		end
		
		-- build gloss row
		if data.glosses then
			build("<tr>")
				if data.IPAs and data.IPAs[1] then build("<td />") end -- extra column for alignment
				for i = 1, term_count do
					if data.glosses[i] then
						build('<td style="' .. cell_style .. '">' .. m_gloss.show(mw.getCurrentFrame():newChild{title="title",args={data.glosses[i]}}) .. '</td>')
					else
						build('<td />')
					end
				end
			build("</tr>")
		end
		
		-- build split translation row
		if data.translations then
			build("<tr>")
				if data.IPAs and data.IPAs[1] then build("<td />") end -- extra column for alignment
				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>")
			if data.IPAs and data.IPAs[1] then build("<td />") end -- extra column for alignment
			build('<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>")
			if data.IPAs and data.IPAs[1] then build("<td />") end -- extra column for alignment
			build('<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 g_count, t_count, p_count = 0, 0, 0
	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 pre_colon, post_colon = mw.ustring.match(arg, "<alt:([^>]*):([^>]*)>") -- store any colons in alt: parameter
			
			local term, term_args = m_inline.parse(arg)
			
			if pre_colon or post_colon then term_args.alt = (pre_colon or "") .. ":" .. (post_colon or "") end-- resolve colons in alt: parameter
			
			if term_args["t"] then
				translations[i-1] = term_args["t"]
				term_args["t"] = nil
				t_count = t_count + 1
			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
				g_count = g_count + 1
			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
				p_count = p_count + 1
			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
	
	local send_build = {
		terms = terms,
		s_IPA = args["pr"] or args["p"] or args["ipa"],
		s_translation = args["t"],
		bold = (args["bold"] ~= nil),
		phonemic = (args["phnm"] ~= nil)
	}
	if p_count > 0 then send_build["IPAs"] = IPAs end
	if g_count > 0 then send_build["glosses"] = glosses end
	if t_count > 0 then send_build["translations"] = translations end
	return build_grid(send_build)
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"}})
]]