Документация
-- This module implements {{Roman}}.

local p = {}

-- This function implements the {{overline}} template.
local function overline( s )
	return mw.ustring.format( '<span style="text-decoration:overline;">%s</span>', s )
end

-- Gets the Roman numerals for a given numeral table. Returns both the string of
-- numerals and the value of the number after it is finished being processed.
local function getLetters( num, t )
	local ret = {}
	for _, v in ipairs( t ) do
		local val, letter = unpack( v )
		while num >= val do
			num = num - val
			table.insert( ret, letter )
		end
	end
	return table.concat( ret ), num
end

-- The main control flow of the module.
function p.convert( arg1, arg2 )
	-- Get input and exit displaying nothing if the input is bad.
	local num = tonumber( arg1 )
	if not num or num < 1 or num == math.huge then
		return
	end
	num = math.floor( num )

	-- Return a message for numbers too big to be expressed in Roman numerals.
	if num >= 5000000 then
		return arg2 or 'N/A'
	end

	local ret = ''
	-- Find the Roman numerals for the large part of numbers 5000 and bigger.
	-- The if statement is not strictly necessary, but makes the algorithm 
	-- more efficient for smaller numbers.
	if num >= 5000 then
		local bigRomans = {
			{ 1000000, 'M' },
			{ 900000, 'CM' }, { 500000, 'D' }, { 400000, 'CD' }, { 100000, 'C' },
			{ 90000, 'XC' }, { 50000, 'L' }, { 40000, 'XL' }, { 10000, 'X' },
			{ 5000, 'V' }
		}
		local bigLetters
		bigLetters, num = getLetters( num, bigRomans )
		ret = overline( bigLetters )
	end

	-- Find the Roman numerals for numbers 4999 or less.
	local smallRomans = {
		{1000, "M"},
		{900, "CM"}, {500, "D"}, {400, "CD"}, {100, "C"},
		{90, "XC"}, {50, "L"}, {40, "XL"}, {10, "X"},
		{9, "IX"}, {5, "V"}, {4, "IV"}, {1, "I"} 
	}
	local smallLetters = getLetters( num, smallRomans )
	ret = ret .. smallLetters

	return ret
end

local roman_table = {
	I = 1,
	V = 5,
	X = 10,
	L = 50,
	C = 100,
	D = 500,
	M = 1000
}

function p._roman_to_int(r)
	local ret = 0
	local i = 1
	local n = mw.ustring.len(r)
	local d = r:sub(i, i)
	local rd = roman_table[d] or 0
	local rd_next
	while i < n do
		local d_next = r:sub(i+1, i+1)
		rd_next = roman_table[d_next]
		if rd and rd_next then
			if rd < rd_next then
				ret = ret - rd
			else
				ret = ret + rd
			end
			rd = rd_next
		else
			return 0 --встретившийся символ не является римской цифрой
		end
		i = i +1
	end
	return ret + rd
end

function p.roman_to_int(frame)
	if not getArgs then
		getArgs = require('Module:Arguments').getArgs
	end
	local args = getArgs(frame)
	return p._roman_to_int(args[1])
end

function p.main( frame )
	-- If called via #invoke, use the args passed into the invoking
	-- template, or the args passed to #invoke if any exist. Otherwise
	-- assume args are being passed directly in from the debug console
	-- or from another Lua module.
	local origArgs
	if frame == mw.getCurrentFrame() then
		origArgs = frame:getParent().args
		for k, v in pairs( frame.args ) do
			origArgs = frame.args
			break
		end
	else
		origArgs = frame
	end
	-- Trim whitespace and remove blank arguments.
	local args = {}
	for k, v in pairs( origArgs ) do
		if type( v ) == 'string' then
			v = mw.text.trim( v )
		end
		if v ~= '' then
			args[k] = v
		end
	end
	return p.convert( args[ 1 ] , args[ 2 ] )
end

return p