Документация
local getArgs = require('Module:Arguments').getArgs

local p = {}

local function startsWith(source, substring)
	if mw.ustring.len(substring) > mw.ustring.len(source) then
		return false
	end
	return mw.ustring.sub(source, 1, mw.ustring.len(substring)) == substring
end


local function formatUrlImpl(source, title, length)
	local scheme, host, path
	local postfix = ''
	local arg1, arg2 = source, title
	local isTestPage = mw.title.getCurrentTitle().prefixedText == 'Модуль:URL'
	
	-- Две квадратные скобки подряд — [[вики-ссылка]] вместо [ссылки] — возвращаем вход как есть.
	if string.find(arg1, "[[", 1, true) then
		local result = arg1
		if not isTestPage then
			result = result -- .. '[[Категория:Википедия:Статьи с вики-ссылкой, переданной в Модуль:URL]]'
			if arg2 then
				-- Если есть arg2, а мы распарсить ссылку не смогли, и значит заменить title не сможем корректно, это есть ошибка.
				result = result -- .. '[[Категория:Википедия:Статьи с ошибочной работой Модуль:URL]]'
			end
		end
		return result
	end
	
	-- Более одной квадратной скобки — скорее всего, задано более одного URL — тоже возвращаем как есть.
	if select(2, string.gsub(arg1, "%[", "")) > 1 then
		local result = arg1
		if not isTestPage then
			result = result -- .. '[[Категория:Википедия:Статьи со сложным входом в Модуль:URL]]'
			if arg2 then
				-- Если есть arg2, а мы распарсить ссылку не смогли, и значит заменить title не сможем корректно, это есть ошибка.
				result = result -- .. '[[Категория:Википедия:Статьи с ошибочной работой Модуль:URL]]'
			end
		end
		return result
	end
	
	source = mw.text.trim(source, "%[%] ")
	local titleDelimeterPosition = mw.ustring.find(source, " ", 1)
	if titleDelimeterPosition then
		if not title or title == "" then
			title = mw.ustring.sub(source, titleDelimeterPosition + 1)
			local postfixDelimeterPosition = mw.ustring.find(title, "%]", 1)
			if postfixDelimeterPosition then
				postfix = mw.ustring.sub(title, postfixDelimeterPosition + 1)
				title = mw.ustring.sub(title, 1, postfixDelimeterPosition - 1)
			end
		end
		source = mw.ustring.sub(source, 1, titleDelimeterPosition - 1)
	end
	
	local hostStartPosition
	local schemeDelimeterPosition = mw.ustring.find(source, "://", 1, true)
	if schemeDelimeterPosition then
		scheme = mw.ustring.sub(source, 1, schemeDelimeterPosition + 2)
		hostStartPosition = schemeDelimeterPosition + 3
	elseif mw.ustring.find(source, "^//", 1) then
		scheme = "//"
		hostStartPosition = 3
	elseif mw.ustring.find(source, "^mailto:", 1) then
		scheme = "mailto:"
		hostStartPosition = 8
	elseif mw.ustring.find(source, "@", 1) then
		scheme = "mailto:"
		source = scheme .. source
		hostStartPosition = 8
	else
		scheme = "http://"
		source = scheme .. source
		hostStartPosition = 8
	end

	if title then
		local finds = mw.ustring.find(arg1, "[", 1, true)
		if titleDelimeterPosition and finds and finds > titleDelimeterPosition + 1 then
			-- Если titleDelimeterPosition промазал мимо скобки и нашел пробел раньше неё, к примеру "a [b  c]",
			-- то свернуть всю нашу хиромантию и выдать первый аргумент без изменений.
			if arg2 == nil then
				return arg1 --.. (isTestPage and '' or '[[Категория:Википедия:Статьи со сложным входом в Модуль:URL]]')
			-- Если есть arg2, а мы распарсить ссылку не смогли, и значит заменить title не сможем корректно, это есть ошибка.
			-- С другой стороны, если arg2 нет, а arg1 очень сложный, то возможно это нормальный ход вещей,
			-- и на вход в модуль дана уже очень сильно оформленная ссылка.
			else
				return arg1 --.. (isTestPage and '' or '[[Категория:Википедия:Статьи с ошибочной работой Модуль:URL]]')
			end
		end
		return '[' .. source .. ' ' .. title .. ']' .. postfix
	end

	local hostDelimeterPosition = mw.ustring.find(source, "/", hostStartPosition, true)
	if hostDelimeterPosition then
		host = mw.ustring.sub(source, hostStartPosition, hostDelimeterPosition - 1)
		if hostDelimeterPosition == mw.ustring.len(source) then
			path = nil
		else
			path = mw.ustring.sub(source, hostDelimeterPosition + 1)
		end
	else
		host = mw.ustring.sub(source, hostStartPosition)
	end

	-- post-split format options
	if startsWith(host, 'www.') then
		host = mw.ustring.sub(host, 5)
	end
	host = mw.language.new('en'):lc(host)

	if path and path ~= '' and path ~= '/' then
		local title = host .. '/' .. path
		if length and #title > length then
			title = host .. '/' .. mw.ustring.sub(path, 1, length - #title - 2) .. '…'
		end
		return '[' .. source .. ' ' .. title .. ']' .. postfix
	else
		return '[' .. source .. ' ' .. host .. ']' .. postfix
	end
end


function p.formatUrlSingle(context, options, url)
	url = mw.text.trim(url)
	if url == '' then
		return nil
	end
	local title = nil
	if (options['text'] and options['text'] ~= '') then
		title = options['text']
	end
	local length = options['length'] and tonumber(options['length'])

	return formatUrlImpl(url, title, length)
end

function p.formatUrl(args)
	local url = args[1] or ''
	local title = args[2] or ''
	local length = args['length'] and tonumber(args['length'])

	url = mw.text.trim(url)
	title = mw.text.trim(title)

	if url == '' then
		return nil
	end
	if title == '' then
		title = nil
	end
	return formatUrlImpl(url, title, length)
end

function p.getLink(frame)
	local args = getArgs(frame)
	return p.formatUrl(args)
end

return p