Module:inc-ash/dial

From Wiktionary, the free dictionary
Jump to navigation Jump to search

This module needs documentation.
Please document this module by describing its purpose and usage on the documentation page.

local lang = require("Module:languages").getByCode("inc-ash")
local m_links = require("Module:links")
local iut = require("Module:inflection utilities")
local m_string_utilities = require("Module:string utilities")
local sub = mw.ustring.sub
local variety_data = require("Module:inc-ash/dial/data")

local export = {}

local variety_list = {
	"Central", "East", "Northwest", "West", "South"
}

local variety_colour = {
	["Central"]		= "FAF5F0",
	["East"]		= "F0F5FA",
	["Northwest"]	= "F0FAF3",
	["West"]		= "FAF0F6",
	["South"]		= "FAF9F0",
}

local dots = {
	"d2502e", "6941c7", "9fdd42", "c74dc9", "6ccb6e", 
	"d34280", "77d6ba", "4f286c", "d1b94e", "777ad0", 
	"557433", "cf8ebf", "342a29", "c7c3a2", "7f3241", 
	"8ab8d7", "8d6234", "5b6080", "da8573", "4e7a6e"
}

local special_note = {
	-- none yet
}

-- declension
local genders = {"m", "f", "n"}
local numbers = {"sg", "pl"}
local cases = {"nom", "acc", "ins", "dat", "abl", "gen", "loc"}
local cases_full = {"nominative", "accusative", "instrumental", "dative", "ablative", "genitive", "locative"}
local persons = {"1", "2", "3"}
local persons_full = {"1st", "2nd", "3rd"}
local moods = {"pres", "imp", "potn", "impf", "aor", "fut"}
local moods_full = {"present", "imperative", "potential", "imperfect", "aorist", "future"}

local slots = {}
slots["noun"] = {
	{"nom.sg", "nom|sg"}, {"nom.pl", "nom|pl"},
	{"acc.sg", "acc|sg"}, {"acc.pl", "acc|pl"},
	{"ins.sg", "ins|sg"}, {"ins.pl", "ins|pl"},
	{"dat.sg", "dat|sg"}, {"dat.pl", "dat|pl"},
	{"abl.sg", "abl|sg"}, {"abl.pl", "abl|pl"},
	{"gen.sg", "gen|sg"}, {"gen.pl", "gen|pl"},
	{"loc.sg", "loc|sg"}, {"loc.pl", "loc|pl"},
}
slots["adj"] = {
	{"m.nom.sg", "m|nom|sg"}, {"m.nom.pl", "m|nom|pl"}, {"f.nom.sg", "f|nom|sg"}, {"f.nom.pl", "f|nom|pl"}, {"n.nom.sg", "n|nom|sg"}, {"n.nom.pl", "n|nom|pl"},
	{"m.acc.sg", "m|acc|sg"}, {"m.acc.pl", "m|acc|pl"}, {"f.acc.sg", "f|acc|sg"}, {"f.acc.pl", "f|acc|pl"}, {"n.acc.sg", "n|acc|sg"}, {"n.acc.pl", "n|acc|pl"},
	{"m.ins.sg", "m|ins|sg"}, {"m.ins.pl", "m|ins|pl"}, {"f.ins.sg", "f|ins|sg"}, {"f.ins.pl", "f|ins|pl"}, {"n.ins.sg", "n|ins|sg"}, {"n.ins.pl", "n|ins|pl"},
	{"m.dat.sg", "m|dat|sg"}, {"m.dat.pl", "m|dat|pl"}, {"f.dat.sg", "f|dat|sg"}, {"f.dat.pl", "f|dat|pl"}, {"n.dat.sg", "n|dat|sg"}, {"n.dat.pl", "n|dat|pl"},
	{"m.abl.sg", "m|abl|sg"}, {"m.abl.pl", "m|abl|pl"}, {"f.abl.sg", "f|abl|sg"}, {"f.abl.pl", "f|abl|pl"}, {"n.abl.sg", "n|abl|sg"}, {"n.abl.pl", "n|abl|pl"},
	{"m.gen.sg", "m|gen|sg"}, {"m.gen.pl", "m|gen|pl"}, {"f.gen.sg", "f|gen|sg"}, {"f.gen.pl", "f|gen|pl"}, {"n.gen.sg", "n|gen|sg"}, {"n.gen.pl", "n|gen|pl"},
	{"m.loc.sg", "m|loc|sg"}, {"m.loc.pl", "m|loc|pl"}, {"f.loc.sg", "f|loc|sg"}, {"f.loc.pl", "f|loc|pl"}, {"n.loc.sg", "n|loc|sg"}, {"n.loc.pl", "n|loc|pl"},
}
slots["verb"] = {
	{"1sg.pres", "1|sg|pres"}, {"2sg.pres", "2|sg|pres"}, {"3sg.pres", "3|sg|pres" }, {"1pl.pres", "1|pl|pres"}, {"2pl.pres", "2|pl|pres"}, {"3pl.pres", "3|pl|pres" },
	-- add middle, passive
	{"1sg.imp", "1|sg|imp"}, {"2sg.imp", "2|sg|imp"}, {"3sg.imp", "3|sg|imp" }, {"1pl.imp", "1|pl|imp"}, {"2pl.imp", "2|pl|imp"}, {"3pl.imp", "3|pl|imp" },
	{"1sg.potn", "1|sg|potn"}, {"2sg.potn", "2|sg|potn"}, {"3sg.potn", "3|sg|potn" }, {"1pl.potn", "1|pl|potn"}, {"2pl.potn", "2|pl|potn"}, {"3pl.potn", "3|pl|potn" },
	{"1sg.impf", "1|sg|impf"}, {"2sg.impf", "2|sg|impf"}, {"3sg.impf", "3|sg|impf" }, {"1pl.impf", "1|pl|impf"}, {"2pl.impf", "2|pl|impf"}, {"3pl.impf", "3|pl|impf" },
	{"1sg.aor", "1|sg|aor"}, {"2sg.aor", "2|sg|aor"}, {"3sg.aor", "3|sg|aor" }, {"1pl.aor", "1|pl|aor"}, {"2pl.aor", "2|pl|aor"}, {"3pl.aor", "3|pl|aor" },
	{"1sg.fut", "1|sg|fut"}, {"2sg.fut", "2|sg|fut"}, {"3sg.fut", "3|sg|fut" }, {"1pl.fut", "1|pl|fut"}, {"2pl.fut", "2|pl|fut"}, {"3pl.fut", "3|pl|fut" },
}

