Module:Convert/show
This module can be used to prepare tables of wikitext to display simple documentation for specified units. Data is obtained by calling Module:Convert. In addition, the module can be used to show {{convert}} usage examples.
Listing links
See Module talk:Convert/show for a list of unique links for units. The list is shorter and easier to check than the full list of units.
Displaying unit information
The module contains a built-in list of commonly used units. The information at Help:Convert units#Units is the output from:
{{#invoke:convert/show|units}}
When no units are specified, the full built-in list of unit codes is used. In addition, the headings and examples defined in the module are displayed.
Units may be specified by entering section names or individual unit codes. No headings or examples are included if units are specified.
For example, one or more sections from the full list can be displayed as in the following examples:
{{#invoke:convert/show|units|length}}
{{#invoke:convert/show|units|length|mass|area}}
Any "input" unit codes can be specified individually, for example, the following line:
{{#invoke:convert/show|units|um|cm|ug|kg}}
gives the result:
Unit code | Unit symbol | Unit name | US name, if different |
---|---|---|---|
um | μm | micrometre | micrometer |
cm | cm | centimetre | centimeter |
ug | μg | microgram | |
kg | kg | kilogram |
Only units suitable for use as a conversion input can be used. For example, ftin
cannot be used as it is an output unit which displays the result in feet and inches.
Displaying usage examples
The module can display examples of {{convert}} usage in a list or a table. The required parameters must be separated with !
(exclamation mark) rather than the normal |
(pipe), and a parameter that includes an equals sign must be prefixed with 1=
(for the first parameter), or 2=
(for the second), etc.
For example, the following line:
{{#invoke:convert/show|list|1=123!cm!in!abbr=on|2=125!sqft!m2!abbr=off!sp=us}}
gives the result:
{{convert|123|cm|in|abbr=on}}
→ 123 cm (48 in){{convert|125|sqft|m2|abbr=off|sp=us}}
→ 125 square feet (11.6 square meters)
The same information can be displayed in a table.
{{#invoke:convert/show|table|1=123!cm!in!abbr=on|2=125!sqft!m2!abbr=off!sp=us}}
gives the result:
{{convert|123|cm|in|abbr=on}} |
→ | 123 cm (48 in) |
{{convert|125|sqft|m2|abbr=off|sp=us}} |
→ | 125 square feet (11.6 square meters) |
Substitution
Results from invoking the module can be substituted into the current page, for example:
{{subst:#invoke:convert/show|units|length}}
{{subst:#invoke:convert/show|table|1=123!cm!in!abbr=on|2=125!sqft!m2!abbr=off!sp=us}}
Substitution may be useful if editing of the resulting wikitext is required.
-- 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 Collection -- a table to hold items
Collection = {
add = function (self, item)
if item ~= nil then
self.n = self.n + 1
self[self.n] = item
end
end,
join = function (self, sep)
return table.concat(self, sep)
end,
remove = function (self, pos)
if self.n > 0 and (pos == nil or (0 < pos and pos <= self.n)) then
self.n = self.n - 1
return table.remove(self, pos)
end
end,
sort = function (self, comp)
table.sort(self, comp)
end,
new = function ()
return setmetatable({n = 0}, Collection)
end
}
Collection.__index = Collection
local function strip(text)
-- Return text with no leading/trailing whitespace.
return text:match("^%s*(.-)%s*$")
end
local function fakeFrame(selfArgs, parentArgs)
-- Simulate enough of a MediaWiki module frame for convert.
-- This is a cheap way to call convert with specified arguments.
return {
args = selfArgs,
parent = parentArgs and fakeFrame(parentArgs, nil),
getParent = function (self) return self.parent end,
}
end
local cvtFunction
local function callConvert(args)
if not cvtFunction then
cvtFunction = require('Module:Convert').convert
end
return cvtFunction(fakeFrame({}, args))
end
local function makeTable(frame, 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.new()
row:add(ucode)
local args = { '1', ucode, abbr = 'on', disp = 'unit' }
row:add(callConvert(args))
args.abbr = 'off'
local name1 = callConvert(args)
row:add(name1)
args.sp = 'us'
local name1_us = callConvert(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 commonUnits = {
["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",
},
["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 commonSections = {
"Area",
"Fuel efficiency",
"Length",
"Mass",
"Pressure",
"Speed",
"Temperature",
"Torque",
"Volume",
}
local function _showExamples(frame, results, examples, wantTable)
local fmt
if wantTable then
results:add('{|')
fmt = '|<code>%s</code>|| → ||%s'
else
fmt = '*<code>%s</code> → %s'
end
for i, item in ipairs(examples) do
if wantTable 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 wantTable then
results:add('|}')
end
end
local function _showLinks(frame, results, args)
local sandbox = args[1] == 'sandbox' and '/sandbox' or ''
local dataModule = 'Module:Convert/data' .. sandbox
local textModule = 'Module:Convert/text' .. sandbox
local dataCode = require(dataModule)
local textCode = require(textModule)
local uniqueLinks = {}
local links = Collection.new()
local function addLink(link)
if link and link ~= '' then
-- Some items (alias symlink, chainlk symbol) are already linked.
-- Therefore, add link syntax if not present, before testing for uniqueness.
-- There will be some duplicate targets such as [[Chain (unit)|chain]] + [[Chain (unit)|ch]].
if link:sub(1, 2) ~= '[[' then
link = '[[' .. link .. ']]'
end
if not uniqueLinks[link] then
uniqueLinks[link] = true
links:add(link)
end
end
end
for _, v in ipairs(textCode.customary_units) do
addLink(v.link)
end
for _, v in pairs(dataCode.all_units) do
-- This does not add anything for automatic per units (assuming they do not define a link).
-- That is ok because per unit x/y has link LINK(x)/LINK(y).
if v.symbol and v.symbol:sub(1, 2) == '[[' then
addLink(v.symbol)
end
if v.name1 and v.name1:sub(1, 2) == '[[' then
addLink(v.name1)
end
addLink(v.symlink)
addLink(v.link or v.name1 or (not v.per and not v.target) and v.symbol)
end
for _, v in pairs(dataCode.link_exceptions) do
addLink(v)
end
for _, v in pairs(dataCode.per_unit_fixups) do
if type(v) == 'table' then
addLink(v.link)
end
end
local function comp(a, b)
local la = a:lower(a)
local lb = b:lower(b)
if la == lb then
return a < b
end
return la < lb
end
links:sort(comp)
for _, v in ipairs(links) do
results:add('*' .. v)
end
end
local function _showUnits(frame, results, args)
local doFull
if args[1] == nil then
doFull = true
args = commonSections
end
local group = Collection.new()
for _, item in ipairs(args) do
local units = commonUnits[item] or commonUnits[item:sub(1, 1):upper() .. item:sub(2)]
if units then
if group.n > 0 then
makeTable(frame, results, group)
group = Collection.new()
end
if doFull then
if units.heading then
results:add('===' .. units.heading .. '===')
end
if units.examples then
results:add('Examples:')
_showExamples(frame, results, units.examples)
end
end
makeTable(frame, results, units)
else
group:add(item)
end
end
if group.n > 0 then
makeTable(frame, results, group)
end
end
local function showExamples(frame, wantTable)
local results = Collection.new()
local ok, msg = pcall(_showExamples, frame, results, frame.args, wantTable)
if ok then
return results:join('\n')
end
return '<strong class="error">Error</strong>\n' .. msg
end
local function showLinks(frame)
local results = Collection.new()
local ok, msg = pcall(_showLinks, frame, results, frame.args)
if ok then
return results:join('\n')
end
return '<strong class="error">Error</strong>\n' .. msg
end
local function showUnits(frame)
local results = Collection.new()
local ok, msg = pcall(_showUnits, frame, results, frame.args)
if ok then
return results:join('\n')
end
return '<strong class="error">Error</strong>\n' .. msg
end
return {
links = showLinks,
unit = showUnits,
units = showUnits,
['list'] = function (frame) return showExamples(frame, false) end,
['table'] = function (frame) return showExamples(frame, true) end,
}