Mô đun:Track gauge
Giao diện
-- This module implements the {{Track gauge}} template.
-- Data is in Module:Track gauge/data and in Module:Track gauge/extra
local p = {}
local gaugeDataAll = nil
local gaugeDataExtra = nil
local dataPageName = 'Module:Track gauge/data' -- sandbox here
local dataPageExtra = 'Module:Track gauge/extra' -- sandbox here
-----------------------------------------------------------------------------------
-- 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
-----------------------------------------------------------------------------------
-- getRgEntry -- Find entry data for a single gauge (alias)
-----------------------------------------------------------------------------------
function p.getRgEntry(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
-- No hit, so seach in datapage /extra
tgEntry = nil
gaugeDataExtra = mw.loadData(dataPageExtra)
for i, tgEntry in ipairs(gaugeDataExtra) 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)
return mw.ustring.format(
'<span class="frac">%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
cat = 'Articles that mention a specific track gauge' -- Parent, the container cat
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
if inches and not num and not den then
table.insert(ret, inches)
elseif num and den 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 = 'Phân số/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)
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)
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, addArticleLink, disp, setNowrap)
-- Asserted: al=on
if tgEntry.name == nil then
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 addArticleLink and tgEntry.link then -- If not defined then fallback to unlinked name
table.insert(retAlt, tgEntry.link)
else
table.insert(retAlt, tgEntry.name)
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: tgEntry (from TG/data) is passed to the functions, arguments are processed here.
local title = mw.title.getCurrentTitle()
local args = prepareArgs(frame)
local tgEntry = p.getRgEntry(args.searchAlias)
-- Categorise the page if no gauge information was found.
if tgEntry == nil then
local category = ''
if title:inNamespaces(0, 14) then
local sort1
if (args[1] or '') == '' then -- Blank input, sort top.
sort1 = ' '
else
sort1 = args[1] .. ', '
end
category = mw.ustring.format(
"[[Category:Articles using template 'Track gauge' with unrecognized input|%s%s]]",
sort1, title.text)
end
return (args[1] or '') .. category
end
-- sandbox here: option to show "(Track gauge/sandbox is currently under construction)" message. (Comment out to make it idle)
-- return tgEntry.id .. ' <span style="font-size:85%; font-style:italic; font-family=courier">(Track gauge/sandbox is currently under construction)</span>'
-- 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 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'))
else
table.insert(ret,
p.formatImp(tgEntry, measurementToLink, setNowrapElement, unitlink == 'on'))
end
-- The joint and the second measure
if disp == '1' then
else
local joinText = ''
local closeDisp = ''
if disp == 's' or disp == '/' then
joinText = '/​'
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'))
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 or args.allk ~= nil then
local setNowrapAltname = (nowrap == '' or nowrap == 'on') -- Logic applied to prevent nested nowrap tags
table.insert(ret, formatAltName(tgEntry, args.allk == 'on', disp, setNowrapAltname))
end
-- Closing nowrap tag
if nowrap == 'all' then
table.insert(ret, '</span>')
end
-- Now sting the table together
return table.concat(ret, '')
end
return p