Module:Number table sorting
Appearance
![]() | This Lua module is used on approximately 41,000 pages and changes may be widely noticed. Test changes in the module's /sandbox or /testcases subpages, or in your own module sandbox. Consider discussing changes on the talk page before implementing them. |
![]() | This module depends on the following other modules: |
Implements {{Number table sorting}}
local lang = mw.language.getContentLanguage()
-- constants
local INF = tonumber('inf')
local NEGINF = tonumber('-inf')
--------------------------------------------------------------------------------
-- Nts class
--------------------------------------------------------------------------------
local Nts = {}
Nts.__index = Nts
Nts.formats = {
formatted = true,
no = true,
yes = true,
hide = true
}
function Nts.new(args)
local self = setmetatable({}, Nts)
self:parseNumber(args[1])
-- Set the format string
if args.format then
self.format = args.format
else
self.format = 'formatted'
end
if not Nts.formats[self.format] then
error(string.format(
"'%s' is not a valid format",
tostring(self.format)
), 0)
end
-- To display some text before the display version of the number
-- {{nts|123456789.00123|prefix=approx. }} → approx. 123,456,789.00123
self.prefix = args.prefix or ''
-- debug info
self.debug = args.debug or ''
return self
end
-- Parse the entered number
function Nts:parseNumber(s)
-- sanitize
s = s or '';
s = mw.ustring.gsub(s,'−','-')
s = mw.ustring.gsub(s, '−', '-')
self.rawNumberString = s
-- fractions. was somewhat but completely broken at some point
self.isFraction = (string.find(2, '/') ~= nil)
-- format detection
self.isScientificNotation = (string.find(2, 'e') ~= nil)
-- parse with language options
self.number = lang:parseFormattedNumber(s)
-- parse with fallback
if not self.number then
self.number = tonumber(s)
end
if not self.number then
error(string.format(
"'%s' is not a valid number",
tostring(s)
), 0)
end
if self.number ~= INF and self.number ~= NEGINF then
self.magnitude = math.floor(math.log10(math.abs(self.number)))
self.significand = self.number / 10^self.magnitude
mw.log( 'sig: ' .. self.significand)
end
end
function Nts:makeDisplay()
local ret ={}
if self.format == 'hide' then
return ''
end
ret[#ret + 1] = self.prefix
if self.format == 'formatted' then
ret[#ret + 1] = lang:formatNum(self.number)
return table.concat(ret)
end
local sciNotation = tonumber(self.number .. 400)
if sciNotation == 0 or sciNotation == INF or sciNotation == NEGINF then
ret[#ret + 1] = self.number * 10^-self.magnitude
ret[#ret + 1] = '<span style="margin-left:0.2em">×<span style="margin-left:0.1em">10</span></span><s style="display:none">^</s><sup>'
if self.magnitude<0 then
ret[#ret + 1] = '−' .. (-self.magnitude)
else
ret[#ret + 1] = self.magnitude
end
ret[#ret + 1] = '</sup>'
else
ret[#ret + 1] = self.rawNumberString
end
return table.concat(ret)
end
function Nts:makeSortKey()
if self.number == 0 then
return '5000000000000000000♠'
elseif self.number == tonumber('inf') then
return '9000000000000000000♠'
elseif self.number == tonumber('-inf') then
return '1000000000000000000♠'
end
if self.number > 0 then
return tostring(7000 + self.magnitude)
.. string.format('%05d', (math.floor(self.number * 10^(4-self.magnitude) ) % 1e5))
.. string.format('%05d', (math.floor(self.number * 10^(9-self.magnitude) ) % 1e5))
.. string.format('%05d', (math.floor(self.number * 10^(14-self.magnitude) ) % 1e5))
.. '♠'
else
return tostring(2999 - self.magnitude)
.. string.format('%05d', math.floor((self.number + 10*10^self.magnitude) * 10^(4-self.magnitude)) %1e5)
.. string.format('%05d', math.floor((self.number + 10*10^self.magnitude) * 10^(9-self.magnitude)) %1e5)
.. string.format('%05d', math.floor((self.number + 10*10^self.magnitude) * 10^(14-self.magnitude)) %1e5)
.. '♠'
end
end
function Nts:renderTrackingCategories()
if self.hasDeprecatedParameters then
return '[[Category:Nts templates with deprecated parameters]]'
else
return ''
end
end
function Nts:__tostring()
local root = mw.html.create()
local span = root:tag('span')
:attr('data-sort-value', self:makeSortKey())
-- Display
if self.format ~= 'hide' then
if self.debug == 'yes' then
span:tag('span')
:css('border', '1px solid')
:wikitext(self:makeSortKey())
end
span:wikitext(self:makeDisplay())
else
-- tidy removes empty spans. Keep nbsp content till remexhtml is deployed
span:css('display', 'none')
:wikitext(' ')
end
-- Tracking categories
root:wikitext(self:renderTrackingCategories())
return tostring(root)
end
--------------------------------------------------------------------------------
-- Exports
--------------------------------------------------------------------------------
local p = {}
function p._exportClasses()
return {
Nts = Nts
}
end
function p._main(args)
local success, ret = pcall(function ()
local nts = Nts.new(args)
return tostring(nts)
end)
if success then
return ret
else
ret = string.format(
'<strong class="error">Error in [[Template:Nts]]: %s</strong>',
ret
)
if mw.title.getCurrentTitle().namespace == 0 then
-- Only categorise in the main namespace
ret = ret .. '[[Category:Nts templates with errors]]'
end
return ret
end
end
function p.main(frame)
local args = require('Module:Arguments').getArgs(frame, {
wrappers = { 'Template:Number table sorting', 'Template:Ntsh' },
})
return p._main(args)
end
return p