A modult a Modul:Routemap/doc lapon tudod dokumentálni
local i18n = {
errors = {
= "Missing parameter!",
= "Collapsible section not closed properly!",
= "Missing start-Collapsible markup!",
= "Collapsible section must not be empty!",
= "Invalid first row of collapsible section!",
= "Invalid collapsible replacement row!",
= "Invalid colspan set!",
},
= {
default = ']',
= ']',
= ']',
= ']',
= ']',
= ']',
= ']'
},
text = {
navbar_mini = false, -- for navbar pos 2 only
navbar_text = 'This diagram:', -- for navbar pos 2 only
legend_text = 'Legend',
legend = {
default = '[[Template:Railway line legend',
track = '[[Template:Railway track legend',
bus = '[[Template:Bus route legend',
road = '[[Template:Roads legend',
canal = '[[Template:Waterways legend',
water = '[[Template:Waterways legend',
waterway = '[[Template:Waterways legend',
foot = '[[Template:Trails legend',
footpath = '[[Template:Trails legend',
walkway = '[[Template:Trails legend'
}
},
html = {
= '<div style="%s">]%s</div>',
= '<div class="RMic" style="%s">]</div>',
= '<div style="%s"><div class="RMov">%s</div><div%s>]%s</div></div>',
= '<div class="RMtx RM%s" style="%s"><div%s style="%s" title="%s">%s%s%s%s%s%s</div></div>',
= '<div class="RMtx RM%s" style="%s"><div%s style="%s" title="%s">%s%s%s%s%s</div></div>',
= '<div class="RM%s" style="%s"><div class="RMov">%s</div><div class="RMtx RM%s" style="%s"><div%s style="%s" title="%s">%s%s%s%s%s%s</div></div></div>',
= '<div class="RM%s" style="%s">%s</div>',
= '<div style="%s"><div class="RMov">%s</div><div class="RMsp RM%s" style="%s">%s</div></div>',
= '<div class="RMf_" style="%s"><div class="RMfm" style="background:%s"></div></div>',
= '<div class="RMf_ RM%s" style="%s"></div>',
= '\
|class="RMl4" style="%s"|<div class="RMsi">%s</div>',-- parameters:linfo4-width, linfo4
= '<div class="RMsi">%s</div> ',
= ' <div class="RMsi">%s</div>',
= '\
|class="RMr4" style="%s"|<div class="RMsi">%s</div>',-- parameters:rinfo4-width, rinfo4
= '\
|- %s\
|class="RMl" colspan="%s" style="%s"|%s\
|%s style="%s"|<div class="RMsi">%s</div>\
|class="RMir" style="%s"|%s\
|%s style="%s"|<div class="RMsi">%s</div>\
|class="RMr" colspan="%s" style="%s"|%s%s',-- parameters: linfo4-fmt, colspan-left, linfo3+2-width, linfo3+2, linfo1-pad, linfo1-width, linfo1, bg, cells, rinfo1-pad, rinfo1-width, rinfo1, colspan-right, rinfo2+3-width, rinfo2+3, rinfo4-fmt
= '\
|- style="line-height:1"\
|colspan="7" style="padding:0 !important;background:%s"|\
{|class="RMcollapse %s%s" style="%s"',-- parameters: bg, "collapsible "/"mw-collapsible mw-", collapse-state, "float:right" / ""
= '\n|}',
= '45px',-- 50px is the minimal width for / button. Use 40px for /
= '\n! style="padding-right:3px;min-width:%s;%s" |',--parameters: left-button-width, linfo4-width
= '\
{|cellspacing="0" cellpadding="0" style="line-height:1;width:100%%;padding:0 !important;margin:0 !important"\
|style="padding:0 3px 0 1px;text-align:left"|<div class="RMsi">%s</div>\
|style="text-align:right"| %s\
|}',-- parameters: linfo4, linfo3+2
= '45px',-- 72px is the minimal width for / button at 90%. Use 58px for /
= '\
{|cellspacing="0" cellpadding="0" style="line-height:1;width:100%%;padding:0 !important;margin:0 !important"\
|style="text-align:left"| %s\
|style="padding:0 1px 0 3px;text-align:right"|<div class="RMsi">%s</div>\
|}',-- parameters: rinfo2+3, linfo4
= '\n| style="padding-left:3px;font-size:90%%;min-width:%s;%s" |',--parameters: right-button-width, rinfo4-width
= '\
|- style="line-height:1"\
|colspan="7" style="padding:0 %s"|<div style="position:relative">\
{| class="RMreplace" style="%sbackground:%s"',-- parameters: "right-button-width 0 0" / "0 0 left-button-width", "right:0px" / "", bg
= '\n|}</div>',
= '%s\n|-\n| colspan="7" style="background:%s;text-align:%s;%s"|\n%s',
= '\n|-\n|style="padding:0 3px 0 0;%s"|\n|style="%s"|\n|%s style="%s"|\n|\n|%s style="%s"|\n|style="%s"|\n|style="padding:0 0 0 3px;%s"|'
}
}
local p,q={},{}
local getArgs = require('Module:Arguments').getArgs
local function makeInvokeFunction(funcName)
-- makes a function that can be returned from #invoke, using
-- ].
return function (frame)
local args = getArgs(frame, {parentOnly = true})
return p(args)
end
end
local function formaterror(key,param)
local result = string.format(i18n.html, '', '', '', '', '<span class="error">' .. string.format(i18n.errors or (tostring(key) .. ' %s'),
tostring(param or '')) .. '</span>')
if mw.site.namespaces.isContent then result = result .. (i18n or i18n.default or '') end
return result
end
local function RGBbyCode(code)-- RGB codes for BSicon sets at Commons:Category:Icons for railway descriptions/other colors
local colors = {-- Any changes should be discussed at Commons:Talk:BSicon/Colors
bahn = 'BE2D2C', ex = 'D77F7E',
u = '003399', uex = '6281C0',
f = '008000', fex = '64B164',
g = '2CA05A', gex = '7EC49A',
azure = '3399FF', ex_azure = '99CCFF',
black = '000000', ex_black = '646464',
blue = '0078BE', ex_blue = '64ACD6',
brown = '8D5B2D', ex_brown = 'B89A7F',
carrot = 'ED9121', ex_carrot = 'F1BA76', excarrot = 'F1BA76', ex_excarrot = 'F3D2A9',
cerulean = '1A8BB9', ex_cerulean = '73B7D3',
cyan = '40E0D0', ex_cyan = '8AEAE1',
deepsky = '00BFFF', ex_deepsky = '7FDFFF',
denim = '00619F', ex_denim = '649EC3',
fuchsia = 'B5198D', ex_fuchsia = 'D173B8',
golden = 'D7C447', ex_golden = 'E5DA8E',
green = '2DBE2C', ex_green = '7FD67E',
grey = '999999', ex_grey = 'C0C0C0',
jade = '53B147', ex_jade = '95CE8E',
lavender = '9999FF', ex_lavender = 'C0C0FF',
lime = '99CC00', ex_lime = 'D1E681',
maroon = '800000', ex_maroon = 'B16464',
ochre = 'CC6600', ex_ochre = 'DEA164',
olive = '837902', ex_olive = 'B2AC64',
orange = 'FF6600', ex_orange = 'FF9955',
pink = 'F0668D', ex_pink = 'F4A1B8',
purple = '8171AC', ex_purple = 'B1A8CB',
red = 'EF161E', ex_red = 'F37176',
ruby = 'CC0066', ex_ruby = 'DE64A1', exruby = 'DE64A1', ex_exruby = 'E89FC4',
saffron = 'FFAB2E', ex_saffron = 'FFC969',
sky = '069DD3', ex_sky = '67C2E3',
steel = 'A1B3D4', ex_steel = 'C4CFE3',
teal = '339999', ex_teal = '82C0C0', exteal = '82C0C0', ex_exteal = 'B1D6D6',
violet = '800080', ex_violet = 'B164B1',
yellow = 'FFD702', ex_yellow = 'FFEB81',
}
return colors or colors.bahn
end
p.RGBbyCode = makeInvokeFunction('_RGBbyCode')
function p._RGBbyCode(args)
return RGBbyCode(args)
end
local function properties(str)
--str is a combination of properties with following syntax:
--property name=value,property name1=value1,property name2=value2 and so on
local result = {}
for i, v in ipairs(mw.text.split(str, ',')) do
if v then
local t = mw.text.split(v, '=')
if string.find(v, '=') then
t = mw.text.trim(t) --trim parameter names
table.insert(result, t)
result] = t or '' --fill table with pairs "property"="value"
elseif result] then
table.insert(result, result)
result] = result]..','..t --if no equals sign then tack t onto the previous result
else
table.insert(result, '~~')
end
else
table.insert(result, '~~')
end
end
return result
end
local function positive(x)
if not x then return nil else x = string.lower(x) end
if x == 'yes' or x == 'y' or x == '1' or x == 'true' then return 1 end
end
local function negative(x)
if not x then return nil else x = string.lower(x) end
if x == 'no' or x == 'n' or x == '0' or x == 'false' then return 0 end
end
local function alignment(x, y, z)
if not x then return nil end
local directions = {
= {'l', 'left',},
= {'r', 'right',},
= {'a', 't', 'top',},
= {'e', 'b', 'bottom',},
= {'la', 'tl', 'c4', 'nw', 'top-left', 'topleft',},
= {'ra', 'tr', 'c1', 'ne', 'top-right', 'topright',},
= {'le', 'bl', 'c3', 'sw', 'bottom-left', 'bottomleft',},
= {'re', 'br', 'c2', 'se', 'bottom-right', 'bottomright',},
= {'c', 'center', 'centre',},
= {'m', 'middle',},
= {'ma', 'tc', 'top-center', 'top-centre', 'topcenter', 'topcentre',},
= {'me', 'bc', 'bottom-center', 'bottom-centre', 'bottomcenter', 'bottomcentre',},
= {'lm', 'ml', 'middle-left', 'middleleft',},
= {'rm', 'mr', 'middle-right', 'middleright',},
= {'cm', 'mc', 'middle-center', 'middle-centre', 'middlecenter', 'middlecentre',},
}
for k, v in pairs(directions) do
for _, name in ipairs(v) do
if x:lower() == name then
local values = mw.text.split(k, '-')
if values == 'inherit' then values = y end
if values == 'inherit' then values = z end
return values
end
end
end
return {y, z}
end
local function cell(icon,overlapIcons,rowProps)--[[
Icon handling. Each icon is defined as in the following example:
icon ID!~overlap icon ID!@image link target
Values for an icon ID containing "*" are treated as text, with the letter(s) before "*" as width prefix(es).
No limit on overlapping icons or text; just separate them by "!~".
Parameters can be added after every object, separated to the left by "!_". This, if there is a link, must be after the link.
Parameters for individual objects in an overlapping stack can also be added, separated to the left by "__".
Unless a link is provided, each cell will have mouseover text indicating its contents.
]]
local tmp, tmp2, cellProps, iconProps, overlapProps, tmp_sep, link, tracking, icontext, iconpre = {}, {}, {}, {}, {}, '', '', ''
if #overlapIcons > 0 then
tmp = mw.text.split(overlapIcons, '!_')
if #tmp > 1 then overlapIcons, cellProps = tmp, properties(tmp) end
tmp = mw.text.split(overlapIcons, '!@')
overlapIcons = tmp
if #tmp > 1 then link = tmp end
tmp = mw.text.split(icon, '__')
icon = tmp
if #tmp > 1 then iconProps = properties(tmp) end
for i, v in ipairs(overlapIcons) do
tmp = mw.text.split(v, '__')
overlapIcons = mw.text.trim(tmp)
if #tmp > 1 then overlapProps = properties(tmp) else overlapProps = {} end
end
else
tmp = mw.text.split(icon, '_')
if #tmp > 1 then icon, cellProps = tmp, properties(tmp) end
tmp = mw.text.split(icon, '!@')
icon = mw.text.trim(tmp)
if #tmp > 1 then link = tmp end
end
if #overlapIcons > 0 and icon ~= '' then tmp_sep = '; ' end
local icontip = mw.text.nowiki(mw.text.unstripNoWiki(icon..tmp_sep..table.concat(overlapIcons, '; ')))
local textspl = string.find(icon, '%*')
if textspl then
icontext = mw.text.trim(mw.ustring.sub(icon, textspl + 1))
if textspl ~= 1 then iconpre = mw.text.trim(mw.ustring.sub(icon, 1, textspl - 1)) end
end
cellProps.class = ''
if cellProps.style then cellProps.style = ';'..cellProps.style else cellProps.style = '' end
cellProps.bg = cellProps.bg or cellProps.background or cellProps.bgcolor
if cellProps.bg then cellProps.style = cellProps.style..';background:'..cellProps.bg end
if #overlapIcons > 0 or icontext then
cellProps._before, cellProps._after = rowProps._before or '', rowProps._after or ''
cellProps.color = cellProps.color or cellProps.colour ; cellProps.bold = cellProps.bold or cellProps.b ; cellProps.italic = cellProps.italic or cellProps.i or cellProps.it
if cellProps.color then cellProps.style = cellProps.style..';color:'..cellProps.color end
if positive(cellProps.italic) then cellProps.style = cellProps.style..';font-style:italic' end
if positive(cellProps.bold) then cellProps.style = cellProps.style..';font-weight:bold' end
if not cellProps.fontsize or rowProps.fontsize or cellProps.fontsize == 'info' then
elseif cellProps.fontsize == 'cmt' or cellProps.fontsize == 'comment' then
cellProps._before, cellProps._after = '<div class="RMsi">', '</div>'
else
cellProps.style = cellProps.style..';font-size:'..cellProps.fontsize
end
if cellProps.align or rowProps.align then
rowProps.align = rowProps.align or {'middle', 'center'}
cellProps.align = alignment(cellProps.align, rowProps.align, rowProps.align) or rowProps.align
cellProps.style, cellProps.textfmt = cellProps.style..';text-align:'..cellProps.align, ';vertical-align:'..cellProps.align
else
cellProps.textfmt = ''
end
end
if #overlapIcons > 0 then
tmp = {}
for i, v in ipairs(overlapIcons) do
local thislink = link
if i ~= #overlapIcons then thislink = '' end
if thislink and thislink ~= '' then icontip = thislink end
if overlapProps.style then overlapProps.style = ';'..overlapProps.style else overlapProps.style = '' end
overlapProps.bg = overlapProps.bg or overlapProps.background or overlapProps.bgcolor
if overlapProps.bg then overlapProps.style = overlapProps.style..';background:'..overlapProps.bg end
local tmp_textspl = string.find(v, '%*')
if tmp_textspl then
overlapProps.class = ''
local tmp_icontext, tmp_iconpre = mw.text.trim(mw.ustring.sub(v, tmp_textspl + 1)), ''
if tmp_textspl ~= 1 then tmp_iconpre = mw.text.trim(mw.ustring.sub(v, 1, tmp_textspl - 1)) end
overlapProps._before, overlapProps._after = cellProps._before, cellProps._after
overlapProps.color = overlapProps.color or overlapProps.colour ; overlapProps.bold = overlapProps.bold or overlapProps.b ; overlapProps.italic = overlapProps.italic or overlapProps.i or overlapProps.it
if overlapProps.color then overlapProps.style = overlapProps.style..';color:'..overlapProps.color end
if positive(overlapProps.italic) then overlapProps.style = overlapProps.style..';font-style:italic' end
if positive(overlapProps.bold) then overlapProps.style = overlapProps.style..';font-weight:bold' end
if rowProps.fontsize or cellProps.fontsize or overlapProps.fontsize == 'info' then
elseif not overlapProps.fontsize then
overlapProps.class = ' class="RMts"'
elseif overlapProps.fontsize == 'cmt' or overlapProps.fontsize == 'comment' then
overlapProps._before, overlapProps._after = '<div class="RMsi">', '</div>'
else
overlapProps.style = overlapProps.style..';font-size:'..overlapProps.fontsize
end
if overlapProps.align or cellProps.align then
cellProps.align = cellProps.align or {'middle', 'center'}
overlapProps.align = alignment(overlapProps.align, cellProps.align, cellProps.align) or cellProps.align
overlapProps.style, overlapProps.textfmt = overlapProps.style..';text-align:'..overlapProps.align, ';vertical-align:'..overlapProps.align
else
overlapProps.style, overlapProps.textfmt = overlapProps.style..';text-align:center', ';vertical-align:middle'
end
if overlapProps.abbr then
overlapProps.tag = {'<abbr title="'..string.gsub(overlapProps.abbr, '"', '"')..'">', '</abbr>'}
else
overlapProps.tag = {'', ''}
end
table.insert(tmp, string.format(i18n.html, (tmp_iconpre and tmp_iconpre ~= '' and tmp_iconpre or '_'), overlapProps.style, overlapProps.class, overlapProps.textfmt, icontip, overlapProps.tag, overlapProps._before, tmp_icontext, overlapProps._after, overlapProps.tag))
else
v = mw.text.trim(v)
if string.find(v, 'num') then
if not string.find(v, 'numN%d+') then tracking = tracking..(i18n or i18n.default) end
end
table.insert(tmp, string.format(i18n.html, overlapProps.style, v, thislink, icontip))
end
end
if iconProps.style then tmp2 = true else iconProps.style = '' end
iconProps.bg = iconProps.bg or iconProps.background or iconProps.bgcolor
if iconProps.bg then iconProps.style = iconProps.style..';background:'..iconProps.bg end
if string.match(icon, '^?o?c?d?b?s?w?$') then
if tmp2 then iconProps.style = ';'..iconProps.style end
return string.format(i18n.html, cellProps.style, mw.text.trim(table.concat(tmp)), (string.match(icon, '^.+$') or '_'), iconProps.style, tracking)
elseif icontext then
iconProps.class = ''
iconProps._before, iconProps._after = cellProps._before, cellProps._after
iconProps.color = iconProps.color or iconProps.colour ; iconProps.bold = iconProps.bold or iconProps.b ; iconProps.italic = iconProps.italic or iconProps.i or iconProps.it
if iconProps.color then iconProps.style = iconProps.style..';color:'..iconProps.color end
if positive(iconProps.italic) then iconProps.style = iconProps.style..';font-style:italic' end
if positive(iconProps.bold) then iconProps.style = iconProps.style..';font-weight:bold' end
if rowProps.fontsize or cellProps.fontsize or iconProps.fontsize == 'info' then
elseif not iconProps.fontsize then
iconProps.class = ' class="RMts"'
elseif iconProps.fontsize == 'cmt' or iconProps.fontsize == 'comment' then
iconProps._before, iconProps._after = '<div class="RMsi">', '</div>'
else
iconProps.style = iconProps.style..';font-size:'..iconProps.fontsize
end
if iconProps.align or cellProps.align then
cellProps.align = cellProps.align or {'middle', 'center'}
iconProps.align = alignment(iconProps.align, cellProps.align, cellProps.align) or cellProps.align
iconProps.style, iconProps.textfmt = iconProps.style..';text-align:'..iconProps.align, ';vertical-align:'..iconProps.align
else
iconProps.style, iconProps.textfmt = iconProps.style..';text-align:center', ';vertical-align:middle'
end
if iconProps.abbr then
iconProps.tag = {'<abbr title="'..string.gsub(iconProps.abbr, '"', '"')..'">', '</abbr>'}
else
iconProps.tag = {'', ''}
end
if tmp2 then iconProps.style = ';'..iconProps.style end
return string.format(i18n.html, (iconpre and iconpre ~= '' and iconpre or '_'), cellProps.style, mw.text.trim(table.concat(tmp)), (iconpre and iconpre ~= '' and iconpre or '_'), iconProps.style, iconProps.class, iconProps.textfmt, icontip, iconProps.tag, iconProps._before, icontext, iconProps._after, tracking, iconProps.tag)
else
if iconProps.style ~= '' then iconProps.style = string.gsub(' style="'..iconProps.style..'"', '";', '"', 1) end
if string.find(icon, 'num') then
if not string.find(icon, 'numN%d+') then tracking = tracking..(i18n or i18n.default) end
end
return string.format(i18n.html, cellProps.style, mw.text.trim(table.concat(tmp)), iconProps.style, icon, icontip, tracking)
end
end
if string.match(icon, '^?o?c?d?b?s?w?$') then
return string.format(i18n.html, (string.match(icon, '^.+$') or '_'), cellProps.style, tracking)
else
if link and link ~= '' then icontip = link end
if icontext then
if not cellProps.fontsize and not rowProps.fontsize then cellProps.class = ' class="RMts"' end
if cellProps.abbr then
cellProps.tag = {'<abbr title="'..string.gsub(cellProps.abbr, '"', '">')..'">', '</abbr>'}
else
cellProps.tag = {'', ''}
end
return string.format(i18n.html, (iconpre and iconpre ~= '' and iconpre or '_'), cellProps.style, cellProps.class, cellProps.textfmt, icontip, cellProps.tag, cellProps._before, icontext, cellProps._after, tracking, cellProps.tag)
else
if string.find(icon, 'num') then
if not string.find(icon, 'numN%d+') then tracking = tracking..(i18n or i18n.default) end
end
return string.format(i18n.html, cellProps.style, icon, link, icontip, tracking)
end
end
end
local function fillercell(code, height)
--Creates a 5px-high row.
--Values in icon pattern can only be , d, or #.
height = mw.text.trim(height)
if height ~= '' then
if tonumber(height) then height = height..'px' end
height = 'height:'..height..';min-height:'..height
end
if string.match(code, '^?o?c?d?b?s?w?$') then
return string.format(i18n.html, (string.match(code, '^.+$') or '_'), height)
elseif mw.ustring.sub(code,1,1) == '#' then
return string.format(i18n.html, height, code)
else
return string.format(i18n.html, height, '#'..RGBbyCode(code))
end
end
local function row(pattern,noformatting,filler)--[[
Row handling. Each row looks like the following:
row properties~~linfo4~~linfo3~~linfo2~~linfo1! !(icon pattern)~~rinfo1~~rinfo2~~rinfo3~~rinfo4~~row properties
]]
local result = { = '', = '', = '', rowstyle = '', = {}, = '', = '', = '', = {}}
local lcolspan, rcolspan, linfo4_fmt, rinfo4_fmt = '2', '2', '', ''
local left, right, icons, overlapIcons, tmp = {}, {}, {}, {}, mw.text.split(pattern, '! !')
if #tmp > 1 then--splitting the pattern by '! !'
left = tmp ; right = tmp
else
left = '' ; right = tmp or ''
end
tmp = mw.text.split(left, '~~')--analysing the left part
if #tmp > 1 then--if there are several ~~
result = mw.getCurrentFrame():preprocess(mw.text.trim(tmp))
result = mw.text.trim(tmp)
if #tmp > 2 then
tmp = mw.text.trim(tmp)
if tmp ~= '' then result = string.format(i18n.html, tmp) .. result end
if #tmp > 3 then
tmp = mw.text.trim(tmp)
if tmp ~= '' then
result = mw.getCurrentFrame():preprocess(tmp)
lcolspan = '1'
linfo4_fmt = string.format(i18n.html, '', result)
end
if #tmp > 4 then result.rowProp = properties(mw.text.trim(tmp)) end
end
end
else--assume only linfo2 was provided.
result = mw.text.trim(tmp)
end
result = mw.getCurrentFrame():preprocess(result)--expand possible templates in info.
tmp = mw.text.split(right, '~~')--analysing the right part
if #tmp > 2 then
result = mw.getCurrentFrame():preprocess(mw.text.trim(tmp))
result = mw.text.trim(tmp)
if #tmp > 3 then
tmp = mw.text.trim(tmp)
if tmp ~= '' then result = result .. string.format(i18n.html, tmp) end
if #tmp > 4 then
tmp = mw.text.trim(tmp)
if tmp ~= '' then
result = mw.getCurrentFrame():preprocess(tmp)
rcolspan = '1'
rinfo4_fmt = string.format(i18n.html, '', result)
end
if #tmp > 5 then result.rowProp = properties(mw.text.trim(tmp)) end
end
end
else--assume only rinfo2 was provided.
result = mw.text.trim(tmp or '')
end
result = mw.getCurrentFrame():preprocess(result)
-- The below parameter functions are passed through to the cells.
if result.rowProp.fontsize == 'cmt' or result.rowProp.fontsize == 'comment' then
result.rowProp._before, result.rowProp._after = '<div class="RMsi">', '</div>'
end
if result.rowProp.align then
result.rowProp.align = alignment(result.rowProp.align, 'middle', 'center') or {'middle', 'center'}
end
icons = mw.text.split(tmp, '\\')--splitting the string of icons first by "\"
if type(filler) == 'string' then
result.style = ';font-size:0px'
for i, v in ipairs(icons) do table.insert(result, fillercell(v, filler)) end--no !@ or !~ for filler row
else
result.style = ''
for i, v in ipairs(icons) do
tmp = mw.text.split(v, '!~')
icons = tmp
table.remove(tmp, 1)
table.insert(overlapIcons, tmp)
end
for i, v in ipairs(icons) do table.insert(result, cell(v, overlapIcons, result.rowProp)) end
end
result = table.concat(result)
if result.rowProp.style then result.style = result.style..';'..result.rowProp.style end
result.rowProp.bg = result.rowProp.bg or result.rowProp.background or result.rowProp.bgcolor ; result.rowProp.color = result.rowProp.color or result.rowProp.colour ; result.rowProp.bold = result.rowProp.bold or result.rowProp.b ; result.rowProp.italic = result.rowProp.italic or result.rowProp.i or result.rowProp.it
if result.rowProp.bg then result.style = result.style..';background:'..result.rowProp.bg end
if result.rowProp.color then result.style = result.style..';color:'..result.rowProp.color end
if positive(result.rowProp.italic) then result.style = result.style..';font-style:italic' end
if positive(result.rowProp.bold) then result.style = result.style..';font-weight:bold' end
if result.rowProp.fontsize and result.rowProp._after == '' and result.rowProp.fontsize ~= 'info' then
result.style = result.style..';font-size:'..result.rowProp.fontsize
end
if noformatting then
return result
else
return string.format(i18n.html, linfo4_fmt, lcolspan, '', result, q.linfo1_pad, '', result, result.style,
result, q.rinfo1_pad, '', result, rcolspan, '', result, rinfo4_fmt)
end
end
--↓ This table handles diagram rows beginning with a hyphen ("-").
q = {collapsibles = -1, text_width = {'', '', '', '', '', ''}, linfo1_pad = 'class="RMl1"', rinfo1_pad = 'class="RMr1"', bg = '#F9F9F9'}
q.isKeyword = function(pattern, i, rows, justTest)
if mw.ustring.sub(pattern, 1, 1) ~= '-' then if justTest then return false else return nil end end--not a valid keyword
local tmp = mw.text.split(string.sub(pattern, 2), '%-')
if type(q])=="function" and tmp ~= 'isKeyword' then
if justTest then return tmp else return q](tmp, i, rows) end--valid keyword
else
if justTest then return false else return nil end
end
end
q = function(params, i, rows)
table.remove(rows, i)
local tmp = q.isKeyword(rows, i, rows, true)
if tmp then
if tmp == 'endCollapsible' then return formaterror('collapsible-block-empty')
else return formaterror('collapsible-block-no-first-row') .. q.isKeyword(rows, i, rows) --no valid keywords that can follow "startCollapsible"
end
end
if q.collapsibles == -1 then q.collapsibles = 1 else q.collapsibles = q.collapsibles + 1 end--q.collapsibles == -1 means there are no collapsibles at all; 0 - all closed; >0 - some not closed
local collapsed, replace, props = params, params or '', properties(table.concat(params, '-', 4))--params is the keyword name so all indices are shifted by one.
if collapsed == nil or collapsed == '' then collapsed = 'collapsed' end
if props.bg == nil or props.bg == '' then props.bg = 'transparent' ; props = q.bg else props = props.bg end
local mode, float, result
if q.rinfo1_pad == '' then mode = 'collapsible ' ; float = 'float:right;'
else mode = 'mw-collapsible mw-' ; float = ''
end
result = string.format(i18n.html, props.bg, mode, collapsed, float)
tmp = row(rows, true, nil)
local linfo4_3_2_fmt, rinfo2_3_4_fmt = '', ''
if q.rinfo1_pad == '' then
if tmp ~= '' or tmp ~= '' then linfo4_3_2_fmt = string.format(i18n.html, tmp, tmp) end
result = result .. string.format(i18n.html, string.format(i18n.html, i18n.html, q.text_width),
'1', q.text_width, linfo4_3_2_fmt, q.linfo1_pad, q.text_width, tmp, tmp.style, tmp, '', '', '', '1', '', '', string.format(i18n.html, '', ''))
else
if tmp ~= '' or tmp ~= '' then rinfo2_3_4_fmt = string.format(i18n.html, tmp, tmp) end
result = result .. string.format(i18n.html, string.format(i18n.html, q.text_width, tmp),
'1', q.text_width, tmp, q.linfo1_pad, q.text_width, tmp, tmp.style, tmp, q.rinfo1_pad, q.text_width, tmp,
'1', q.text_width, rinfo2_3_4_fmt, string.format(i18n.html, i18n.html, q.text_width))
end
if replace ~= '' then
if q.isKeyword(rows, i, rows, true) then return result .. formaterror('collapsible-block-no-replacement') end--a plain row needed for replacement
table.remove(rows, i)
tmp = row(rows, true, nil)
local padding, right = i18n.html .. ' 0 0', ''
if q.rinfo1_pad == '' then padding = '0 0 ' .. i18n.html ; right = 'right:0px;' end
result = result .. string.format(i18n.html, padding, right, props)
linfo4_3_2_fmt = '' ; rinfo2_3_4_fmt = ''
if q.rinfo1_pad == '' then
if tmp ~= '' or tmp ~= '' then linfo4_3_2_fmt = string.format(i18n.html, tmp, tmp) end
result = result .. string.format(i18n.html, string.format(i18n.html, '', ''), '1', q.text_width, linfo4_3_2_fmt,
q.linfo1_pad, q.text_width, tmp, tmp.style, tmp, '', '', '', '1', '', '', string.format(i18n.html, '', ''))
else
if tmp ~= '' or tmp ~= '' then rinfo2_3_4_fmt = string.format(i18n.html, tmp, tmp) end
result = result .. string.format(i18n.html, string.format(i18n.html, q.text_width, tmp), '1', q.text_width,
tmp, q.linfo1_pad, q.text_width, tmp, tmp.style, tmp, q.rinfo1_pad, q.text_width, tmp, '1', q.text_width,
rinfo2_3_4_fmt, string.format(i18n.html, '', ''))
end
result = result .. i18n.html
end
return result
end
q = function(params, i, rows)
if q.collapsibles > 0 then
q.collapsibles = q.collapsibles - 1
return i18n.html
else
return formaterror('collapsible-block-not-open')
end
end
q = function(params, i, rows)
if params == 'end' then return '' end
local tmp, j, nrows, props = {}, 0, tonumber(params), properties(table.concat(params, '-', 3))
if nrows ~= 0 then table.remove(rows, i) end
if nrows == nil then nrows = #rows - i + 1 end
while j < nrows and i <= #rows do
j = j + 1
if rows == '-colspan-end' then
j = nrows
else
table.insert(tmp, rows)
end
if nrows ~= j or i == #rows then table.remove(rows, i) end
end
if j < nrows then j = formaterror('colspan-less-rows-than-set',j) else j = '' end
return string.format(i18n.html, j, props.bg or '', props.align or '', props or '', mw.getCurrentFrame():preprocess(table.concat(tmp, '\n')))
end
q = function(params, i, rows)
local tmp, height = table.concat(params, '-', 3), (params or '')
if #params < 3 or tmp == '' then return formaterror('parameter-missing') end--TODO: specify the name of the parameter
if params ~= '' then height = params end
return row(tmp, nil, height)
end
function p.RGBbyCode(frame)
return RGBbyCode(mw.text.trim(frame.args or ''))
end
local function localroute(pattern,ptw,pbg,process)
local tmp = {}
if mw.text.trim(pbg) ~= '' then q.bg = pbg end
tmp = mw.text.split(mw.text.trim(ptw), '%s*,%s*')
if #tmp == 6 then
for i = 1, 6 do
if tmp ~= '' then
if tonumber(string.sub(tmp,-1)) then
q.text_width = 'width:' .. tmp .. 'px;min-width:' .. tmp .. 'px;'
else
q.text_width = 'width:' .. tmp .. ';min-width:' .. tmp .. ';'
end
end
end
if tmp == '' and tmp == '' and tmp == '' then
q.rinfo1_pad = ''--padding for rinfo1 column = 0, not 3px
elseif tmp == '' and tmp == '' and tmp == '' then
q.linfo1_pad = ''
end--padding for linfo1 column = 0, not 3px
elseif #tmp == 3 then
for i = 1, 3 do
if tmp ~= '' then
if tonumber(string.sub(tmp,-1)) then
q.text_width = 'width:' .. tmp .. 'px;min-width:' .. tmp .. 'px;'
else
q.text_width = 'width:' .. tmp .. ';min-width:' .. tmp .. ';'
end
end
end
q.linfo1_pad = ''
elseif #tmp == 1 and tmp ~= '' then
if tonumber(string.sub(tmp,-1)) then
q.text_width = 'width:' .. tmp .. 'px;min-width:' .. tmp .. 'px;'
else
q.text_width = 'width:' .. tmp .. ';min-width:' .. tmp .. ';'
end
q.linfo1_pad = ''
end
for i = 1, 6 do
tmp = tonumber(mw.ustring.match(q.text_width, ':(+%.?*)px;'))
if tmp then
tmp = tmp*3/40
q.text_width = 'width:' .. tmp .. 'em;min-width:' .. tmp .. 'em;'
end
end
tmp = {}
local index = 0
local rows = {}
if not process or process == '' or negative(process) then
pattern = mw.ustring.gsub(pattern, '\n(#)', '%1')
end
for item in pattern:gmatch('(*)\n?') do
item = mw.text.trim(item)
if item ~= '' then
index = index + 1
rows = item
end
end
if index == 0 then return formaterror('parameter-missing') end
for i, v in ipairs(rows) do
local keyword = q.isKeyword(v, i, rows)
if type(keyword) ~= "string" then
table.insert(tmp, row(v, nil, nil))
else
table.insert(tmp, keyword)
end
end
if q.collapsibles > 0 then table.insert(tmp, formaterror('collapsible-block-not-closed') .. q()) end
if q.collapsibles ~= -1 then
if q.rinfo1_pad == '' then
q.text_width = q.text_width .. 'min-width:' .. i18n.html .. ';'
else
q.text_width = q.text_width .. 'min-width:' .. i18n.html .. ';'
end
end
-- ↓ empty row to set column widths; ↑ if q.collapsibles ≠ -1 and there are collapsible sections, leftmost or rightmost column should be wide enough to accomodate the button
table.insert(tmp, string.format(i18n.html, q.text_width, q.text_width, q.linfo1_pad, q.text_width, q.rinfo1_pad, q.text_width, q.text_width, q.text_width))
return mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(table.concat(tmp), 'style=";* *', 'style="'), '\n| *style="" *|', '\n|'), ' ?style=""', ''), ' ?colspan="1"', ''), '<div class="RMsi"></div>', ''), 'class="RM%+', 'class="RM_'), '(class="* RM)%+', '%1_')
end
local function getArgNums(prefix, args)
-- Copied from Module:Infobox on enwiki.
-- Returns a table containing the numbers of the arguments that exist
-- for the specified prefix. For example, if the prefix were 'data', and
-- 'data1', 'data2', and 'data5' existed, this would return {1, 2, 5}.
local nums = {}
for k, v in pairs(args) do
local num = tostring(k):match('^' .. prefix .. '(%d*)$')
if num then table.insert(nums, tonumber(num)) end
end
table.sort(nums)
return nums
end
local greatercontrast = require('Module:Color contrast')._greatercontrast
local rgb_black = '#252525' -- class .mw-body in Mediawiki:Common.css
p.infobox = makeInvokeFunction('_infobox')
function p._infobox(args) -- Creates a pretty box.
args.map1, args.tw, args, args, args = args.map1 or args.map, args.tw or args or args, args or args, args or args, args or args or args or args
local function map_prefix(x) return 'map'..x end
local mapnums, prefix = {}
if args and args ~= '' then
prefix = tonumber
for k, v in pairs(args) do
if type(k) == 'number' then table.insert(mapnums, k) end
end
else
prefix = map_prefix
mapnums = getArgNums('map', args)
table.sort(mapnums)
end
local classes = {}
args = args or args or args or '#27404E'
args = args or args or greatercontrast{args, '#FFF', rgb_black}
args.legend = args.legend or ''
local navbar = require('Module:Navbar').navbar
local navtable = {}
if args.navbar then
navtable = {args.navbar, mini = i18n.text.navbar_mini, text = i18n.text.navbar_text}
args.navbar = navbar(navtable)
else
args.navbar = ''
end
local result = ''
if args.inline then result = result..' \n' end
result = result..'{|'
args.collapse = args.collapse or args.collapsed
if args.inline or negative(args.collapsible) then
args.collapsible = '0'
else
table.insert(classes, 'collapsible')
if args.collapse then table.insert(classes, 'collapsed') end
end
args.float = args.float or 'right'
if args.float == 'right' then
args.margin = 'margin-left:1em;'
elseif args.float == 'left' then
args.margin = 'margin-right:1em;'
else
args.margin = ''
end
args.fontsize2 = 10000/88
if args.inline then
table.insert(classes, 'RMinline')
args.fontsize = 100
else
table.insert(classes, 'RMbox')
args.fontsize = 88 -- as above: CSS rule for .infobox in %
end
args.bg = args.bg or '#F9F9F9'
args.style = args.style or ''
result = result .. 'class="' .. table.concat(classes, ' ') .. '" cellspacing="0" cellpadding="0" style="float:' .. args.float .. ';clear:' .. args.float .. ';margin-top:0;margin-bottom:1em;' .. args.margin .. 'empty-cells:show;border-collapse:collapse;font-size:' .. args.fontsize .. '%;background:' .. args.bg .. ';' .. args.style .. '"'
args.title = args.title or ''
if args.inline or args.title == 'no' or args.title == '0' then
else
result = result .. '\n! style="color:' .. args .. ';background:' .. args .. ';text-align:center;padding:5px"|'
if args then
result = result .. '<div>'
else
if args.navbar ~= '' then
navtable.mini = true
navtable.brackets = true
navtable.style = 'float:left;margin-right:5px;white-space:nowrap'
navtable.fontstyle = 'font-size:'..args.fontsize2..'%;color:' .. args
args.navbar = navbar(navtable) .. '<div style="margin-left:55px">'
else
args.navbar = '<div>'
end
result = result .. args.navbar
end
result = result .. '<div style="white-space:nowrap;'
if args.collapsible == '0' and (args or args.navbar == '<div>') then
else
result = result .. 'margin-right:55px;'
if args or args.navbar == '<div>' then
result = result .. 'margin-left:55px;'
end
end
result = result .. 'font-size:'..args.fontsize2..'%">' .. args.title .. '</div></div>'
end
args.top = args.top or args
if args.top then
result = result .. '\n|-\n|style="padding:0px 5px;text-align:center;'..(args.topstyle or '')..'"|' .. args.top
end
result = result .. '\n|-\n|style="line-height:normal;padding:4px 5px"|'
if args.navbar ~= '' and args == '1' then
if not positive(args) and not negative(args) then navtable.mini = true; args.navbar = navbar(navtable) end
result = result .. '<div style="float:left;padding-right:5px">' .. args.navbar .. '</div>'
end
args.legend2 = mw.ustring.lower(args.legend)
if args.legend2 ~= 'no' and args.legend2 ~= '0' then
args.legend = i18n.text.legend or ((args.legend2 ~= '') and ('[['..args.legend) or i18n.text.legend.default)
args.legend = args.legend .. '|' .. (args or i18n.text.legend_text) .. ']]'
result = result .. '<div class="selfreference noprint" style="text-align:right;font-size:97%">' .. args.legend .. '</div>'
end
if args.inline then args.padding2 = '0px' else args.padding2 = '0px 6px' end
for k, v in ipairs(mapnums) do
if not mapnums then
if not args.inline then args.padding2 = '0px 6px 6px' end
end
args.ending = ''
if args then
args.header_margin = '0'
if k == 1 then args.border_header = 'border-bottom: 5px solid '..args.bg..';' else args.border_header = 'border-top: 5px solid '..args.bg..';border-bottom: 5px solid '..args.bg..';' end
if positive(args) then
args.header_margin = '0 55px'
args.ending = '\n|}'
if positive(args) or positive(args) then args.map_collapsed = ' mw-collapsed autocollapse' else args.map_collapsed = '' end
result = result..'\n|-\n|\n{|class="mw-collapsible'..args.map_collapsed..'" cellpadding="0" cellspacing="0" style="display:table;min-width:100%;margin:0 auto"'
end
if args.inline then args.header_style2 = ' style="line-height:normal"' else args.header_style2 = '' end
result = result..'\n|-'..args.header_style2..'\n!style="'..args.border_header..'padding:3px 5px;text-align:center;vertical-align:middle;color:'..rgb_black..';background:#EEEEEE" | <div style="margin:'..args.header_margin..';font-size:'..10000/args.fontsize..'%">'..args..'</div>'
args.border_top = ''
else
if k == 1 then args.border_top = '' else args.border_top = 'border-top: 5px solid '..args.bg..';' end
end
result = result .. '\n|-\n|style="'..args.border_top..'padding:' .. args.padding2 .. '"|\n{|class="nogrid routemap" style="font-size:'..(args.fontsize2 * .95)..'%"\n'..localroute(args, (args or args or args or args.tw or ''), args.bg, args.process)..'\n|}'..args.ending
end
args.bottom = args.bottom or args.footnote
if args.bottom then
if args.inline then args.padding2 = '6px' else args.padding2 = '0px' end
result = result .. '\n|-\n|style="line-height:normal;text-align:right;padding:' .. args.padding2 .. ' 5px 5px;'..(args.bottomstyle or args.footnotestyle or '')..'"|' .. args.bottom
if string.find(args.bottom, '&action=edit') then result = result .. (i18n or i18n.default) end
end
if args.navbar ~= '' and args == '2' then
if negative(args) or positive(args) then navtable.mini = true; args.navbar = navbar(navtable) end
if args.inline and not args.bottom then args.padding2 = '6px' else args.padding2 = '0px' end
result = result .. '\n|-\n|style="line-height:normal;padding:' .. args.padding2 .. ' 5px 3px;text-align:center"|' .. args.navbar
end
return result .. '\n|}'
end
local function base(t1,t2,link,stn,italic,it,it2,bold,align,style,bg1,bg2,line,fs1,fs2,lh,v1,swap,inp,bs)
--Creates an inline table with two rows of text. Can be used in any Routemap text cell.
--Implemented in the BSsplit, BSto, BSsrws and BScvt templates.
if not align then
if bs == 'cvt' then
align = 'right'
else
align = 'inherit'
end
end
style = style or ''
local result = ' <table cellspacing="0" cellpadding="0" class="RMsplit" style="text-align:'..align
if italic or it == 'all' then result = result..';font-style:italic' end
if bold then result = result..';font-weight:bold' end
local rowstart = '<tr><td style="text-align:inherit;padding:0;line-height:'
result = result..';'..style..'">'..rowstart..lh
if line then result = result..';border-bottom:1px solid gray' end
local bgpad = ';padding-left:.5em;padding-right:.5em'
local function bgtext(v)
return ';color:'..greatercontrast{v, '#FFF', rgb_black}
end
if bg1 then
result = result..bgpad..bgtext(bg1)..';background:'..bg1
elseif bg2 then
result = result..bgpad
end
if fs1 then result = result..';font-size:'..fs1 end
result = result..'">'
if not t1 or string.find(t1, '^%s*$') then
if not t2 then t2 = '' end
if string.find(t2, '<br ?/?>') == nil then t1 = ' ' end
end
if not t2 or string.find(t2, '^%s*$') then
if not t1 then t1 = '' end
if string.find(t1, '<br ?/?>') == nil then t2 = ' ' end
end
if bs == 'srws' then
if stn then
link = t1..' '..t2..' '..stn
else
link = t1..' '..t2..' railway station'
end
elseif bs == 'cvt' then
local split, floor, outp, v2, mult = mw.text.split, math.floor
local function trim(x)
return string.gsub(x, '%s', '')
end
local cvt = { -- conversion values
= 1.609344,
= 20.1168,
= 80,
= 1 / .9144,
= .9144,
= .3048,
}
local sf = { -- 10 ^ floor(log10(cvt) + .5); or 10 ^ floor(log10(cvt] * cvt) + .5) for dual-unit inputs. this corrects the accuracy of result so that it usually has same significant figures
= 1,
= 10,
= .01,
= 1,
= 1,
= .1,
}
if not inp then inp = 'mi' end
inp = string.lower(trim(inp))
if inp == 'ch' or inp == 'yd' or inp == 'ft' then -- output unit
outp = 'm'
elseif inp == 'm' then
outp = 'yd'
else
if inp ~= 'mi;ch' then inp = 'mi' end
outp = 'km'
end
local pos = string.find(v1, '%.')
if not pos then
mult = 1
else
mult = 10 ^ (string.len(v1) - pos)
end
local inps = string.find(inp, ';')
if inps then
inps = split(inp, ';')
if swap then
t1 = v1..' '..outp
v1 = tonumber(v1)
t2 = floor(v1 / cvt])..' '..inps..' '..floor(v1 % cvt] / cvt] * cvt * mult * sf + .5) / mult / sf..' '..inps
else
v1 = split(trim(v1), ';')
t1 = v1..' '..inps..' '..v1..' '..inps
t2 = floor((tonumber(v1) * cvt] + tonumber(v1) * cvt] / cvt) * mult / sf + .5) / mult * sf..' '..outp
end
else
if swap then
v2 = floor(tonumber(v1) / cvt * mult * sf + .5) / mult / sf
inp, outp = outp, inp
else
v2 = floor(tonumber(v1) * cvt * mult / sf + .5) / mult * sf
end
t1 = v1..' '..inp
t2 = v2..' '..outp
end
end
if t1 then
if link then
result = result..']'
else
result = result..t1
end
end
local rowend = '</td></tr>'
result = result..rowend..rowstart..lh
if bg2 then
result = result..bgpad..bgtext(bg2)..';background:'..bg2
elseif bg1 then
result = result..bgpad
end
if fs2 then result = result..';font-size:'..fs2 end
if (it ~= 'off' and bs == 'to') or it2 == 'italic' then
result = result..';font-style:italic'
elseif it == 'off' then
result = result..';font-style:normal'
end
result = result..'">'
if t2 then
if link then
result = result..']'
else
result = result..t2
end
end
result = result..rowend..'</table> '
if bs == 'to' or bs == 'srws' then
if t1 == ' ' or t2 == ' ' then result = result..(i18n or i18n.default) end
end
if string.find(t1, '<br ?/?>') ~= nil or string.find(t2, '<br ?/?>') ~= nil then result = result..(i18n or i18n.default) end
if bs == 'split' then
if link and t1 and t2 then
if string.find(link, '^'..t1..' '..t2..' ') then result = result..(i18n or i18n.default) end
end
end
return result
end
p.BSto = makeInvokeFunction('_BSto')
function p._BSto(args)
args = args or args.L
args = args or args.it or args.i
args = args or args.b
return base(args,args,args,nil,nil,args,nil,args,args.align,args.style,args.bg1,args.bg2,args.line,'105%','inherit','.9',nil,nil,nil,'to')
end
p.BSsplit = makeInvokeFunction('_BSsplit')
function p._BSsplit(args)
args = args or args.L
args = args or args.it or args.i
args = args or args.b
return base(args,args,args,nil,args,nil,nil,args,args.align,args.style,args.bg1,args.bg2,args.line,'inherit','inherit','.9',nil,nil,nil,'split')
end
p.BSsrws = makeInvokeFunction('_BSsrws')
function p._BSsrws(args)
args = args or args.S
args = args or args.it or args.i
args = args or args.b
return base(args,args,nil,args,args,nil,nil,args,args.align,args.style,args.bg1,args.bg2,args.line,'inherit','inherit','.9',nil,nil,nil,'srws')
end
p.BScvt = makeInvokeFunction('_BScvt')
function p._BScvt(args)
return base(nil,nil,nil,nil,nil,nil,args.alt,nil,args.align,args.style,args.bg1,args.bg2,args.line,'inherit','inherit','.9',args,args,args,'cvt')
end
p.rmri = makeInvokeFunction('_rmri')
function p._rmri(args)--[[
Displays a blue arrow pointing in one of eight directions.
Implemented in the RoutemapRouteIcon template.
]]
local directions, result = {
= {'u', 'up'},
= {'d', 'dn', 'down'},
= {'l', 'left'},
= {'r', 'right'},
= {'ur', 'ne', 'c1', 'upperright'},
= {'lr', 'se', 'c2', 'lowerright'},
= {'ll', 'sw', 'c3', 'lowerleft'},
= {'ul', 'nw', 'c4', 'upperleft'},
}
local d, link, size = args, args, args
if not d then
if args ~= ' ' then d, link, size = args, args, 's' end
end
for k, v in pairs(directions) do
for _, name in ipairs(v) do
if d:lower() == name then
if size == 's' then
size = '7'
elseif not size then
size = '10'
end
if not link then link = '' end
result = ']'
end
end
end
if not result then
return '<span style="color:#f00">Invalid ] arrow value "<span style="font-style:italic">'..d..'</span>".</span>'..(i18n or i18n.default)
else
return result
end
end
p.rmr = makeInvokeFunction('_rmr')
function p._rmr(args)--[[
Displays text between two blue arrows (or to the left/right side of one).
Text can be split with an en dash if entered in both first and second numbered parameters.
Implemented in the RoutemapRoute template.
]]
args.l = args.l or args.Licon or args.licon or args.L
args.r = args.r or args.Ricon or args.ricon or args.R
if args.l then args.l = p._rmri{args.l,args.llink,(args.lsize or args.size),' '}..' ' else args.l = '' end
if args.r then args.r = ' '..p._rmri{args.r,args.rlink,(args.rsize or args.size),' '} else args.r = '' end
if args then
if args then args = args..' – '..args end
else
args = args or ''
end
if args == '' or args.enclosed == 'no' then
args.b1, args.b2 = '', ''
else
args.b1, args.b2 = '(', ')'
end
return args.b1..args.l..args..args.r..args.b2
end
function p.BSrow(frame)
local args = getArgs(frame, {
parentOnly = true,
removeBlanks = false,
})
return p._BSrow(args)
end
function p._BSrow(args)--[[
Creates Routemap syntax for a diagram row based on parameters.
Implemented in the RDTr template.
]]
args.n = tonumber(args.n or '')
if not args.n then
local icontotal = getArgNums('', args)
table.sort(icontotal)
args.n = icontotal or 1
end
local count, icons, overlaps, overlapCalc = tonumber(args) or 1, {}, {}, math.log10(args.n)
local text = (args.text and '*') or ''
if overlapCalc == math.floor(overlapCalc) then overlapCalc = 10^(overlapCalc) else overlapCalc = 10^(math.floor(overlapCalc) + 1) end
while count <= args.n do
local cellparams, overlapn = {}, (string.match(count/overlapCalc, '%.(0+)') or '')..count
table.insert(icons, (text..(args or '')))
if args then
local iconparams, overlapparams, overlapt = {}, {}, {}
for k, v in pairs({bg = (args or args or args), color = (args or args), b = (args or args), i = (args or args or args), align = args, fontsize = args, abbr = args, style = args}) do
if v then table.insert(iconparams, k..'='..v) end
end
if iconparams then icons = icons..'__'..table.concat(iconparams, ',') end
for k, v in pairs({bg = (args or args or args), color = (args or args), b = (args or args), i = (args or args or args), align = args, fontsize = args, abbr = args, style = args}) do
if v then table.insert(overlapparams, k..'='..v) end
end
if overlapparams then args = args..'__'..table.concat(overlapparams, ',') end
overlaps = getArgNums('O'..overlapn, args) or {}
table.sort(overlaps)
if overlaps then
for i, v in ipairs(overlaps) do
overlapparams = {}
for k, v2 in pairs({bg = (args or args or args), color = (args or args), b = (args or args), i = (args or args or args), align = args, fontsize = args, abbr = args, style = args}) do
if v2 then table.insert(overlapparams, k..'='..v2) end
end
if overlapparams then args = args..'__'..table.concat(overlapparams, ',') end
table.insert(overlapt, text..args)
end
overlaps = '!~'..text..args..'!~'..table.concat(overlapt, '!~')
else
overlaps = '!~'..text..args
end
icons = icons..overlaps
else
if args then table.insert(cellparams, 'abbr='..args) end
end
if args then icons = icons..'!@'..args end
for k, v in pairs({bg = (args or args or args), color = (args or args), b = (args or args), i = (args or args or args), align = args, fontsize = args, style = args}) do
if v then table.insert(cellparams, k..'='..v) end
end
if cellparams then icons = icons..'!_'..table.concat(cellparams, ',') end
count = count + 1
end
local row, rowparams, left, right = table.concat(icons, '\\'), {}
for k, v in pairs({bg = (args.bg or args.background or args.bgcolor), color = (args.color or args.colour), b = (args.b or args.bold), i = (args.i or args.it or args.italic), align = args.align, fontsize = args.fontsize, style = args.style}) do
if v then table.insert(rowparams, k..'='..v) end
end
if rowparams then args.R5 = table.concat(rowparams, ',') end
for i, v in ipairs({'R1', 'R2', 'R3', 'R4', 'R5', 'L1', 'L2', 'L3', 'L4'}) do
if not args or string.find(args, '^%s*$') then args = nil end
end
if args.R5 then
right = {(args.R1 or ' '), (args.R2 or ' '), (args.R3 or ' '), (args.R4 or ' '), args.R5}
elseif args.R4 then
right = {(args.R1 or ' '), (args.R2 or ' '), (args.R3 or ' '), args.R4}
elseif args.R3 then
right = {(args.R1 or ' '), (args.R2 or ' '), args.R3}
elseif args.R1 then
right = {args.R1, (args.R2 or '')}
elseif args.R2 then
right = {args.R2}
end
if right then row = row..'~~'..table.concat(right, '~~') end
if args.L4 then
left = {args.L4, (args.L3 or ' '), (args.L2 or ' '), (args.L1 or '')}
elseif args.L3 then
left = {args.L3, (args.L2 or ' '), (args.L1 or '')}
elseif args.L1 then
left = {(args.L2 or ''), args.L1}
elseif args.L2 then
left = {args.L2}
end
if left then row = table.concat(left, '~~')..'! !'..row end
return row
end
function p.BSrow_lite(frame)
local args = getArgs(frame, {
removeBlanks = false,
})
return p._BSrow_lite(args)
end
function p._BSrow_lite(args)--[[
Creates Routemap syntax for a diagram row based on parameters.
Intended to be used to substitute legacy templates.
Note that for compatibility the link and sidebar parameter names are different.
]]
args.n = tonumber(args.n or '')
if not args.n then
local icontotal = getArgNums('', args)
table.sort(icontotal)
args.n = icontotal or 1
end
local count, icons, overlaps, overlapCalc = tonumber(args) or 1, {}, {}, math.log10(args.n)
local text = (args.text and '*') or ''
if overlapCalc == math.floor(overlapCalc) then overlapCalc = 10^(overlapCalc) else overlapCalc = 10^(math.floor(overlapCalc) + 1) end
while count <= args.n do
local cellparams, overlapn = {}, (string.match(count/overlapCalc, '%.(0+)') or '')..count
table.insert(icons, (text..(args or '')))
if args then
local overlapt = {}
overlaps = getArgNums('O'..overlapn, args) or {}
table.sort(overlaps)
if overlaps then
for i, v in ipairs(overlaps) do table.insert(overlapt, text..args) end
overlaps = '!~'..text..args..'!~'..table.concat(overlapt, '!~')
else
overlaps = '!~'..text..args
end
icons = icons..overlaps
end
if args then icons = icons..'!@'..args end
count = count + 1
end
local row, rowparams, left, right = table.concat(icons, '\\'), {}
for k, v in pairs({bg = (args.bg or args.background or args.bgcolor), style = args.style}) do
if v then table.insert(rowparams, k..'='..v) end
end
if rowparams then args.r5 = table.concat(rowparams, ',') end
for i, v in ipairs({'r1', 'r2', 'r3', 'r4', 'r5', 'l1', 'l2', 'l3', 'l4'}) do
if not args or string.find(args, '^%s*$') then args = nil end
end
if args.r5 then
right = {(args.r1 or ' '), (args.r2 or ' '), (args.r3 or ' '), (args.r4 or ' '), args.r5}
elseif args.r4 then
right = {(args.r1 or ' '), (args.r2 or ' '), (args.r3 or ' '), args.r4}
elseif args.r3 then
right = {(args.r1 or ' '), (args.r2 or ' '), args.r3}
elseif args.r1 then
right = {args.r1, (args.r2 or '')}
elseif args.r2 then
right = {args.r2}
end
if right then row = row..'~~'..table.concat(right, '~~') end
if args.l4 then
left = {args.l4, (args.l3 or ' '), (args.l2 or ' '), (args.l1 or '')}
elseif args.l3 then
left = {args.l3, (args.l2 or ' '), (args.l1 or '')}
elseif args.l1 then
left = {(args.l2 or ''), args.l1}
elseif args.l2 then
left = {args.l2}
end
if left then row = table.concat(left, '~~')..'! !'..row end
return row
end
local function pre_block(text)
-- Pre tags returned by a module do not act like wikitext <pre>...</pre>.
return '<pre>' ..
mw.text.nowiki(text) ..
(text:sub(-1) == '\n' and '' or '\n') ..
'</pre>\n'
end
function p.convertbs(frame)--[[
Converts a legacy route diagram into Routemap format.
Code to be used is displayed in preview mode or after saving the page, above the original code.
{{#invoke:Routemap|convertbs|<nowiki>
(Original diagram)
</nowiki>}}
]]
local org = mw.text.unstripNoWiki(frame.args or 'Paste legacy RDT markup between nowiki tags')
local res = org
res = string.gsub(res, '{{%-?map', '{{Routemap') -- "%-" is an escape for hyphen which is used as "between" in pattern.
res = string.gsub(res, '{|%s?{{ailway line header}}', '{{Routemap')
res = string.gsub(res, '{{%-header%d?|', '{{safesubst:BS-header/safesubst|') -- "%d?" means optional digit in case use of variant template like BS-header3.
res = string.gsub(res, '{{%-table%d?}}', '|map =')
res = string.gsub(res, '{{(%d?)(%d?)|', '{{safesubst:BS%1%2/safesubst|')
res = string.gsub(res, '{{(%d?)(%d?)%-replace|', '!replace{{safesubst:BS%1%2/safesubst|')
res = string.gsub(res, '{{(%d?)(%d?)%-startCollapsible|', '-startCollapsible-collapsed\n{{safesubst:BS%1%2/safesubst|')
res = string.gsub(res, '{{(%d?)(%d?)%-sc|', '-startCollapsible-collapsed\n{{safesubst:BS%1%2/safesubst|')
res = string.gsub(res, '{{(%d?)(%d?)%text|', '{{safesubst:BS%1%2text/safesubst|')
res = string.gsub(res, '{{(%d?)(%d?)%-2|', '{{safesubst:BS%1%2-2/safesubst|')
res = string.gsub(res, '{{(%d?)(%d?)%-2replace|', '!replace{{safesubst:BS%1%2-2|')
res = string.gsub(res, '{{(%d?)(%d?)%-2sc|', '-startCollapsible-collapsed\n{{safesubst:BS%1%2-2|')
res = string.gsub(res, '{{!}}}', '-endCollapsible-')
res = string.gsub(res, '{{nd}}', '-endCollapsible-')
res = string.gsub(res, '|}\n?|}', '}}') -- Replace ending of Railway line header map setup.
res = string.gsub(res, '{{%-colspan}}\n{{safesubst', '{{safesubst') -- BS-colspan is unnecessary and would cause error in Routemap.
res = string.gsub(res, '{{%-colspan}}\n%-%-%-%-', '-colspan-2\n----')
res = string.gsub(res, '<', '<')
res = string.gsub(res, '>', '>')
if string.find(res, '!replace') or string.find(res, '|%s*bg%s*=') then
local restable = mw.text.split(res, '\n')
for i, v in ipairs(restable) do
if string.find(v, '!replace') then
restable = string.gsub(restable, '!replace', '')
restable = string.gsub(restable, 'collapsed', 'collapsed-replace')
end
if (string.find(v, '|%s*bg%s*=%s*#?+') or string.find(v, '|%s*bg%s*=%s*#?{{+}}%s*|') or string.find(v, '|%s*bg%s*=%s*#?{{+}}%s*}}')) and string.find(restable, '^-startCollapsible') then
local bg = string.match(v, '|%s*bg%s*=%s*(#?+)') or string.find(v, '|%s*bg%s*=%s*(#?{{+}})%s*|') or string.find(v, '|%s*bg%s*=%s*(#?{{+}})%s*}}')
restable = string.gsub(restable, '|%s*bg%s*=%s*'..bg, '')
restable = string.gsub(restable, '%-?$', '--bg=')..bg
if string.find(restable, '!replace') then
restable = string.gsub(restable, '!replace', '')
restable = string.gsub(restable, 'collapsed%-', 'collapsed-replace')
if (string.find(restable, '|%s*bg%s*=%s*#?+') or string.find(restable, '|%s*bg%s*=%s*#?{{+}}%s*|') or string.find(restable, '|%s*bg%s*=%s*#?{{+}}%s*}}')) then
local bg2 = string.match(restable, '|%s*bg%s*=%s*(#?+)') or string.find(restable, '|%s*bg%s*=%s*(#?{{+}})%s*|') or string.find(restable, '|%s*bg%s*=%s*(#?{{+}})%s*}}')
if bg2 == bg then restable = string.gsub(restable, '|%s*bg%s*=%s*'..bg2, '') end
end
end
end
end
res = table.concat(restable, '\n')
end
return "\n'''Safe substitution''':\n" .. pre_block(res) .. "'''''Original''''':\n" .. pre_block(org)
end
return p