-- Prepare tables of wikitext to display simple documentation about
-- specified units. Data is obtained by calling Module:Convert.
-- Also provides a function to show convert usage examples.
local function collection()
-- Return a table to hold items.
return {
n = 0,
add = function (self, item)
self.n = self.n + 1
self[self.n] = item
end,
join = function (self, sep)
return table.concat(self, sep)
end,
}
end
local function strip(text)
-- Return text with no leading/trailing whitespace.
return text:match("^%s*(.-)%s*$")
end
local function frame(self_args, parent_args)
-- Simulate enough of a MediaWiki module frame for convert.
return {
args = self_args,
parent = parent_args and frame(parent_args, nil),
getParent = function (self) return self.parent end,
}
end
local cvt_function
local function call_convert(args)
if not cvt_function then
-- A testing program can set the global variable 'is_test_run'.
cvt_function = require(is_test_run and 'convert' or 'Module:Convert').convert
end
return cvt_function(frame({}, args))
end
local function maketable(results, units)
results:add('{| class="wikitable"')
results:add('! Unit code !! Unit symbol !! Unit name !! US name, if different')
for i, ucode in ipairs(units) do
local row = collection()
row:add(ucode)
local args = { '1', ucode, abbr = 'on', disp = 'unit' }
row:add(call_convert(args))
args.abbr = 'off'
local name1 = call_convert(args)
row:add(name1)
args.sp = 'us'
local name1_us = call_convert(args)
if name1_us == name1 then
row:add('')
else
row:add(name1_us)
end
results:add('|-')
results:add(strip('| ' .. row:join(' || ')))
end
results:add('|}')
results:add('')
end
-- Commonly used units for main documentation.
-- Can only be input units (not combinations or multiples).
local common_units = {
["Area"] = {
heading = "Area",
examples = { "1.5|sqmi|km2", "1.5|sqmi|km2|abbr=off", "1.5|sqmi|km2|abbr=on" },
"acre",
"ha",
"m2",
"cm2",
"km2",
"sqin",
"sqft",
"sqyd",
"sqmi",
"cda",
},
["Fuel efficiency"] = {
heading = "Fuel efficiency",
examples = { "12|mpgus|km/L", "12|mpgus|km/L|abbr=off", "12|mpgus|km/L|abbr=off|sp=us", "12|mpgus|km/L|abbr=on" },
"km/L",
"mpgimp",
"mpgus",
"L/km",
"L/100 km",
},
["Length"] = {
heading = "Length",
examples = { "123|cm|in", "123|cm|in|abbr=off|sp=us", "123|cm|in|abbr=on" },
"uin",
"in",
"ft",
"yd",
"mi",
"nmi",
"m",
"cm",
"mm",
"km",
"angstrom",
},
["Mass"] = {
heading = "Mass",
examples = { "72.3|kg|lb", "72.3|kg|lb|abbr=off", "72.3|kg|lb|abbr=on" },
"g",
"kg",
"oz",
"lb",
"st",
"LT",
"MT",
"ST",
},
["Pressure"] = {
heading = "Pressure",
examples = { "28|psi|Pa", "28|psi|Pa|abbr=off", "28|psi|Pa|abbr=on" },
"atm",
"mbar",
"psi",
"Pa",
},
["Speed"] = {
heading = "Speed",
examples = { "60|mph|km/h", "60|mph|km/h|abbr=off", "60|mph|km/h|abbr=on" },
"km/h",
"km/s",
"kn",
"mph",
},
["Temperature"] = {
heading = "Temperature",
examples = { "100|C|F", "100|C|F|abbr=off", "100|C-change|F-change", "100|C-change|F-change|abbr=out" },
"C",
"F",
"K",
"C-change",
"F-change",
"K-change",
},
["Torque"] = {
heading = "Torque",
examples = { "12.5|Nm|lb.in", "12.5|Nm|lb.in|abbr=off", "12.5|Nm|lb.in|abbr=on|lk=on" },
"lb.in",
"lb.ft",
"Nm",
},
["Volume"] = {
heading = "Volume",
examples = { "125|cuin|l", "125|cuin|l|abbr=off", "125|cuin|l|abbr=on" },
"cuin",
"cuft",
"cuyd",
"cumi",
"impgal",
"impoz",
"usgal",
"usoz",
"L",
"l",
"m3",
"cc",
"mm3",
},
}
-- Order in which sections are wanted when doing all common units.
local common_sections = {
"Area",
"Fuel efficiency",
"Length",
"Mass",
"Pressure",
"Speed",
"Temperature",
"Torque",
"Volume",
}
local function _show_examples(frame, results, examples, want_table)
local fmt
if want_table then
results:add('{|')
fmt = '|<code>%s</code>|| → ||%s'
else
fmt = '*<code>%s</code> → %s'
end
for i, item in ipairs(examples) do
if want_table and i > 1 then
results:add('|-')
end
item = item:gsub('!', '|')
item = '{{convert' .. (item:sub(1, 1) == '|' and '' or '|') .. item .. '}}'
results:add(fmt:format(mw.text.nowiki(item), frame:preprocess(item)))
end
if want_table then
results:add('|}')
end
end
local function _show_units(frame, results, args)
local do_full
if args[1] == nil then
do_full = true
args = common_sections
end
local group = collection()
for _, item in ipairs(args) do
local units = common_units[item] or common_units[item:sub(1, 1):upper() .. item:sub(2)]
if units then
if group.n > 0 then
maketable(results, group)
group = collection()
end
if do_full then
if units.heading then
results:add('===' .. units.heading .. '===')
end
if units.examples then
results:add('Examples:')
_show_examples(frame, results, units.examples)
end
end
maketable(results, units)
else
group:add(item)
end
end
if group.n > 0 then
maketable(results, group)
end
end
local function show_examples(frame, want_table)
local results = collection()
local ok, msg = pcall(_show_examples, frame, results, frame.args, want_table)
if ok then
return results:join('\n')
end
return '<strong class="error">Error</strong>\n' .. msg
end
local function show_units(frame)
local results = collection()
local ok, msg = pcall(_show_units, frame, results, frame.args)
if ok then
return results:join('\n')
end
return '<strong class="error">Error</strong>\n' .. msg
end
return {
unit = show_units,
units = show_units,
['list'] = function (frame) return show_examples(frame, false) end,
['table'] = function (frame) return show_examples(frame, true) end,
}