Jump to content

Module:Convert/helper

Fi Wikipedia

Documentation for this module may be created at Module:Convert/helper/doc

-- This module provides some functions to prepare template parameters
-- for use with Template:Convert.
-- This module is not used by Template:Convert or Module:Convert.

local function stripToNil(text)
	-- If text is a non-empty string, return its trimmed content,
	-- otherwise return nothing (empty string or not a string).
	if type(text) == 'string' then
		return text:match('(%S.-)%s*$')
	end
end

-- Remove commas and references (any strip markers) from a number.
-- First usage in Template:Infobox_UK_place/dist (June 2018)
local function cleanNumber(frame)
	local args = frame.args
	local text = stripToNil(args[1]) or ''
	if text == '' or tonumber(text) then
		return text
	end
	return mw.text.killMarkers(text):gsub(',', '')
end

local fractions = {
	['½'] = '1/2',
	['⅓'] = '1/3',
	['⅔'] = '2/3',
	['¼'] = '1/4',
	['¾'] = '3/4',
	['⅛'] = '1/8',
	['⅜'] = '3/8',
	['⅝'] = '5/8',
	['⅞'] = '7/8',
}

local fractionNumbers = {
	['½'] = 1/2,
	['⅓'] = 1/3,
	['⅔'] = 2/3,
	['¼'] = 1/4,
	['¾'] = 3/4,
	['⅛'] = 1/8,
	['⅜'] = 3/8,
	['⅝'] = 5/8,
	['⅞'] = 7/8,
}

-- Format regular input with fraction (MOS-confirmant) into Convert-format "12+3/8" ("+" added).
-- First usage in Template:NFL_predraft (August 2017)
local function number(frame)
	--[[ Preprocess a template parameter to translate a number to be used as
	input for {{convert}}.
	{{#invoke:convert/helper|number|12 3/8}} → 12+3/8
		Input				Output
		12					12
		12 3/8				12+3/8
		{{frac|12|3|8}}		12+3/8
		12{{frac|3|8}}		12+3/8
		12⅜					12+3/8
	Template:Fraction redirects to Template:Frac so either may be used in the input.
	]]
	local args = frame.args
	local text = stripToNil(args[1]) or ''
	if text == '' or tonumber(text) then
		return text  -- examples: '', '12', '12.3', '12.3e4', or negative
	end
	text = text:gsub(' ', ' '):gsub('  +', ' '):gsub(' *%+ *', '+'):gsub('⁄', '/'):gsub('⁄', '/')
	local integer, numerator, denominator, rest
	-- Look for a fraction of form '12 3/8' or '12+3/8' or '3/8'.
	integer, numerator, denominator = text:match('^(%d+)[ +](%d+)/(%d+)$')
	if integer then
		return integer .. '+' .. numerator .. '/' .. denominator
	end
	numerator, denominator = text:match('^(%d+)/(%d+)$')
	if numerator then
		return numerator .. '/' .. denominator
	end
	-- Look for an expanded fraction such as the result of {{frac|12|3|8}} or 12{{frac|3|8}} or {{frac|3|8}}.
	numerator, denominator = text:match('<sup>(%d+)</sup>/<sub>(%d+)</sub></span>')
	if numerator then
		integer = text:match('(%d+)<span class="sr-only">') or
			text:match('^(%d+)%s*&#x200B;<span') or  -- Template:Frac outputs zwsp since December 2017
			text:match('^(%d+)%s*<span')
		return (integer and (integer .. '+') or '') .. numerator .. '/' .. denominator
	end
	-- Look for a fraction of form '12¾' or '¾'.
	integer, rest = text:match('^(%d*)%s*(.*)')
	local expand = fractions[rest]
	if expand then
		return (integer == '' and integer or (integer .. '+')) .. expand
	end
	return text
end

local function distanceNumber(text)
	-- Return a number corresponding to text (0 if text is empty) or throw an error if invalid.
	text = text or 0
	if tonumber(text) then
		return tonumber(text)
	end
	-- Look for a fraction of form '12¾' or '¾'.
	local integer, expand = text:match('^(%d*)%s*(.*)')
	if integer == '' then
		integer = 0
	else
		integer = tonumber(integer)
	end
	if expand == '' then
		expand = 0
	else
		expand = fractionNumbers[expand]
	end
	if integer and expand then
		return integer + expand
	end
	error('Invalid number "' .. text .. '"', 0)
end

-- First usage in Template:Horse_race_distance (January 2024)
local function horseRaceDistance(frame)
	local args = frame:getParent().args
	local miles = stripToNil(args[1])
	local furlongs = stripToNil(args[2])
	local yards = stripToNil(args[3])
	local show = {}
	if miles then
		table.insert(show, miles .. 'm')
	end
	if furlongs then
		table.insert(show, furlongs .. 'f')
	end
	if yards then
		table.insert(show, yards .. 'y')
	end
	miles = distanceNumber(miles)
	furlongs = distanceNumber(furlongs)
	yards = distanceNumber(yards)
	local meters = miles * 1609.344 + furlongs * 201.168 + yards * 0.9144
	return
		'<span data-sort-value="' ..
		tostring(meters) ..
		'&nbsp;!">' ..
		table.concat(show, ' ') ..
		'</span>'
end

return {
	number = number,
	cleanNumber = cleanNumber,
	horseRaceDistance = horseRaceDistance,
}