Dokumentasjon for denne modulen kan opprettes på Modul:grammar-link/dok

local lk = require("Modul:link")
local lang = require("Modul:lang")

local export = {}

local function link(str, link_type, lang_code, pos_code, format)
	local new_str = ""
	local new_tbl = {}
	
	local magic_characters_set  = "[%^%$%(%)%%%.%[%]%*%+%-%?]";
	local is_standalone         = not not pos_code and pos_code ~= ""
	local should_include_anchor = not not lang_code and lang_code ~= ""

	local function trimLeft(s)
		return mw.ustring.gsub(s, "^%s*", "")
	end
	
	local function escapeMagicCharacters(s)
		return string.gsub(s, magic_characters_set, "%%%1")
	end
	
	local function addSpanTagsForEachLink(s)
		for link_str in mw.ustring.gmatch(s, "%[%[[^%[%]]*%]%]") do
			local link_str_with_span_tag = '<span class="' .. link_type .. '">' .. link_str .. '</span>'
			local escaped_link_str = escapeMagicCharacters(link_str)
			s = mw.ustring.gsub(s, escaped_link_str, link_str_with_span_tag)
		end
		
		return s
	end
	
	local function isSpecialCase(s)
		return not not (s == "&nbsp;" or s == "–" or s == "?")
	end
	
	local function maybeLink(s)
		local contains_no_space        = not mw.ustring.find(s, " ")
		local first_1                  = mw.ustring.sub(s, 1, 1)
		local last_1                   = mw.ustring.sub(s, -1, -1)
		local is_special_case_maybe    = last_1 == "?" and s ~= "?"
		local is_special_case_slightly = first_1 == "(" and last_1 == ")"
		local should_try_to_add_link   = link_type ~= "no-link" and contains_no_space
		local should_add_spans         = link_type ~= "link-only" and not isSpecialCase(s) and format ~= "export"
		
		if is_special_case_maybe then
			local word = mw.ustring.sub(s, 1, -2)
			s = word
		elseif is_special_case_slightly then
			local word = mw.ustring.sub(s, 2, -2)
			s = word
		end

		if should_try_to_add_link and not is_special_case_maybe then
			if should_include_anchor then
				s = lk.link(s, lang_code)
			else
				s = lk.link(s)
			end
		end

		if should_add_spans then
			s = addSpanTagsForEachLink(s)
		end

		s = s == "-" and "–" or s

		if format == "export" then
			s = mw.ustring.gsub(s, "[^%[]*%[%[", "")
			s = mw.ustring.gsub(s, "%]%].*", "")
			s = mw.ustring.gsub(s, "[^%|]+%|", "")
		end

		if is_special_case_maybe then
			if format == "export" then
				s = s .. "?"
			else
				s = "'''('''" .. s .. "''')?'''"
			end
		elseif is_special_case_slightly then
			if format == "export" then
				s = "(" .. s .. ")"
			else
				s = "'''('''" .. s .. "''')'''"
			end
		end

		if format == "export" then
			if link_type == "no-link" or link_type == "link-only" or isSpecialCase(s) or not lk.isValidLinkTarget(s) then
				s = ""
			end
		end
		return s
	end
	
	for word_str in mw.ustring.gmatch(str, '([^,]+)') do
		word_str = trimLeft(word_str)

		word_str = maybeLink(word_str)

		if format == "export" and word_str ~= "" then
			table.insert(new_tbl, word_str)
		else
			new_str = new_str .. (new_str == "" and "" or ", ") .. word_str
		end
	end

	new_str = new_str == "" and "&nbsp;" or new_str
	
	if is_standalone then
		new_str = '<span class="grammar-inline" data-lang="' .. lang_code .. '" data-h3="' .. pos_code .. '">' .. new_str .. '</span>'
	end
	
	if format == "export" then
		return new_tbl
	else
		return new_str
	end
end

function export.link(arg, link_type, lang_code, pos_code)
	local str

	if arg == mw.getCurrentFrame() then
		local frame = arg
		str         = frame.args[1] or ""
		link_type   = frame.args[2]
		lang_code   = frame.args[3]
		pos_code    = frame.args[4]
	else
		str         = arg or ""
	end

	return link(str, link_type, lang_code, pos_code, "wikitable")
end

function export.linkExport(arg, link_type)
	local str

	if arg == mw.getCurrentFrame() then
		local frame = arg
		str         = frame.args[1] or ""
		link_type   = frame.args[2]
	else
		str         = arg or ""
	end

	return link(str, link_type, nil, nil, "export")
end

return export