Module:Fmtn

Jump to navigation Jump to search

This module implements {{Fmtn}}.

Dependencies[edit source]

[view] [edit] [history] [refresh]The above documentation is transcluded from Module:Fmtn/doc.
local p = {}

-- Known building patterns, with a transformation to become
-- a valid standard.
-- The pattern does not have to be perfect because it is validated as a number
-- after processing. So no problem if he can eventually
-- produce invalid numbers. Just take care that you do not
-- produce incorrect numbers.
-- Note: Many REGEXes are not valid on Lua.
-- See the documentation at:
-- https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Patterns
local known_patterns = {
    {   "^[%d,]*%.%d*$",     -- format 1,123,123.123
        false,                 -- does not require revision
        {
        	{ ",", "" },           -- remove commas
        }
    },
    {   "^[%d.]*,%d*$",      -- format 1.123.123,123 or 1123123,123
        false,                 -- does not require revision
        {
        	{ "%.", "" },          -- remove dots
        	{ ",", "."},           -- replace comma by dot
        }
    },
    {	"^[%d%s]*[,.]%d*$",  -- format 1 123 123,123 or 1 123 123.123
        false,                 -- do not mark for review
        {
        	{ "%s", "" },          -- remove spaces
        	{ ",", "."},           -- replace comma by dot, if there are
        }
    },
    {   "^[%d,]*,%d%d%d$",   -- format 1,123,123
        false,                 -- do not mark for review
        {
        	{ ",", "" },           -- remove commas
        }
    },
	{   "^[%d.]*%.%d%d%d$",   -- format 1.123.123 (three digits in the last block)
        false,                  -- do not mark for review
        {
        	{ ",", "" },            -- remove dots
        }
    },
    {   "^[%d,]*,%d%d%d$",   -- format 1,123,123 (three digits in the last block)
        false,                 -- do not mark for review
        {
        	{ ",", "" },           -- remove commas
        }
    },
	{   "^[%d%s]*%s%d%d%d$", -- format 1 123 123 (three digits in the last block)
        false,                -- do not mark for review
        {
        	{ "%s", "" },         -- remove spaces
        }
    },
    {   "^[%d.]*%.%d%d$",   -- format 1.123.12 (two digits in the last block)
        true,                 -- mark for review
        {
        	{ ".", "" },          -- remove dots
        	{ "(%d%d)$", ".%1" }, -- insert a period before the last two digits
        }
    },
    {   "^[%d,]*,%d%d$",    -- format 1,123,12 (two digits in the last block)
        true,                 -- mark for review
        {
        	{ ",", "" },          -- remove commas
        	{ "(%d%d)$", ".%1" }, -- insert a period before the last two digits
        }
    },
    {   "^[%d%s]%s%d%d$",    -- format 1 123 12 (two digits in the last block)
        true,                 -- mark for review
        {
        	{ "%s", "" },          -- remove spaces
        	{ "(%d%d)$", ".%1" }, -- insert a period before the last two digits
        }
    },
}

function p.fmtn(frame)
	local param1 = frame.args[1] or ""
	local param2 = frame.args[2] or ""
	local param3 = frame.args[3] or ""
	
	num1, isnumber1, needcheck1 = recognize_number(param1)
	num2, isnumber2, needcheck2 = recognize_number(param2)
	num3, isnumber3, needcheck3 = recognize_number(param3)
	
	isarticle = mw.title.getCurrentTitle().namespace == 0
	
	prefix = ''
	suffix = ''
	if isnumber1 and not isnumber2 and not isnumber3 then
		-- only the first number is valid
		mynum = num1
		needcheck = needcheck1
		if param2 ~= '' then suffix = suffix .. ' ' .. param2 end
		if param3 ~= '' then suffix = suffix .. ' ' .. param3 end
	elseif not isnumber1 and isnumber2 and not isnumber3 then
		-- only the second number is valid
		mynum = num2
		needcheck = needcheck2
		if param1 ~= '' then prefix = prefix .. param1 .. ' ' end
		if param3 ~= '' then suffix = suffix .. ' ' .. param3 end
	elseif not isnumber1 and not isnumber2 and isnumber3 then
		-- only the third number is valid
		mynum = num3
		needcheck = needcheck3
		if param1 ~= '' then prefix = prefix .. param1 .. ' ' end
		if param2 ~= '' then prefix = prefix .. param2 .. ' ' end
	else
		-- ERROR: There are more than two valid numbers, or none are valid
		-- In this case, do what was already done before, try to format
		-- what is possible and returns the parameters in the order they were
		-- presented
		
		-- Here the "callParserFunction" is used to copy the behavior that has already
		-- been seen before this module existed and to prevent errors from being
		-- printed
		res = ''
		if param1 ~= '' then
			res = res .. formatnum(param1)
		end
		if param2 ~= '' then
			if res ~= '' then res = res .. ' ' end
			res = res .. formatnum(param2)
		end
		if param3 ~= '' then
			if res ~= '' then res = res .. ' ' end
			res = res .. formatnum(param3)
		end
		if isarticle then
			res = res .. '[[Category:Pages with error using the default Fmtn]]'
		end
		return res
	end
	
  	res = prefix .. formatnum(mynum) .. suffix
  	if needcheck and isarticle then
  		res = res .. '[[Category:Pages whose use of the default Fmtn should be reviewed]]'
  	end
  	return res
end

function formatnum(num)
	frame = mw.getCurrentFrame()
	return frame:callParserFunction{ name = 'formatnum', args = { num } }
	
	-- Not used because it does not preserve the number of digits after the decimal point
	-- lang = mw.language.getContentLanguage()
	-- return lang:formatNum(mynum)
end

function recognize_number(num)
	if tonumber(num) then
		-- it's already a valid number, you do not have to do anything
		isnumber = true
		needcheck = false
	else
		isnumber = false
		needcheck = true
		-- is not a valid number, look at the patterns to see
		-- if it can be converted to a valid standard
		for _, rule in pairs(known_patterns) do
			checkpattern = rule[1]
			if string.find(num, checkpattern) then
				newneedcheck = rule[2]
				substitutions = rule[3]
				
				newstr = num
				for _, subs in pairs(substitutions) do
					-- apply substitution in string
					newstr = string.gsub(newstr, subs[1], subs[2])
				end
				
				if tonumber(newstr) then
					-- verifies that the transformation produced a valid number
					-- If so, close the loop
					num = newstr
					isnumber = true
					needcheck = newneedcheck
					break
				end
			end
		end
		-- if no pattern hit then it should be invalid
		-- code returns the same last number and lets
		-- the caller does its job
	end
	return num, isnumber, needcheck
end

return p