Module:Fmtn

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 .. ''		end return res end res = prefix .. formatnum(mynum) .. suffix if needcheck and isarticle then res = res .. '' 	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