-- This module implements the {{Track gauge}} template.
-- Data is in Module:Track gauge/data
local p = {}
local gaugeDataAll = nil
local dataPageName = 'Module:Track gauge/data/sandbox' -- set /data/sandbox here to test data/sandbox
-----------------------------------------------------------------------------------
-- prepareArgs -- Normalise Arguments coming from an #invoke or from a module
-----------------------------------------------------------------------------------
local function prepareArgs(frame)
local origArgs
if frame == mw.getCurrentFrame() then
origArgs = frame:getParent().args
for k, v in pairs(frame.args) do
origArgs = frame.args
break
end
else
origArgs = frame
end
local args = {}
-- searchAlias is the cleaned value of args[1]. args[1] is kept as rawInput for error message
local searchAlias = ''
local rawDisp
for k, v in pairs(origArgs) do
if tonumber(k) == nil then -- Named argment
if k == 'disp' then
rawDisp = v -- Keep raw disp input to pass through plain (wiki)text
args[k] = mw.ustring.lower(v)
elseif k == 'first' then
v = mw.ustring.lower(v)
if v == 'met' or v == 'metric' then
v = 'met'
elseif v == 'imp' or v == 'imperial' then
v = 'imp'
else k = 'trashparam_first' end
args[k] = v
elseif k == 'nowrap' or k == 'wrap' then -- wrap=y deprecated; reading: nowrap=off
v = mw.ustring.lower(v)
if v == '' or v == 'off' or v == 'on' or v == 'all' then
elseif v == 'inline' or (k == 'wrap' and v == 'y') then
v = 'off'
else v = '' end
args['nowrap'] = v
else
args[k] = mw.ustring.lower(v)
end
else
args[k] = v -- Keep rawInput in [1] for error message
if k == 1 then
-- Unnamed argument, the alias to be searched
-- Cleanup
searchAlias = p.normaliseAliasInput(v)
end
end
end
args['searchAlias'] = searchAlias
if rawDisp then args['rawDisp'] = rawDisp end
return args
end
-----------------------------------------------------------------------------------
-- normaliseAliasInput
-----------------------------------------------------------------------------------
function p.normaliseAliasInput(aliasIn)
local a
a = mw.ustring.lower(mw.ustring.gsub(aliasIn, '[%s%,]', ''))
a = mw.ustring.gsub(a, ' ', '')
a = mw.ustring.gsub(a, 'gauge$', '')
a = mw.ustring.gsub(a, "'", "ft")
a = mw.ustring.gsub(a, '"', 'in')
a = mw.ustring.gsub(a, '⁄', '/')
a = mw.ustring.gsub(a, '⁄', '/')
return a
end
-----------------------------------------------------------------------------------
-- debugReturnArgs -- Debug function.
-----------------------------------------------------------------------------------
function p.debugReturnArgs(frame)
local args = prepareArgs(frame)
local retArgs = {}
for k, a in pairs(args) do
table.insert(retArgs, k .. '=' .. a)
end
return 'Args: ' .. table.concat(retArgs, '; ')
end
-----------------------------------------------------------------------------------
-- getTrackGaugeEntry -- Find entry data for a single gauge (alias)
-----------------------------------------------------------------------------------
function p.getTrackGaugeEntry(searchAlias)
gaugeDataAll = mw.loadData(dataPageName)
if searchAlias == '' then
return nil
end
local tgEntry = nil
for i, tgEntry in ipairs(gaugeDataAll) do
for j, alias in ipairs(tgEntry.aliases) do
if alias == searchAlias then
return tgEntry
end
end
end
end
-----------------------------------------------------------------------------------
-- noWrap -- Add span tags to prevent a string from wrapping.
-----------------------------------------------------------------------------------
local function noWrap(s)
return mw.ustring.format('<span class="nowrap">%s</span>', s)
end
-----------------------------------------------------------------------------------
-- frac -- A slimmed-down version of the {{frac}} template (a nowrap is to be added with the unit)
-----------------------------------------------------------------------------------
local function frac(whole, num, den)
-- normally would do the TemplateStyles expansion here, but instead we do
-- it at the callsite because of [[:phab:T200704]]
return mw.ustring.format(
'<span class="frac" role="math">%s<span class="num">%s</span>⁄<span class="den">%s</span></span>',
whole and (whole .. '<span class="sr-only">+</span>') or '',
num,
den
)
end
-----------------------------------------------------------------------------------
-- catMentions -- Wikicode for "article mentions gauge" categories
-----------------------------------------------------------------------------------
function p.catMentions(tgEntry, sortlabel, doReturn)
local ns = 'Category:'
local cat
if tgEntry == nil then
-- Parent, the container cat
cat = 'Articles that mention a specific track gauge'
else
cat = 'Articles that mention track gauge ' .. tgEntry.id .. ' mm'
end
-- Argument 'label' can be used to add a catsort. Catsort is not used (as of 20 May 2014)
if sortlabel ~= nil then
sortlabel = '|' .. sortlabel
else
sortlabel = ''
end
if doReturn ~= nil then
if doReturn == 'fullpagename' then
return ns .. cat
elseif doReturn == 'pagename' then -- plaintext, no namespace
return cat
elseif doReturn == 'show' then -- colontrick
return '[[:' .. ns .. cat .. sortlabel .. ']]'
else -- unknown arg value
return ns .. cat
end
else -- Returns straight categorisation (wikitext)
return '[[' .. ns .. cat .. sortlabel .. ']]'
end
end
-----------------------------------------------------------------------------------
-- formatImp -- Formats imperial units size into a single text element
-----------------------------------------------------------------------------------
function p.formatImp(tgEntry, measurementToLink, setNowrap, addUnitlink)
local ret = {}
local ft = tgEntry.ft
if ft then
local ftlink = addUnitlink and measurementToLink ~= 'imp' and '[[Foot (unit)|ft]]' or 'ft'
table.insert(ret, mw.ustring.format('%s %s', ft, ftlink))
end
local inches = tgEntry['in']
local num = tgEntry.num
local den = tgEntry.den
local has_fraction = num and den
if inches and not num and not den then
table.insert(ret, inches)
elseif has_fraction then
table.insert(ret, frac(inches, num, den))
end
if inches or num and den then
local incheslink = addUnitlink and measurementToLink ~= 'imp' and '[[inch|in]]' or 'in'
table.insert(ret, incheslink)
end
local gaugeSize
if setNowrap then
gaugeSize = noWrap(table.concat(ret, ' '))
else
gaugeSize = table.concat(ret, ' ')
end
-- we have do this here to work around [[phab:T200704]]
local templatestyles
if has_fraction then
templatestyles = mw.getCurrentFrame():extensionTag{
name = 'templatestyles', args = { src = 'Fraction/styles.css' }
}
else
templatestyles = ''
end
if measurementToLink == 'imp' and tgEntry.pagename ~= nil then
return mw.ustring.format(
'%s[[%s|%s]]',
templatestyles,
tgEntry.pagename,
gaugeSize
)
else
return templatestyles .. gaugeSize
end
end
-----------------------------------------------------------------------------------
-- formatMet -- Formats metric measurements into a single formatted text element. Public for autodocument
-----------------------------------------------------------------------------------
function p.formatMet(tgEntry, measurementToLink, setNowrap, addUnitlink, removeComma)
local m = tgEntry.m
local gaugeSize
if m then
local mUnit = addUnitlink and measurementToLink ~= 'met' and '[[metre|m]]' or 'm'
gaugeSize = mw.ustring.format('%s %s', m, mUnit)
else
local mm = tgEntry.mm
mm = tonumber(mm)
if mm then
mm = mw.getContentLanguage():formatNum(mm)
if removeComma then
mm = string.gsub( mm, ",", "" )
end
end
local mmUnit = addUnitlink and measurementToLink ~= 'met' and '[[millimetre|mm]]' or 'mm'
gaugeSize = mw.ustring.format('%s %s', mm, mmUnit)
end
if setNowrap then
gaugeSize = noWrap(gaugeSize)
end
if measurementToLink == 'met' and tgEntry.pagename ~= nil then
return mw.ustring.format('[[%s|%s]]', tgEntry.pagename, gaugeSize)
else
return gaugeSize
end
end
-----------------------------------------------------------------------------------
-- formatAltName
-----------------------------------------------------------------------------------
function formatAltName(tgEntry, addGaugeName, addGaugeNameLink, disp, setNowrap, engvar)
-- Assumed: at least one to add is true.
if tgEntry.name == nil then
-- Not checked: link does exist alone
return ''
end
local retAlt = {}
if disp == 'br' then
table.insert(retAlt, '<br />')
else
table.insert(retAlt, ' ')
end
if setNowrap then
table.insert(retAlt, '<span class="nowrap">')
end
if addGaugeNameLink then
if engvar == 'en-us' then
-- Current implementations (2016): metER for metRE (1000-met, 1009-met)
table.insert(retAlt, tgEntry.en_US_link or tgEntry.link or tgEntry.name)
else
table.insert(retAlt, tgEntry.link or tgEntry.name)
end
else -- so must be unlinked .name to add
if engvar == 'en-us' then
-- Current implementations (2016): metER for metRE (1000-met, 1009-met)
table.insert(retAlt, tgEntry.en_US_name or tgEntry.name)
else
table.insert(retAlt, tgEntry.name)
end
end
if setNowrap then --close tag
table.insert(retAlt, '</span>')
end
return table.concat(retAlt, '')
end
-----------------------------------------------------------------------------------
-- main -- The basic module
-----------------------------------------------------------------------------------
function p.main(frame)
-- In general: the tgEntry object (from TG/data) is passed to the functions, while arguments are processed here.
local title = mw.title.getCurrentTitle()
local args = prepareArgs(frame)
local tgEntry = p.getTrackGaugeEntry(args.searchAlias)
-- Categorise & preview warning when no track gauge definition was found.
if tgEntry == nil then
local input = args[1] or ''
local errorTail = require('Module:If preview')._warning({
'Track gauge ' ..
input ..
' not in [[:Template:Track_gauge#List_of_defined_track_gauges|List of defined track gauges]] ([[Template talk:Track gauge|talk]]).'
})
if title:inNamespaces(0, 14) then -- mainspace and category space
errorTail = errorTail .. "[[Category:Articles using Template:Track gauge with unrecognized input]]"
end
return input .. errorTail
end
-- Check and set args & tgEntry props: disp, first, nowrap, first
local disp = args.disp or ''
local first = args.first or tgEntry.def1
local unitlink = args.unitlink or ''
local comma = args.comma or ''
local nowrap = args.nowrap or ''
local setNowrapElement = (nowrap == '' or nowrap == 'off') -- To prevent nested nowrap tags
local measurementToLink
if args.lk == 'on' then
if disp == '1' then
measurementToLink = first -- Can make metric text links to the imp linked page
else
measurementToLink = tgEntry.def1 -- When first=swapped, this could link 2nd measure.
end
end
-- String the text elements together (compose the return table)
local ret = {}
-- nowrap opening tag
if nowrap == 'all' or nowrap == 'on' then
table.insert(ret, '<span class="nowrap">')
end
-- First measure
if first == 'met' then
table.insert(ret,
p.formatMet(tgEntry, measurementToLink, setNowrapElement, unitlink == 'on', comma == 'off'))
else
table.insert(ret,
p.formatImp(tgEntry, measurementToLink, setNowrapElement, unitlink == 'on', comma == 'off'))
end
-- The joint and the second measure
if disp ~= '1' then
local joinText = ''
local closeDisp = ''
if disp == 's' or disp == '/' then
joinText = ' / ' --spaces
elseif disp == 'br' then
joinText = '<br />('
closeDisp = ')'
elseif disp == '[' or disp == '[]' then
joinText = ' ['
closeDisp = ']'
elseif disp ~= '' then -- Is anytext
joinText = ' ' .. args['rawDisp'] .. ' '
else
joinText = ' ('
closeDisp = ')'
end
table.insert(ret, joinText)
if first ~= 'met' then
table.insert(ret,
p.formatMet(tgEntry, measurementToLink, setNowrapElement, unitlink == 'on', comma == 'off'))
else
table.insert(ret,
p.formatImp(tgEntry, measurementToLink, setNowrapElement, unitlink == 'on'))
end
table.insert(ret, closeDisp) -- Could be ''
end
if nowrap == 'on' then -- Closing tag
table.insert(ret, '</span>')
end
-- Alternative name
if args.al == 'on' or args.allk == 'on' then
local setNowrapAltname = (nowrap == '' or nowrap == 'on') -- Logic applied to prevent nested nowrap tags
table.insert(ret, formatAltName(tgEntry, args.al == 'on', args.allk == 'on', disp, setNowrapAltname, args.engvar))
end
-- Closing nowrap tag
if nowrap == 'all' then
table.insert(ret, '</span>')
end
-- Category mentionings (maintenance)
if args.addcat or '' == 'no' then
-- No categorization
elseif title:inNamespaces(0) then
-- switched off per [[Wikipedia:Categories_for_discussion/Log/2016_December_6#Category:Articles_that_mention_a_specific_track_gauge]]
-- 2016-12-19
-- table.insert(ret, p.catMentions(tgEntry))
end
-- Now sting the table together
return table.concat(ret, '')
end
return p
--20161219: maintenance categorisation switched off per CfD
--20170602: fix bug, show name when al=on
--20180708: show preview warning when gauge is not in list
--20190124: with disp=/ (slash) value separator: surround by spaces
--20210304: add option comma=off (mm only)