-- format a link for the dialect table, including notes
function format_link(word, all_notes, alt)
	notes = mw.text.split(all_notes or "", "; ")
	local filtered_notes = {}
	local partial = false
	for _, note in ipairs(notes) do
		if note == "partial" then
			partial = true
		else
			table.insert(filtered_notes, note)
		end
	end
	local note = table.concat(filtered_notes, "; ")
	return ((partial and "<sup>?</sup>") or "") .. m_links.full_link({
		term = word,
		alt = alt,
		lang = lang,
		tr = "-",
	}) .. ((note and (' <span style="font-size:60%"><i>' .. note .. '</i></span>')) or '') .. ' <small>(' .. lang:transliterate(word or alt) .. ')</small>'
end

function get_lemma(word)
	return mw.ustring.match(word, "{(.*)}") or mw.ustring.match(word, "<(.*)>") or word
end

function remove_lemma_indicators(word)
	return mw.ustring.gsub(mw.ustring.gsub(word, "{.*}", ""), "[<>]", "")
end

local function make_table(data, pos)
	local result = ""
	if pos == "adj" then
		result = [=[
{| class="inflection-table vsSwitcher" data-toggle-category="declension" style="background:var(--wikt-palette-lavender, #f8f8ff); text-align:center; min-width:45em; border: 1px solid #9e9e9e;"
|- style="background: var(--wikt-palette-lightblue, #d9ebff);"
! class="vsToggleElement" style="text-align: left;" colspan="7" | Declension of {lemma}
|- class="vsHide"
! style="background:var(--wikt-palette-lightblue, #d9ebff); width:25%" rowspan="2" |
! style="background:var(--wikt-palette-lightblue, #d9ebff)" colspan="2" | masculine
! style="background:var(--wikt-palette-lightblue, #d9ebff)" colspan="2" | feminine
! style="background:var(--wikt-palette-lightblue, #d9ebff)" colspan="2" | neuter
|- class="vsHide"
! style="background:var(--wikt-palette-lightblue, #d9ebff)" | singular
! style="background:var(--wikt-palette-lightblue, #d9ebff)" | plural
! style="background:var(--wikt-palette-lightblue, #d9ebff)" | singular
! style="background:var(--wikt-palette-lightblue, #d9ebff)" | plural
! style="background:var(--wikt-palette-lightblue, #d9ebff)" | singular
! style="background:var(--wikt-palette-lightblue, #d9ebff)" | plural]=]
	
		for i, case in ipairs(cases) do
			local row = '\n|- class="vsHide"'
			row = row .. '\n! style="background:var(--wikt-palette-lighterblue, #ebf4ff)" | ' .. cases_full[i]
			for _, gender in ipairs(genders) do
				for _, number in ipairs(numbers) do
					row = row .. '\n| {' .. gender .. '.' .. case ..  '.' .. number .. '}'
				end
			end
			result = result .. row
		end
		
		result = result .. "\n{notes_clause}\n|}"
	elseif pos == "noun" then
		result = [=[
{| class="inflection-table vsSwitcher" data-toggle-category="declension" style="background:var(--wikt-palette-lavender, #f8f8ff); text-align:center; min-width:45em; border: 1px solid #9e9e9e;"
|- style="background: var(--wikt-palette-lightblue, #d9ebff);"
! class="vsToggleElement" style="text-align: left;" colspan="3" | Declension of {lemma}
|- class="vsHide"
! style="background:var(--wikt-palette-lightblue, #d9ebff); width:33%" |
! style="background:var(--wikt-palette-lightblue, #d9ebff)" | singular
! style="background:var(--wikt-palette-lightblue, #d9ebff)" | plural]=]
	
		for i, case in ipairs(cases) do
			local row = '\n|- class="vsHide"'
			row = row .. '\n! style="background:var(--wikt-palette-lighterblue, #ebf4ff)" | ' .. cases_full[i]
			for _, number in ipairs(numbers) do
				row = row .. '\n| {' .. case ..  '.' .. number .. '}'
			end
			result = result .. row
		end
		
		result = result .. "\n{notes_clause}\n|}"
	elseif pos == "verb" then
		result = [=[
{| class="inflection-table vsSwitcher" data-toggle-category="declension" style="background:var(--wikt-palette-lavender, #f8f8ff); text-align:center; min-width:45em; border: 1px solid #9e9e9e;"
|- style="background: var(--wikt-palette-lightblue, #d9ebff);"
! class="vsToggleElement" style="text-align: left;" colspan="7" | Personal forms of {lemma}
|- class="vsHide"
! style="background:var(--wikt-palette-lightblue, #d9ebff); width:33%" rowspan="2" |
! style="background:var(--wikt-palette-lightblue, #d9ebff)" colspan="3" | singular
! style="background:var(--wikt-palette-lightblue, #d9ebff)" colspan="3" | plural
|- class="vsHide"
! style="background:var(--wikt-palette-lightblue, #d9ebff)" | 1st
! style="background:var(--wikt-palette-lightblue, #d9ebff)" | 2nd
! style="background:var(--wikt-palette-lightblue, #d9ebff)" | 3rd
! style="background:var(--wikt-palette-lightblue, #d9ebff)" | 1st
! style="background:var(--wikt-palette-lightblue, #d9ebff)" | 2nd
! style="background:var(--wikt-palette-lightblue, #d9ebff)" | 3rd]=]
	
		for i, mood in ipairs(moods) do
			local row = '\n|- class="vsHide"'
			row = row .. '\n! style="background:var(--wikt-palette-lighterblue, #ebf4ff)" | ' .. moods_full[i]
			for _, number in ipairs(numbers) do
				for _, person in ipairs(persons) do
					row = row .. '\n| {' .. person .. number ..  '.' .. mood .. '}'
				end
			end
			result = result .. row
		end
		
		result = result .. "\n{notes_clause}\n|}"
	end

	local notes_template = [===[
|- class="vsHide"
| colspan=3 | 
<div class="hi-footnote-outer-div">
<div class="hi-footnote-inner-div">
{footnote}
</div></div>
]===]
	
	-- footnotes
	data.forms.notes_clause = data.forms.footnote ~= "" and
		m_string_utilities.format(notes_template, data.forms) or ""
	data.forms.desc = data.desc
	data.forms.lemma = format_link(data.lemma)
	result = m_string_utilities.format(result, data.forms)
		
	return result
end

function export.inflection(frame)
	local args = frame:getParent().args
	local pagename = mw.title.getCurrentTitle().text
	local target_page = args[1] or pagename
	local main_lemma = args[2] or pagename
	local resource_page = "Module:inc-ash/dial/data/" .. target_page
	
	-- get page data
	if mw.title.new(resource_page).exists then
		m_syndata = require(resource_page).list
	else
		return frame:expandTemplate{ title = "Template:inc-ash-dial/uncreated", args = { target_page } }
	end
	
	-- remove unnecessary data
	m_syndata["meaning"] = nil
	local pos = m_syndata["pos"] or "none"
	m_syndata["pos"] = nil
	if m_syndata["note"] then
		note = m_syndata["note"]
		m_syndata["note"] = nil
	end
	if pos == nil then
		error("Please specify a valid pos in the resource page " .. resource_page)
	end
	
	-- slots
	local props = {
	  lang = lang,
	  lemmas = {main_lemma},
	  slot_list = slots[pos],
	  include_translit = true,
	  create_footnote_obj = nil,
	  canonicalize = nil,
	  preprocess_forms = nil,
	  no_deduplicate_forms = false,
	  combine_metadata_during_dedup = nil,
	  transform_accel_obj = nil,
	  format_forms = nil,
	  generate_link = nil,
	  format_tr = nil,
	  join_spans = nil,
	  allow_footnote_symbols = nil,
	  footnotes = nil,
	}
	
	-- get forms
	local data = {forms = {}}
	data.forms.footnote = ""
	-- local process = ""
	for location, synonym_set in pairs(m_syndata) do
		-- check if location is in alias list and use the proper one if so
		if variety_data['aliases'][location] ~= nil then location = variety_data['aliases'][location] end
		if synonym_set[1] ~= "" then
			for i, synonym in ipairs(synonym_set) do
				local synonym_decomp = mw.text.split(synonym, ":")
				local lemma = get_lemma(synonym_decomp[1])
				synonym_decomp[1] = remove_lemma_indicators(synonym_decomp[1])
				if lemma == main_lemma then
					local notes = mw.text.split(synonym_decomp[2] or "", "; ")
					for _, gloss in ipairs(notes) do
						iut.insert_form(data.forms, gloss, {form=synonym_decomp[1]})
						-- process = process .. "\nInserted " .. synonym_decomp[1] .. " into " .. gloss
					end
				end
			end
		end
	end
	
	-- make table
	-- if pos == "verb" then return process end
	data.lemma = main_lemma
	iut.show_forms(data.forms, props)
	return make_table(data, pos)
end

function export.main(frame)
	local args = frame:getParent().args
	local pagename = mw.title.getCurrentTitle().text
	local target_page = args[1] or pagename
	local resource_page = "Module:inc-ash/dial/data/" .. target_page
	if mw.title.new(resource_page).exists then
		m_syndata = require(resource_page).list
	else
		return frame:expandTemplate{ title = "Template:inc-ash-dial/uncreated", args = { target_page } }
	end
	
	local template = {
		["Central"]		= {},
		["East"]		= {},
		["Northwest"]	= {},
		["West"]		= {},
		["South"]		= {},
	}

	main_title = mw.ustring.gsub((target_page == pagename and pagename or '[[' .. target_page .. ']]'), "[0-9%-]", "")
	text = [=[
	{| class="wikitable mw-collapsible mw-collapsed" style="margin:0; text-align:center;"
	|-
	! style="background:#FCFFFC; width:40em" colspan=4 | Dialectal forms of <b><span class="Brah" lang="inc-ash">]=] ..
		main_title .. '</span></b> (“' .. m_syndata["meaning"] .. '”) ' .. [=[
		
	|-
	! style="background:#E8ECFA" | Variety
	! style="background:#E8ECFA" | Location
	! style="background:#E8ECFA" | Lemmas
	! style="background:#E8ECFA; text-align: left;" | Forms]=] .. [=[
	<div style="float: right; clear: right; font-size:60%"><span class="plainlinks">[]=] ..
		tostring(mw.uri.fullUrl("Module:inc-ash/dial/data/" .. target_page, { ["action"] = "edit" })) ..
	' edit]</span></div>'
	
	m_syndata["meaning"] = nil
	local pos = m_syndata["pos"] or "none"
	m_syndata["pos"] = nil
	if m_syndata["note"] then
		note = m_syndata["note"]
		m_syndata["note"] = nil
	end
	
	local categories = ""
	
	for location, synonym_set in pairs(m_syndata) do
		-- check if location is in alias list and use the proper one if so
		if variety_data['aliases'][location] ~= nil then location = variety_data['aliases'][location] end
		
		local sc = "Brah"
		if location == "Shahbazgarhi" or location == "Mansehra" then
			sc = "Khar"
		end
		if synonym_set[1] ~= "" then
			local formatted_synonyms = {}
			local formatted_lemmas = {}
			for i, synonym in ipairs(synonym_set) do
				local synonym_decomp = mw.text.split(synonym, ":")
				local word =  remove_lemma_indicators(synonym_decomp[1])
				local lemma = get_lemma(synonym_decomp[1], pos, sc)
				if (synonym_decomp[1] ~= word) or (synonym_decomp[2] ~= nil) then
					table.insert(formatted_synonyms, {
						formatted = format_link(word, synonym_decomp[2], nil),
						form = word,
					})
				end
				formatted_lemmas[lemma] = format_link(lemma, nil, nil)
			end
			local location_data = variety_data[location]
			local location_name = mw.ustring.gsub(location_data.english or location, "(%(.*%))", "<small>%1</small>")
			local location_link = location_data.link or location_name
			table.insert(template[location_data.group],
				{ location_data.order, location_name, location_link, formatted_synonyms, formatted_lemmas })
		end
	end
	
	local attested = {}
	
	for _, variety in ipairs(variety_list) do
		local sc = "Brah"
		if variety == "Northwest" then
			sc = "Khar"
		end
		local colour = variety_colour[variety]
		if #template[variety] > 0 then
			table.sort(template[variety], function(first, second) return first[1] < second[1] end)
			for i, point_data in ipairs(template[variety]) do
				local forms = {}
				local lemmas = {}
				local attested_point = false
				for lemma_plain, lemma in pairs(point_data[5]) do
					if lemma_plain == pagename then
						attested_point = true
					end
					table.insert(lemmas, lemma)
				end
				for _, word in ipairs(point_data[4]) do
					if word.form == pagename then
						attested_point = true
					end
					table.insert(forms, word.formatted)
				end
				if attested_point then
					table.insert(attested, {point_data[3], point_data[2]})
					categories = categories .. "[[Category:" .. point_data[2] .. " Ashokan Prakrit]]"
				end
				text = text .. "\n|-"
				if i == 1 then
					text = text .. "\n!rowspan=" .. #template[variety] .. (special_note[variety] and " colspan=2" or "") .. 
					' style="background:#' .. colour .. '"| ' .. (special_note[variety] or variety)
				end
				text = text .. ((point_data[2] and not special_note[variety]) and ('\n|style="background:#' .. colour .. '"| ' .. 
					'[[w:' .. point_data[3] .. '|' .. point_data[2] .. ']]') or '') ..
					'\n| ' .. table.concat(lemmas, ", ") ..
					'\n|style="text-align: left;"| ' .. table.concat(forms, ", ")
			end
		end
	end

	if note and note ~= "" then
		text = text .. '\n|-\n! style="background:#FFF7FB; padding-top:5px; padding-bottom: 5px" | ' ..
			"<small>Note</small>\n| colspan=2|<small><i>" .. note .. "</i></small>"
	end
	
	local res = "Attested at "
	table.sort(attested, function(first, second) return first[2] < second[2] end)
	for i, dialect in ipairs(attested) do
		if i == #attested and i ~= 1 then
			res = res .. " and "
		elseif i ~= 1 then
			res = res .. ", "
		end
		res = res .. '[[w:' .. dialect[1] .. '|' .. dialect[2] .. ']]'
	end
	
	return res .. '.\n' .. text .. '\n|}' .. categories
end

function export.make_map(frame)
	local width = tonumber(frame.args["width"]) or 1200
	local word = frame.args[1] or mw.title.getCurrentTitle().text
	local syn_data = require("Module:inc-ash/dial/data/" .. word).list
	local map = [=[
		<div style="margin-left: auto; margin-right:auto; width:]=] .. width .. [=[px; max-width:]=] .. width .. [=[px;">
		<div><div style="height:]=] .. width * (1615/1500) .. [=[px;width:]=] .. width .. [=[px;overflow:auto;">
		<div style="position:relative;top:0;left:0">
		<div style="position:relative;top:0;left:0;line-height:0">[[File:India location map.svg|]=] .. width .. [=[px|link=]]</div>
		]=]
	local prelim_data, data, points, legend = {}, {}, {}, {}
	for location, synonym_set in pairs(syn_data) do
		-- check if location is in alias list and use the proper one if so
		local actual_location = location
		if variety_data['aliases'][location] ~= nil then actual_location = variety_data['aliases'][location] end
		if location ~= "note" and location ~= "meaning" and location ~= "pos" and variety_data[actual_location].lat and synonym_set[1] ~= "" then
			for _, term in ipairs(synonym_set) do
				term = get_lemma(mw.text.split(term, ":")[1])
				local lemma = lang:transliterate(term)
				if prelim_data[term] then
					prelim_data[term].count = prelim_data[term].count + 1
					table.insert(prelim_data[term].locations, location)
				else
					prelim_data[term] = { count = 1, locations = { location }, term = remove_lemma_indicators(term), lemma = lemma }
				end
			end
		end
	end
	for term, term_data in pairs(prelim_data) do
		table.insert(data, { term = term_data.term, count = term_data.count, locations = term_data.locations, lemma = term_data.lemma })
	end
	table.sort(data, function(first, second) return first.count > second.count end)
	
	local prev_count = data[1].count
	local greyed, greyed_count = false, 0
	local completed_lemmas = {}
	local num_completed = 0
	for _, d in ipairs(data) do
		local num = -1
		if completed_lemmas[d.lemma] then
			num = completed_lemmas[d.lemma]
		else
			num = num_completed + 1
			completed_lemmas[d.lemma] = num
			num_completed = num_completed + 1
		end
		greyed = greyed or (num > 10 and d.count ~= prev_count) or num > 20
		local colour = greyed and "CCCCBF" or dots[num]
		for _, location in ipairs(d.locations) do
			-- check if location is in alias list and use the proper one if so
			local actual_location = location
			if variety_data['aliases'][location] ~= nil then actual_location = variety_data['aliases'][location] end
			
			local loc_info = variety_data[actual_location]
			local top_offset, left_offset = 0, 0
			if table.getn(syn_data[location]) > 1 then
				top_offset = math.random(-300, 300) / 100
				left_offset = math.random(-300, 300) / 100
			end
			local top = ((37.5 - loc_info.lat) * (width*(1615/1500))/(37.5-5)) + top_offset
			local left = ((loc_info.long - 67) * width/(99-67)) + left_offset
			local loc_name = mw.ustring.gsub(loc_info.english or actual_location, "%((.*)%)$", "- %1")
			table.insert(points,
				tostring( mw.html.create( "div" )
					:css( "position", "absolute" )
					:css( "top", top .. "px" )
					:css( "left", left .. "px" )
					:css( "margin", "auto" )
					:css( "transform", "translate(-50%,-50%)" ) -- http://stackoverflow.com/questions/33683602/transform-origin-equivalent-for-position-absolute
					:css( "padding", "5px" )
					:css( "border-radius", "100%" )
					:css( "background-color", "#" .. colour )
					:css( "cursor", "help" )
					:css( "opacity", "0.8" )
					:attr( "title", loc_name .. " (" .. loc_info.group .. ")" )))
		end
		if greyed then
			greyed_count = greyed_count + d.count
		else
			table.insert(legend, 
				tostring( mw.html.create( "div" )
					:css( "display", "inline-block" )
					:css( "width", "10px" )
					:css( "height", "10px" )
					:css( "border-radius", "100%" )
					:css( "background-color", "#" .. colour )) .. 
				
				m_links.full_link({lang = lang,
					term = mw.ustring.gsub(d.term, "(.+)_[1-9]", "%1"),
					alt = mw.ustring.gsub(d.term, "(.+)_([1-9])", "%1<sub>%2</sub>")}) .. " (" .. d.count .. ")")
		end
		
		prev_count = d.count
	end
	
	if greyed_count > 0 then
		table.insert(legend, 
			tostring( mw.html.create( "div" )
				:css( "display", "inline-block" )
				:css( "width", "10px" )
				:css( "height", "10px" )
				:css( "border-radius", "100%" )
				:css( "background-color", "#CCCCBF" )) .. 
			
			"other terms (" .. greyed_count .. ")")
	end

	map = [=[
	{| class="wikitable mw-collapsible mw-collapsed" style="margin:0; text-align:center;"
	|-
	! style="background:#FCFFFC; width:40em" colspan=3 | Map of dialectal forms of <b><span class="Brah" lang="inc-ash">]=] ..
		word .. '</span></b> (“' .. syn_data["meaning"] .. '”) ' .. "\n|-\n|\n" .. map .. table.concat(points) .. '</div></div></div>' ..
		'<div style="column-count:' .. math.ceil(width/240) .. ';-moz-column-count:' .. math.ceil(width/240) .. ';-webkit-column-count:' .. math.ceil(width/240) .. ';font-size:smaller;line-height:1.7">' ..
		table.concat(legend, "<br>") .. "</div></div>" .. [=[
		
	|}]=]
		
	return map
end

return export