This Lua module is used on approximately 75,000 pages and changes may be widely noticed. Test changes in the module's /sandbox or /testcases subpages, or in your own module sandbox. Consider discussing changes on the talk page before implementing them. |
This module depends on the following other modules: |
This module is subject to page protection. It is a highly visible module in use by a very large number of pages, or is substituted very frequently. Because vandalism or mistakes would affect many pages, and even trivial editing might cause substantial load on the servers, it is protected from editing. |
Pages related to |
Module:Adjacent stations |
---|
( talk | sandbox | sub-pages) |
{{ Infobox station}} |
( talk | sandbox | testcases) |
{{ Station link}} |
( talk | sandbox | testcases) |
{{ Station icon link}} |
( talk | sandbox | testcases) |
{{ Rail color}} |
( talk | sandbox | testcases) |
{{ Line link}} |
( talk | sandbox | testcases) |
{{ Short line link}} |
( talk | sandbox | testcases) |
{{ Rail icon}} |
( talk | sandbox | testcases) |
{{ Rail color box}} |
( talk | sandbox | testcases) |
{{ Adjacent stations}} |
( talk | sandbox | testcases) |
{{ Line terminus link}} |
( talk | sandbox | testcases) |
This module implements {{
Adjacent stations}}, {{
Rail icon}}, {{
Rail color box}}, {{
Line link}}, {{
Station link}} and {{
Rail color}}. Please see those templates' pages for documentation on how to use those templates. (Instructions for the convert
function of this module are in the {{
Adjacent stations}} documentation.)
The aforementioned templates rely on data stored in subpages for this module (
list). For example, {{
Rail icon|MTR}}
generates
using
Module:Adjacent stations/MTR.
It is possible to create and edit data by following existing examples, but having some knowledge of Lua helps prevent mistakes. If you have programmed or used Lua before, you may like to skip the next subsection.
true
or false
."This is a string"
).0.5
or 42
.{}
in the code.["key"] = value
; each key–value pair is separated by a comma. All keys used here are strings or numbers.{"text", "more text"}
is equivalent to {[1] = "text", [2] = "more text"}
.local variable_name = "value".
return variable_name
) causes a function to exit and reports the value of variable_name
. The "function" here is the code in the main module calling the subpage, and the variable_name
should be the data table.Two modules are demonstrated below:
Blank | local p = {
"system title" = "",
"system icon" = "",
"station format" = {
"",
"" = "",
},
"lines" = {
"" = {
"title" = "",
"color" = "",
"left terminus" = "",
"right terminus" = "",
},
},
}
return p
|
Example | local x = "%1 light rail station"
local p = {
"system title" = "[[Kaohsiung Metro]]",
"system icon" = "[[File:Kaohsiung Mass Rapid Transit Logo(Logo Only).svg|18px|link=Kaohsiung Rapid Transit]]",
"rail box format" = "title",
"station format" = {
"%1 metro station",
"Central Park" = "Central Park metro station (Taiwan)",
"Ciaotou" = "Ciaotou Station (Kaohsiung Metro)",
"Kaohsiung Main Station" = "%1",
"Zuoying" = "%1 HSR station",
-- Circular light rail
"Lizihnei" = x,
"Kaisyuan Rueitian" = x,
"Cianjhen Star" = x,
"Kaisyuan Jhonghua" = x,
"Dream Mall" = x,
"Commerce and Trade Park" = x,
"Software Technology Park" = x,
"Kaohsiung Exhibition Center" = x,
"Cruise Terminal" = x,
"Glory Pier" = x,
"Love Pier" = x,
"Dayi Pier-2" = x,
"Penglai Pier-2" = x,
"Hamasen" = x
},
"lines" = {
"_default" = {
"title" = "[[%1 line (Kaohsiung Metro)|%1 line]]"
},
"Red" = {
"color" = "e20b65",
"icon" = "[[File:Kaohsiung MRT Red Line.svg|20px|link=Red line (Kaohsiung Metro)]]",
"left terminus" = "Gangshan South",
"right terminus" = "Siaogang"
},
"Orange" = {
"color" = "faa73f",
"icon" = "[[File:Kaohsiung Metro Orange Line.svg|20px|link=Orange line (Kaohsiung Metro)]]",
"left terminus" = "Sizihwan",
"right terminus" = "Daliao"
},
"Circular" = {
"title" = "[[Circular light rail]]",
"short name" = "Circular line",
"color" = "7cbd52",
"icon" = "[[File:Kaohsiung LRT Circular Line.svg|20px|link=Circular light rail]]",
"circular" = 1,
"left terminus" = "outer loop / anticlockwise",
"right terminus" = "inner loop / clockwise"
},
-- Future lines
"Yellow" = {
"color" = "ffc100",
"icon" = "[[File:Kaohsiung Rapid Transit Yellow Line.svg|20px|link=Yellow line (Kaohsiung Metro)]]",
"left terminus" = {"Cruise Terminal", "Cianjhen Senior High School"},
"right terminus" = "Dipu"
},
-- Proposed
"Yanchao" = {
"title" = "[[Kaohsiung Metro#All projects|Yanchao line]]",
"color" = "c100ff"
},
"Youchang" = {
"title" = "[[Kaohsiung Metro#All projects|Youchang line]]",
"color" = "008583"
},
"Fongshan" = {
"title" = "[[Kaohsiung Metro#All projects|Fongshan line]]",
"color" = "007fff"
},
"Green" = {
"title" = "[[Kaohsiung Metro#All projects|Green line]]",
"color" = "50cb00"
},
"Foguangshan" = {
"title" = "[[Kaohsiung Metro#All projects|Foguangshan line]]",
"color" = "aa34c0"
},
"Cijin" = {
"title" = "[[Kaohsiung Metro#All projects|Cijin line]]",
"color" = "e10a65"
},
},
"aliases" = {
"circular" = "Circular",
"c" = "Circular",
"orange" = "Orange",
"o" = "Orange",
"red" = "Red",
"r" = "Red",
"yellow" = "Yellow",
"y" = "Yellow"
}
}
return p
|
The example module is Module:Adjacent stations/Kaohsiung Rapid Transit.
Below is Module:Adjacent stations/Taiwan High Speed Rail:
local x = "%1 station"
local p = {
"system title" = "[[Taiwan High Speed Rail]]",
"system icon" = "[[File:Taiwan High Speed Rail Logo(Log Only).svg|18px|link=Taiwan High Speed Rail|alt=Taiwan High Speed Rail]]",
"system color" = "c35617",
"name format" = "color: #FFFFFF; background-color: #C35617;",
"station format" = {
"%1 HSR station",
"Taipei" = "Taipei Main Station",
"Nangang" = x,
"Banqiao" = x
},
"lines" = {
"_default" = {
"title" = "[[Taiwan High Speed Rail|THSR]]",
"color" = "c35617",
"left terminus" = "Nangang",
"right terminus" = "Zuoying"
}
}
}
return p
["_default"]
. The title and colour of this line is used for all lines unless overridden. Parameters are used in the absence of a specified line=
in transclusion.If not specified, all keys and values are strings.
Parameter | Type | Used in {{ Adjacent stations}} | Description |
---|---|---|---|
["lang"]
|
String | Yes | Values are "en-US" and "en-GB" . If not set, "en-GB" is assumed.
|
["system title"]
|
String | Yes | Text in the middle cell of the header. |
["system icon"]
|
String | Yes | Image used in the middle cell of the {{ Adjacent stations}} header and by {{ Rail icon}}. |
["system icon format"]
|
String | No | Icon type, used by {{
Rail icon}}. If specified and not "image" , the value is passed to the function that implements {{
Rail color box}}.
|
["system color"]
|
String | No | RGB hex triplet (three or six characters, like "BE2D2C" or "039" ). Can be called by using only one parameter in {{
Rail color}}.
|
["header stop noun"]
|
String | Yes | The noun after 'preceding' and 'following' in the left and right header cells. Default value is "station" .
|
["name format"]
|
String | No | CSS for the header of {{
Infobox station}} and anything else using the style function with |1=header . Values can be strings or nested tables, with the first level being for the line (whatever's in |style2= of {{
Infobox station}}). The second level is currently unused. The first entry in a nested table with no key (i.e. with key 1 ) is the default.
|
["header background color"]
|
String | No | RGB hex triplet for {{
Infobox station}} subheaders and anything else using the style function with |1=subheader . By default, it is a light gray. Values can be strings or nested tables, like those for "name format" .
|
["header text color"]
|
String | No | RGB hex triplet for {{
Infobox station}} subheaders and anything else using the style function with |1=subheader . By default, it is calculated based on the header background color. Values can be strings or nested tables, like those for ["name format"] .
|
["station format"]
|
Table or string | Yes | Table containing station format strings. The first entry without a specified key (i.e. with the key being the number 1 ) is the default, and all other entries must have keys corresponding to the input. Format strings without wikilink brackets are converted to links, with the input (usually the station name) used as the displayed text. Tables can be nested within this table to indicate options based on the line and line type passed to this template.
|
["lines"]
|
Table | Yes | Data table containing line tables. |
["aliases"]
|
Table | Yes | Table containing aliases (as table keys) for lines (as values). All keys are lowercase, as the input is treated as case-insensitive by being lower-cased. |
Parameter | Type | Used in {{ Adjacent stations}} | Description |
---|---|---|---|
[1]
|
String | Yes | Default format. |
["non-default station name"]
|
String or table | Yes | Format for a non-default station, or line-specific format table. |
Parameter | Type | Used in {{ Adjacent stations}} | Description |
---|---|---|---|
[1]
|
String | Yes | Default format. |
["line name"]
|
String or table | Yes | Format for a non-default station, or type-specific format table. |
Parameter | Type | Used in {{ Adjacent stations}} | Description |
---|---|---|---|
[1]
|
String | Yes | Default format. |
["type name"]
|
String | Yes | Format for a non-default station. |
A virtual line named ["_default"]
can be added to set default values for all lines. Currently, this is available for three parameters.
Parameter | Type | Used in {{ Adjacent stations}} | Description |
---|---|---|---|
["title"]
|
String | Yes | The text displayed in the middle cell, typically a link to the line's article. If not specified, then the data in ["_default"] is used (%1 in the default value is replaced by the input after alias replacement).
|
["short name"]
|
String | No | Abbreviated line name used by {{ Rail color box}} and {{ Short line link}}. |
["icon"]
|
String | No | Image used by {{
Rail icon}}. If not specified, then the data in ["_default"] is used (%1 in the default value is replaced by the input after alias replacement).
|
["icon format"]
|
String | No | Icon type used by {{
Rail icon}}. If specified and not "image" , the value is passed to the function that implements {{
Rail color box}}.
|
["color"]
|
String | Yes | RGB hex triplet. Lines fall back to the ["_default"] colour (if any) or the system's colour if they themselves do not have one; types fall back to the line's colour (if any), to the ["_default"] colour (if any) or to the system's colour. This colour is used in the second and fourth columns of {{
Adjacent stations}}, and by {{
Rail color box}} and {{
Rail icon}} as the emphasised colour. By default, if a type and its line both have a colour, then the line's colour will be treated as the background colour (see next section) for the line name in the middle cell. This can be turned off by setting the type's background colour to "" or "transparent" .
|
["background color"]
|
String | Yes | RGB hex triplet (three or six characters). This colour is optional and is only displayed behind the line name in the middle cell. The module adds transparency so that all text displayed over the background is legible. |
["border color"]
|
String | No | RGB hex triplet used by {{ Rail color box}}. |
["text color"]
|
String | No | RGB hex triplet used by {{ Rail color box}}. |
["left terminus"]
|
String | Yes | The station which is usually the left terminus of the line. If there are multiple stations by default, the value should be a table containing numbered values (e.g. ["left terminus"] = {"Chesham", "Amersham"} ). The key ["via"] in that table can be used to append 'via' and the value's station link.
|
["right terminus"]
|
String | Yes | The station which is usually the right terminus of the line; behaves like ["left terminus"] .
|
["note-mid"]
|
String | Yes | Default small text below line and type names. Overridden by |note-mid= in transclusion.
|
["circular"]
|
Boolean | Yes | If the value is true then the termini will display without 'toward'/'towards'. May be overridden by type.
|
["oneway-left"]
|
Boolean | Yes | If the value is true then 'One-way operation' will display instead of the left terminus.
|
["oneway-right"]
|
Boolean | Yes | Right counterpart of oneway-left. |
["types"]
|
Table | Yes | Table containing the line type tables. |
Parameter | Type | Used in {{ Adjacent stations}} | Description |
---|---|---|---|
["title"]
|
String | Yes | The name of the line type. In {{
Adjacent stations}}, this is displayed as normal-sized text below the line name in the middle cell; in {{
Rail color box}}, for some options this is displayed after the line name, separated from it by a spaced
en dash (this is also used for the nonstop text). To avoid displaying a type name, set this to "" .
|
["short name"]
|
String | No | Abbreviated line name used by {{ Rail color box}} and {{ Short line link}}. |
["icon"]
|
String | No | Image used by {{ Rail icon}}. |
["icon format"]
|
String | No | Icon type used by {{
Rail icon}}. If specified and not "image" , the value is passed to the function that implements {{
Rail color box}}.
|
["color"]
|
String | Yes | RGB hex triplet. Lines fall back to the ["_default"] colour (if any) or the system's colour if they themselves do not have one; types fall back to the line's colour (if any), to the ["_default"] colour (if any) or to the system's colour. This colour is used in the second and fourth columns of {{
Adjacent stations}}, and by {{
Rail color box}} and {{
Rail icon}} as the emphasised colour. By default, if a type and its line both have a colour, then the line's colour will be treated as the background colour (see next section) for the line name in the middle cell. This can be turned off by setting the type's background colour to "" or "transparent" .
|
["background color"]
|
String | Yes | RGB hex triplet (three or six characters). This colour is optional and is only displayed behind the line name in the middle cell. The module adds transparency so that all text displayed over the background is legible. |
["border color"]
|
String | No | RGB hex triplet used by {{ Rail color box}}. |
["text color"]
|
String | No | RGB hex triplet used by {{ Rail color box}}. |
["left terminus"]
|
String | Yes | The station which is usually the left terminus of the line. Overrides line terminus. If there are multiple stations by default, the value should be a table containing numbered values (e.g. ["left terminus"] = {"Chesham", "Amersham"} ). The key ["via"] in that table can be used to append 'via' and the value's station link.
|
["right terminus"]
|
String | Yes | The station which is usually the right terminus of the line; behaves like ["left terminus"] .
|
["note-mid"]
|
String | Yes | Default small text below line and type names. Overridden by |note-mid= in transclusion.
|
["circular"]
|
Boolean | Yes | If the value is true then the termini will display without 'toward'/'towards'.
|
Station links are generated using the station format
part of the data module. Each data module defines a default case and then exceptions, if necessary. Station format
is an array, similar to a switch with cases. Take
Module:Adjacent stations/Incheon Subway, shown below:
local incheon = "%1 station (Incheon)"
local n = "font-size: 160%; font-family:sans-serif; font-weight: bolder; color: #FFFFFF; padding: 0.4em 4px; background-color: #"
local colors = {
"1" = "8cadcb",
"2" = "f06a00",
"3" = "777777",
}
local p = {
"system title" = "[[Incheon Subway]]",
"system icon" = "",
"name format" = {
"1" = n .. colors"1"],
"2" = n .. colors"2"],
"3" = n .. colors"3"],
},
"header background color" = colors,
"header text color" = "ffffff",
"station format" = {
"%1 station",
"Arts Center" = incheon,
"Central Park" = incheon,
"Gyeongin National University of Education" = "[[Gyeongin National University of Education station|Gyeongin Nat'l Univ. of Education]]",
"Mansu" = incheon,
"Seongnam" = incheon,
},
"lines" = {
"1" = {
"title" = "[[Incheon Subway Line 1|Incheon Line 1]]",
"color" = colors"1"],
"text color" = "FFFFFF",
"icon" = "[[File:Incheon Metro Line 1.svg|16px|link=Incheon Subway Line 1]]",
"left terminus" = "Gyeyang",
"right terminus" = "Songdo Moonlight Festival Park",
},
"2" = {
"title" = "[[Incheon Subway Line 2|Incheon Line 2]]",
"color" = colors"2"],
"text color" = "FFFFFF",
"icon" = "[[File:Incheon Metro Line 2.svg|16px|link=Incheon Subway Line 2]]",
"left terminus" = "Geomdan Oryu",
"right terminus" = "Unyeon",
},
"3" = {
"title" = "[[Incheon Subway Line 3|Incheon Line 3]]",
"color" = colors"3"],
"text color" = "FFFFFF",
}
}
}
return p
The default case is "%1 station"
, listed first. The "%1" expands to whatever the passed name of the station is. "Bakchon" becomes
Bakchon station. There are several exceptions. The two usual reasons for exceptions are disambiguation or presenting a name in a non-standard way. In this case, the
Incheon Subway serves three stations whose names are disambiguated:
Arts Center station (Incheon),
Central Park station (Incheon), and
Mansu station (Incheon). This is handled by specifying a key for each station and supplying a different format. Since all three are disambiguated the same way, you can define a local variable at the top of the module:
local incheon = "%1 station (Incheon)"
This can then be used with the exceptions:
"Arts Center" = incheon,
Were it written out, it would look like this:
"Arts Center" = "%1 station (Incheon)"
Suggestions are welcomed on the talk page.
require('strict')
local p = {}
local lang = 'en-GB' -- local default language
-- Below these comments: Internationalization table
-- How to translate this module (for languages without variants):
-- • Characters inside single and double quotation marks are called strings.
-- The strings in this i18n table are used as output.
-- • Strings within square brackets are keys.
-- • Strings are concatenated (joined) with two dots.
-- • Set the string after «local lang =» to your language's code.
-- Change the first key after "i18n" (usually "en-GB") to the same thing.
-- • For each string which is not inside a function, translate it directly.
-- • Strings with keys named "format" are Lua regular expressions.
-- «()» is a match; «.+» means all characters; «%s+» means all spaces.
-- • For each string which is concatenated to the variable «var»,
-- translate the phrase assuming that «var» will be a noun.
-- • Remove any unnecessary translations.
local i18n = require("Module:Adjacent stations/i18n")
local function getData(system, verify)
if verify then
local title = mw.title.new('Module:Adjacent stations/' .. system -- .. '/sandbox'
)
if not (title and title.exists) then return nil end
end
return require('Module:Adjacent stations/' .. system -- .. '/sandbox'
)
end
local function getLine(data, lineN)
if lineN then
if data'aliases' then
lineN = data'aliases'][mw.ustring.lower(lineN)] or lineN
end
local default = data'lines']['_default' or {}
local line = data'lines'][lineN or {}
for k, v in pairs(default) do
if v then linek = linek or v end
end
line'title' = line'title' and mw.ustring.gsub(line'title'], '%%1', lineN)
return line, lineN
end
end
local function getColor(data, system, line, Type, frame)
if system then
if line then return frame:expandTemplate{ title = system .. ' color', args = {line, 'branch' = Type} } end
return frame:expandTemplate{ title = system .. ' color' }
else
line = (getLine(data, line))
local default = data'lines']['_default'
if line or default then
default = default or {}
if not line then line = mw.clone(default) end
local color = line'color' or line'background color' or default'color' or default'background color' or data'system color'
local Type_value = Type and line'types' and (line'types'][Type and line'types'][Type]['color'])
if Type_value then color = Type_value end
return color
end
return (default and (default'color' or default'background color']) or data'system color' or '')
end
end
local lineN, typeN
local function somethingMissing(name, key, formats)
local formatKeys = {}
for k in pairs(formats) do
table.insert(formatKeys, k)
end
return name .. ' was "' .. key .. '" but neither an entry for it nor a default was found. Choices were: ' .. table.concat(formatKeys, ', ')
end
local function getStation(station, _Format)
if type(_Format) == 'table' then
local lineNformats = _Format
_Format = lineNformatslineN or lineNformats1
if not _Format then
error(somethingMissing('lineN', lineN, lineNformats))
elseif type(_Format) == 'table' then
local typeNformats = _Format
_Format = typeNformatstypeN or typeNformats1
if not _Format then
error(somethingMissing('typeN', typeN, typeNformats))
end
end
end
if typeN then _Format = mw.ustring.gsub(_Format, '%%3', typeN) end
if lineN then _Format = mw.ustring.gsub(_Format, '%%2', lineN) end
return (mw.ustring.match(_Format, '%[%[.+%]%]')) and (mw.ustring.gsub(_Format, '%%1', station)) or table.concat({'[[', mw.ustring.gsub(_Format, '%%1', station), '|', station, ']]'})
end
local function getTerminusText(var, Format)
local function subst(var1, var2)
-- var1 is the terminus or table of termini; var2 is the key for the table of termini
return type(var1) == 'string' and getStation(var1, (Formatvar1 or Format1]))
or type(var1) == 'table' and #var1 > 0 and getStation(var1var2], (Formatvar1var2]] or Format1]))
or ''
end
if Format then
if type(var) == 'string' then
return subst(var)
elseif type(var) == 'table' and #var > 0 then
local t = {subst(var, 1)}
for i = 2, #var - 1 do
ti = i18nlang]['comma'](subst(var, i))
end
if #var > 1 then t#var = i18nlang]['or'](subst(var, #var)) end
if var'via' then
if i18nlang]['via-first' then
table.insert(t, 1, i18nlang]['via'](subst(var, 'via')))
else
table.insert(t, i18nlang]['via'](subst(var, 'via')))
end
end
return table.concat(t)
else
return ''
end
else
return var or ''
end
end
function p._main(_args) -- Arguments are processed here instead of the main function
local yesno = require('Module:Yesno')
local trimq = require('Module:Trim quotes')._trim
local boolean = {
'oneway-left' = true,
'oneway-right' = true,
'reverse' = true,
'reverse-left' = true,
'reverse-right' = true
}
local args = {} -- Processed arguments
local index = {} -- A list of addresses corresponding to number suffixes in the arguments
for k, v in pairs(_args) do -- Maps each raw argument to processed arguments by string matching
_argsk = v:match('^%s*(.-)%s*$')
if _argsk and _argsk ~= '' then
local a = mw.ustring.match(k, '^(.*%D)%d+$') or k -- The parameter; address 1 can be omitted
local b = tonumber(mw.ustring.match(k, '^.*%D(%d+)$')) or 1 -- The address for a given argument; address 1 can be omitted
if booleana then
v = yesno(v)
end
if not argsb then
argsb = {[a = v}
table.insert(index, b)
elseif argsb][a then
return error(i18nlang]['error_duplicate'](a .. b))
else
argsb][a = v
end
end
end
table.sort(index)
local function small(s, italic)
return italic and '<div class="isA">' .. s .. '</div>'
or '<div class="smA">' .. s .. '</div>'
end
local style = { -- Style for each cell type
'header cell' = 'class="hcA"|',
'header midcell' = 'colspan="3" class="hmA"|',
'body cell' = 'class="bcA"|',
'body banner' = 'class="bbA" style="color:inherit;background-color:#',
}
local function rgb(var)
if var:len() == 3 then
return {tonumber(var:sub(1, 1), 16) * 17, tonumber(var:sub(2, 2), 16) * 17, tonumber(var:sub(2, 2), 16) * 17}
elseif var:len() == 6 then
return {tonumber(var:sub(1, 2), 16), tonumber(var:sub(3, 4), 16), tonumber(var:sub(5, 6), 16)}
end
return {}
end
local data = {} -- A table of data modules for each address
local noclearclass = (((_args.noclear or '') ~= '') and ' adjacent-stations-noclear' or '')
local wikitable = {'{| class="wikitable adjacent-stations' .. noclearclass .. '"'}
for i, v in ipairs(index) do
-- If an address has a system argument, indexes the data module
datav = argsv]['system' and getData(argsv]['system'])
-- If an address has no system, the row uses data from the previous address
or dataindexi - 1]]
or (argsv]['header' and getData(argsindexi+1]]['system']))
or error(i18nlang]['error_unknown'](argsv]['system']))
local lang = datav]['lang' or lang
if argsv]['system' and not argsv]['hide-system' then -- Header row
local stop_noun = datav]['header stop noun' or i18nlang]['stop_noun'
table.insert(wikitable, table.concat({'\n|-',
'\n! scope="col" ', style'header cell'], i18nlang]['preceding'](stop_noun),
'\n! scope="col" ', style'header midcell'], (datav]['system icon' and datav]['system icon' .. ' ' or ''), (datav]['system title' or ('[['.. argsv]['system' ..']]')),
'\n! scope="col" ', style'header cell'], i18nlang]['following'](stop_noun)
}))
table.insert(wikitable, '')
table.insert(wikitable, '')
table.insert(wikitable, '')
end
if argsv]['header' then -- Subheader
table.insert(wikitable, '\n|-\n!colspan="5" class="hmA"|'.. argsv]['header'])
table.insert(wikitable, '')
table.insert(wikitable, '')
table.insert(wikitable, '')
end
if argsv]['line' or argsv]['left' or argsv]['right' or argsv]['nonstop' then
if not argsv]['line' and i > 1 and not argsv]['system' then
argsv]['line' = argsindexi - 1]]['line'
end
lineN = argsv]['line' or '_default'
typeN = argsv]['type'
if datav]['aliases' then
lineN = datav]['aliases'][mw.ustring.lower(lineN)] or lineN
if typeN then typeN = datav]['aliases'][mw.ustring.lower(typeN)] or typeN end
end
-- get the line table
local line = datav]['lines' and (mw.clone(datav]['lines'][lineN]) or error(i18nlang]['error_unknown'](argsv]['line']))) or error(i18nlang]['error_line'])
local default = datav]['lines']['_default' or {}
line'title' = line'title' or default'title'
line'title' = mw.ustring.gsub(line'title'], '%%1', lineN)
-- cell across row for non-stop service
if argsv]['nonstop' then
table.insert(wikitable,
table.concat({'\n|-\n|colspan="5" ',
style'body cell'],
((argsv]['nonstop' == 'former') and i18nlang]['nonstop_past' or i18nlang]['nonstop_present'])(p._box({data = datav], line = lineN, Type = typeN, inline = 'yes'}))
})
)
table.insert(wikitable, '')
table.insert(wikitable, '')
table.insert(wikitable, '')
else
local Format = datav]['station format' or i18nlang]['error_format'
local color, color_2, background_color, circular
local Type = line'types' and line'types'][typeN -- get the line type table
if Type then
if Type'color' then
-- line color is used as background if there is no background color in the line type table
background_color = Type'background color' or line'color'
color = Type'color'
color_2 = Type'color2' or color
else
background_color = Type'background color' or line'background color'
color = line'color' or default'color' or ''
color_2 = line'color2' or color
end
if Type'circular' then
-- Type may override the circular status of the line
circular = Type'circular'
end
else
background_color = line'background color'
color = line'color' or default'color' or ''
color_2 = line'color2' or color
circular = line'circular'
end
-- Alternate termini can be specified based on type
local sideCell = {true, true}
for i, b in ipairs({'left', 'right'}) do
if not argsv][b then -- If no station is given on one side, the station is assumed to be the terminus on that side
local _through = argsv]['through-' .. b or argsv]['through'
local _through_data = getLine(datav], _through)
if _through_data then _through = _through_data'title' or _through end
sideCelli = _through and "''" .. i18nlang]['through'](trimq(_through)) .. "''"
or "''" .. trimq((argsv]['reverse-' .. b
or argsv]['reverse']) and i18nlang]['reverse'
or i18nlang]['terminus']) .. "''"
else
local terminusT
local terminusN = Type and Typeb .. ' terminus' or lineb .. ' terminus'
-- If the terminus table has more than one numbered key or has the via key then the table shows only the default termini, since terminusN[2] cannot be used and terminusN[via] is reserved
if type(terminusN) == 'string' or (type(terminusN) == 'table' and (terminusN2 or terminusN'via'])) then
if argsv]['to-' .. b then
terminusT = argsv]['to-' .. b
local _or = mw.ustring.match(terminusT, i18nlang]['or-format'])
if _or then
terminusT = mw.ustring.gsub(terminusT, i18nlang]['or-format'], '\127_OR_\127')
terminusT = mw.ustring.gsub(terminusT, i18nlang]['comma-format'], '\127_OR_\127')
end
local _via = (mw.ustring.match(terminusT, i18nlang]['via-format']))
if _via then
terminusT = mw.ustring.gsub(terminusT, i18nlang]['via-format'], '')
terminusT = mw.text.split(terminusT, '\127_OR_\127')
terminusT'via' = _via
elseif _or then
terminusT = mw.text.split(terminusT, '\127_OR_\127')
end
else
terminusT = terminusN
end
elseif type(terminusN) == 'table' then
terminusT = terminusNargsv]['to-' .. b]] or terminusNargsv]['to']] or terminusN1
end
local mainText = argsv]['note-' .. b and getTerminusText(argsv][b], Format) .. small(argsv]['note-' .. b]) or getTerminusText(argsv][b], Format)
local subText = (argsv]['oneway-' .. b or line'oneway-' .. b]) and i18nlang]['oneway'
or argsv][b == terminusT and i18nlang]['terminus'
or circular and terminusT
or i18nlang]['towards'](getTerminusText(terminusT, Format))
subText = small(subText, true)
sideCelli = mainText .. subText
end
end
table.insert(wikitable, '\n|-')
table.insert(wikitable, '\n|' .. style'body cell' .. sideCell1])
table.insert(wikitable, table.concat({'\n|', style'body banner'], color, '"|',
'\n|', (background_color and 'class="bcA" style="background-color:rgba(' .. table.concat(rgb(background_color), ',') .. ',.2)"|' or style'body cell']), line'title'],
-- Type; table key 'types' in subpages (datatype table, with strings as keys). If table does not exist then the input is displayed as the text
(typeN and '<div>' .. (Type and Type'title' or typeN) .. '</div>' or ''),
-- Note-mid; table key 'note-mid' in subpages. Overridden by user input
((argsv]['note-mid' and small(argsv]['note-mid'])) or (Type and Type'note-mid' and small(Type'note-mid'])) or (line'note-mid' and small(line'note-mid'])) or ''),
-- Transfer; uses system's station link table
(argsv]['transfer' and small('transfer at ' .. getTerminusText(argsv]['transfer'], Format), true) or ''),
'\n|', style'body banner'], color_2, '"|'}))
table.insert(wikitable, '\n|' .. style'body cell' .. sideCell2])
end
end
if argsv]['note-row' then -- Note
if argsv]['note-row']:match('^%s*<tr') or argsv]['note-row']:match('^%s*%|%-') then
table.insert(wikitable, '\n' .. argsv]['note-row'])
else
table.insert(wikitable, '\n|-\n|colspan="5" ' .. style'body cell' .. argsv]['note-row'])
end
table.insert(wikitable, '')
table.insert(wikitable, '')
table.insert(wikitable, '')
end
end
local function combine(t, n)
if tn + 4 ~= '' and tn + 4 == tn then
tn + 4 = '' -- The cell in the next row is deleted
local rowspan = 2
while tn + rowspan * 4 == tn do
tn + rowspan * 4 = ''
rowspan = rowspan + 1
end
tn = mw.ustring.gsub(tn], '\n|class="', '\n|rowspan="' .. rowspan .. '" class="')
end
end
local M = #wikitable
for i = 3, M, 4 do combine(wikitable, i) end
for i = 4, M, 4 do combine(wikitable, i) end
for i = 5, M, 4 do combine(wikitable, i) end
table.insert(wikitable, '\n|}')
return table.concat(wikitable)
end
local getArgs = require('Module:Arguments').getArgs
local function makeInvokeFunction(funcName)
-- makes a function that can be returned from #invoke, using
-- [[Module:Arguments]]
return function (frame)
local args = getArgs(frame, {parentOnly = true})
return pfuncName](args, frame)
end
end
p.main = makeInvokeFunction('_main')
function p._color(args, frame)
local data = args.data
if args1 or data then
data = data or getData(args1], true)
if not data then return getColor(nil, args1], args2], args3], frame) end
return getColor(data, nil, args2], args3])
end
end
p.color = makeInvokeFunction('_color')
function p._box(args, frame)
local system = args1 or args.system
lineN = args2 or args.line
if not (system or lineN) then return '' end
local line, Type, line_data
local inline = args3 or args.inline
typeN = args.type
local data = args.data
if system or data then
data = data or getData(system, true)
local color
if data then
local default = data'lines']['_default' or {}
line, lineN = getLine(data, lineN)
if typeN then
typeN = data'aliases' and data'aliases'][mw.ustring.lower(typeN)] or typeN
Type = line'types' and line'types'][typeN and line'types'][typeN]['title' or typeN
end
color = getColor(data, nil, lineN, typeN)
if inline ~= 'box' then
line_data = line or error(i18nlang]['error_unknown'](lineN))
line = line_data'title' or default'title' or error(i18nlang]['error_missing']('title'))
line = mw.ustring.gsub(line, '%%1', lineN)
end
else
color = getColor(nil, system, lineN, typeN, frame)
if inline ~= 'box' then
line = frame:expandTemplate{ title = system .. ' lines', args = {lineN, 'branch' = typeN} }
if mw.text.trim(line) == '' then return error(i18nlang]['error_unknown'](lineN)) end
end
Type = typeN
end
local result
if Type and Type ~= '' and inline ~= 'box' then
if line == '' then
line = Type
else
result = ' – ' .. Type
end
end
if args.note then result = (result or '') .. ' ' .. args.note end
result = result or ''
if not inline then -- [[Template:Legend]]
result = '<div class="legend" style="page-break-inside:avoid;break-inside:avoid-column"><span class="legend-color" style="display:inline-block;min-width:1.25em;height:1.25em;line-height:1.25;margin:1px 0;border:1px solid black;background-color:#' .. color .. '"> </span> ' .. line .. result .. '</div>'
elseif inline == 'yes' then
result = '<span style="background-color:#' .. color .. ';border:1px solid #000"> </span> ' .. line .. result
elseif inline == 'box' then
result = '<span style="background-color:#' .. color .. ';border:1px solid #000"> </span>' .. result
elseif inline == 'link' then
local link = args.link or mw.ustring.match(line, '%[%[([^%[:|%]]+)[|%]]')
if link then
result = '[[' .. link .. '|<span style="background-color:#' .. color .. ';border:1px solid #000"> </span>]]' .. result
else
result = '<span style="background-color:#' .. color .. ';border:1px solid #000"> </span>' .. result
end
elseif inline == 'square' then
result = '<span style="color:#' .. color .. ';line-height:initial">■</span> ' .. line .. result
elseif inline == 'lsquare' then
local link = args.link or mw.ustring.match(line, '%[%[([^%[:|%]]+)[|%]]')
if link then
result = '[[' .. link .. '|<span style="color:#' .. color .. ';line-height:initial">■</span>]]'
else
result = '<span style="color:#' .. color .. ';line-height:initial">■</span>'
end
elseif inline == 'dot' then
result = '<span style="color:#' .. color .. ';line-height:initial">●</span> ' .. line .. result
elseif inline == 'ldot' then
local link = args.link or mw.ustring.match(line, '%[%[([^%[:|%]]+)[|%]]')
if link then
result = '[[' .. link .. '|<span style="color:#' .. color .. ';line-height:initial">●</span>]]'
else
result = '<span style="color:#' .. color .. ';line-height:initial">●</span>'
end
elseif inline == 'small' then
result = '<span style="background-color:#' .. color .. '"> </span>' .. ' ' .. line .. result
else
local yesno = require("Module:Yesno")
local link = args.link or mw.ustring.match(line, '%[%[([^%[:|%]]+)[|%]]')
local border_color, text_color
local color_box = data'color box format' or data'rail box format' or {}
if line_data then
if line_data'types' and line_data'types'][typeN then
local Type_data = line_data'types'][typeN
border_color = Type_data'border color' or line_data'border color' or color
text_color = Type_data'text color' or line_data'text color'
if color_box == 'title' and not args4 then
lineN = Type_data'short name' or line_data'short name' or require('Module:Delink')._delink{line}
else
lineN = Type_data'short name' or line_data'short name' or lineN
end
else
border_color = line_data'border color' or color
text_color = line_data'text color'
if color_box == 'title' and not args4 then
lineN = line_data'short name' or require('Module:Delink')._delink{line}
else
lineN = line_data'short name' or lineN
end
end
else
border_color = color
end
text_color = text_color and '#' .. text_color or require('Module:Color contrast')._greatercontrast{color}
local bold = ';font-weight:bold'
if (yesno(args.bold) == false) then bold = '' end
if inline == 'route' then -- [[Template:RouteBox]]
if link then
result = '<span style="background-color:#' .. color .. ';border:.075em solid #' .. border_color .. ';padding:0 .3em">[[' .. link .. '|<span style="color:' .. text_color .. bold .. ';font-size:inherit;white-space:nowrap">' .. lineN .. '</span>]]</span>'
else
result = '<span style="background-color:#' .. color .. ';border:.075em solid #' .. border_color .. ';padding:0 .3em;color:' .. text_color .. bold .. ';font-size:inherit;white-space:nowrap">' .. lineN .. '</span>'
end
elseif inline == 'croute' then -- [[Template:Bahnlinie]]
if link then
result = '<span style="background-color:#' .. color .. ';border:.075em solid #' .. border_color .. ';border-radius:.5em;padding:0 .3em">[[' .. link .. '|<span style="color:' .. text_color .. bold .. ';font-size:inherit;white-space:nowrap">' .. lineN .. '</span>]]</span>'
else
result = '<span style="background-color:#' .. color .. ';border:.075em solid #' .. border_color .. ';border-radius:.5em;padding:0 .3em;color:' .. text_color .. bold .. ';font-size:inherit;white-space:nowrap">' .. lineN .. '</span>'
end
elseif inline == 'xroute' then -- [[Template:Bahnlinie]]
if link then
result = '<span style="border:.075em solid #' .. border_color .. ';border-radius:.5em;padding:0 .3em">[[' .. link .. '|<span style="color:#' .. color .. bold .. ';font-size:inherit;white-space:nowrap">' .. lineN .. '</span>]]</span>'
else
result = '<span style="border:.075em solid #' .. border_color .. ';border-radius:.5em;padding:0 .3em;color:#' .. color .. bold .. ';font-size:inherit;white-space:nowrap">' .. lineN .. '</span>'
end
elseif inline == 'broute' then
if link then
result = '<span style="background-color:#' .. color .. ';border:.075em solid #000;padding:0 .3em">[[' .. link .. '|<span style="color:' .. text_color .. bold .. ';font-size:inherit;white-space:nowrap">' .. lineN .. '</span>]]</span>'
else
result = '<span style="background-color:#' .. color .. ';border:.075em solid #000;padding:0 .3em;color:' .. text_color .. bold .. ';font-size:inherit;white-space:nowrap">' .. lineN .. '</span>'
end
else -- [[Template:Legend]] (fallback; duplication to simplify logic)
result = '<div class="legend" style="page-break-inside:avoid;break-inside:avoid-column"><span class="legend-color" style="display:inline-block;min-width:1.25em;height:1.25em;line-height:1.25;margin:1px 0;border:1px solid black;background-color:#' .. color .. '"> </span> ' .. line .. result .. '</div>'
end
end
result = mw.ustring.gsub(result, ':%s*#transparent', ':transparent')
return result
end
end
p.box = makeInvokeFunction('_box')
function p._icon(args, frame)
local system = args1 or args.system
local data = args.data
if not system and not data then
return
end
data = data or getData(system)
local line, line_name = getLine(data, args2 or args.line)
local icon
local icon_format
if line then
local line_type = args3 or args.type
if line_type then
line_type = data.aliases and data.aliasesmw.ustring.lower(line_type)] or line_type
line_type = line.types and line.typesline_type -- If there's no type table or entry for this type, then it can't have its own icon
icon_format = line_type'icon format' or data'type icon format'
if line_type.icon then
icon = line_type.icon
end
end
if not icon then
icon = line.icon
end
-- Only if there is no icon use the icon_format.
if not icon and not icon_format then
icon_format = line'icon format' or data'line icon format'
end
local default = data.lines._default or {}
if icon and string.find(icon, "%%1") and default and default.icon then
icon = mw.ustring.gsub(default.icon, '%%1', line_name)
end
end
if not icon then
icon = data'system icon'
end
if not icon_format then
icon_format = data'system icon format'
end
if icon_format then
if icon_format ~= 'image' then
icon = p._box({data = data, 2 = (args2 or args.line), 3 = icon_format, type = (args3 or args.type), bold = args.bold, link = args.link}, frame)
if args.name then
if line and line.title then
return icon .. " " .. line.title
end
return icon .. " " .. data"system title"
end
end
end
local size = args.size
if size then
if mw.ustring.match(size, '%d$') then
size = '|' .. size .. 'px'
else
size = '|' .. size
end
-- Upright values are to be disabled until there is use of upright scaling in subpages; doesn't seem to work anyway as of 2018-08-10
local regex = {
'|%s*%d*x?%d+px%s*([%]|])', -- '|%s*upright=%d+%.?%d*%s*([%]|])', '|%s*upright%s*([%]|])'
}
if mw.ustring.match(icon, regex1]) then
icon = mw.ustring.gsub(icon, regex1], size .. '%1')
-- elseif mw.ustring.match(icon, regex[2]) then
-- icon = gsub(icon, regex[2], size .. '%1')
-- elseif mw.ustring.match(icon, regex[3]) then
-- icon = gsub(icon, regex[3], size .. '%1')
else
icon = mw.ustring.gsub(icon, '(%[%[[^%]|]+)([%]|])', '%1' .. size .. '%2')
end
end
local link = args.link
if link then
if mw.ustring.match(icon, '|%s*link=[^%]|]*[%]|]') then
icon = mw.ustring.gsub(icon, '|%s*link=[^%]|]*([%]|])', '|link=' .. link .. '%1')
else
icon = mw.ustring.gsub(icon, '(%[%[[^%]|]+)([%]|])', '%1|link=' .. link .. '%2')
end
end
local alt = args.alt or link
if alt then
if mw.ustring.match(icon, '|%s*alt=[^%]|]*[%]|]') then
icon = mw.ustring.gsub(icon, '|%s*alt=[^%]|]*([%]|])', '|alt=' .. alt .. '%1')
else
icon = mw.ustring.gsub(icon, '(%[%[[^%]|]+)([%]|])', '%1|alt=' .. alt .. '%2')
end
end
if args.name then
if line and line.title then
return icon .. " " .. line.title
end
return icon .. " " .. data"system title"
end
return icon
end
p.icon = makeInvokeFunction('_icon')
function p._line(args, frame)
local system = args1 or args.system
local line = args2 or args.line
if not line then return '' end
local Type = args3 or args.type
local data = args.data
if system or data then
data = data or getData(system, true)
if data then
line = (getLine(data, line)) or error(i18nlang]['error_unknown'](line))
if Type then
Type = data'aliases' and data'aliases'][mw.ustring.lower(Type)] or Type
Type = line'types' and line'types'][Type and line'types'][Type]['title' or Type
end
line = line'title' or error(i18nlang]['error_missing']('title'))
else
line = frame:expandTemplate{ title = system .. ' lines', args = {line, 'branch' = Type} }
if mw.text.trim(line) == '' then return error(i18nlang]['error_unknown'](lineN)) end
end
if Type and Type ~= '' then
if line == '' then
line = Type
else
line = line .. ' – ' .. Type
end
end
return line
end
end
p.line = makeInvokeFunction('_line')
function p._shortline(args, frame)
local system = args1 or args.system
lineN = args2 or args.line
if not (system or lineN) then return '' end
local line, Type, line_data
typeN = args.type
local data = args.data
if system or data then
data = data or getData(system, true)
if data then
local default = data'lines']['_default' or {}
line, lineN = getLine(data, lineN)
if typeN then
typeN = data'aliases' and data'aliases'][mw.ustring.lower(typeN)] or typeN
Type = line'types' and line'types'][typeN and line'types'][typeN]['title' or typeN
end
line_data = line or error(i18nlang]['error_unknown'](lineN))
line = line_data'title' or default'title' or error(i18nlang]['error_missing']('title'))
line = mw.ustring.gsub(line, '%%1', lineN)
else
line = frame:expandTemplate{ title = system .. ' lines', args = {lineN, 'branch' = typeN} }
if mw.text.trim(line) == '' then return error(i18nlang]['error_unknown'](lineN)) end
Type = typeN
end
local result
if Type and Type ~= '' then
if line == '' then
line = Type
else
result = ' – ' .. Type
end
end
if args.note then result = (result or '') .. ' ' .. args.note end
result = result or ''
local link = args.link or mw.ustring.match(line, '%[%[([^%[:|%]]+)[|%]]')
if line_data then
if line_data'types' and line_data'types'][typeN then
local Type_data = line_data'types'][typeN
lineN = Type_data'short name' or line_data'short name' or lineN
else
lineN = line_data'short name' or lineN
end
end
if link then
result = '[[' .. link .. '|' .. lineN .. ']]'
else
result = lineN
end
result = mw.ustring.gsub(result, ':%s*#transparent', ':transparent')
return result
end
end
p.shortline = makeInvokeFunction('_shortline')
function p._station(args, frame)
local system = args1 or args.system
local station = args2 or args.station
if not station then return '' end
lineN = args3 or args.line
typeN = args4 or args.type
local data = args.data
if system or data then
data = data or getData(system, true)
if data then
local _Format = data'station format'][station or data'station format'][1
if _Format then
if data'aliases' then
if lineN then
lineN = data'aliases'][mw.ustring.lower(lineN)] or lineN
end
if typeN then
typeN = data'aliases'][mw.ustring.lower(typeN)] or typeN
end
end
station = getStation(station, _Format)
else
station = station or ''
end
else
station = frame:expandTemplate{ title = system .. ' stations', args = {['station' = station, 'line' = lineN, 'branch' = typeN} }
end
return station
end
end
p.station = makeInvokeFunction('_station')
function p._terminusTable(args, frame)
local system = args1 or args.system
lineN = args2 or args.line
local side = mw.ustring.sub(mw.ustring.lower(args3 or args.side or ''), 1, 1)
typeN = args.type
local prefix = (side == 'r') and 'right' or 'left'
local data = args.data
if system or data then
data = data or getData(system, true)
end
if data then
local line = getLine(data, lineN) or error(i18nlang]['error_unknown'](lineN))
if typeN and data and data'aliases' then typeN = data'aliases'][mw.ustring.lower(typeN)] or typeN end
local Type = line'types' and line'types'][typeN
local circular
if Type then
if Type'circular' then
-- Type may override the circular status of the line
circular = Type'circular'
end
else
circular = line'circular'
end
return Type and Typeprefix .. ' terminus' or lineprefix .. ' terminus'], data'station format' or i18nlang]['error_format'], circular
else
local terminus = frame:expandTemplate{ title = 'S-line/' .. system .. ' ' .. prefix .. '/' .. lineN }
return mw.ustring.gsub(terminus, '{{{type}}}', typeN)
end
end
function p._terminus(args, frame)
local var, Format, circular = p._terminusTable(args, frame)
return circular and var or getTerminusText(var, Format)
end
p.terminus = makeInvokeFunction('_terminus')
function p._style(args, frame)
local style = args1 or args.style
local system = args2 or args.system
local line = args3 or args.line
local station = args4 or args.station
local result = {}
local data = args.data
local default = 'background-color:#efefef' -- Default background color for {{Infobox station}}
if system or data then
data = data or getData(system, true)
end
if data then
local function getValue(var)
if type(var) == 'table' then
var = varline or var1
if type(var) == 'table' then
var = varstation or var1
end
end
if var ~= '' then return var end
end
if style == 'header' then
local tmp = data'name format' and getValue(data'name format'])
if tmp then table.insert(result, tmp) end
elseif style == 'subheader' then
local tmp = data'header background color' and getValue(data'header background color'])
if tmp then
table.insert(result, 'background-color:#' .. tmp)
local color = data'header text color' and getValue(data'header text color'])
if color then
table.insert(result, 'color:#' .. color)
else
local greatercontrast = require('Module:Color contrast')._greatercontrast
if greatercontrast{tmp} == '#FFFFFF' then table.insert(result, 'color:#FFFFFF') end
end
else
table.insert(result, default)
local color = data'header text color' and getValue(data'header text color'])
if color then table.insert(result, 'color:#' .. color) end
end
end
result = table.concat(result, ';')
elseif system then
local title = 'Template:' .. system .. ' style'
local titleObj = mw.title.new(title)
if titleObj and titleObj.exists then
local tmp
if style == 'header' then
tmp = frame:expandTemplate{ title = title, args = {'name_format', line, station} }
if tmp ~= '' then table.insert(result, tmp) end
elseif style == 'subheader' then
tmp = frame:expandTemplate{ title = title, args = {'thbgcolor', line, station} }
if tmp ~= '' then
table.insert(result, 'background-color:#' .. tmp)
local color = frame:expandTemplate{ title = title, args = {'thcolor', line, station} }
if color ~= '' then
table.insert(result, 'color:#' .. color)
else
local ratio = require('Module:Color contrast')._ratio
if ratio{tmp, '222222'} < 4.5 then table.insert(result, 'color:#FFFFFF') end -- 222222 is the default text color in Vector
end
else
table.insert(result, default)
tmp = frame:expandTemplate{ title = title, args = {'thcolor', line, station} }
if tmp ~= '' then
table.insert(result, 'color:#' .. tmp)
end
end
end
result = table.concat(result, ';')
else
if style == 'subheader' then
result = default
else
result = ''
end
end
else
if style == 'subheader' then
result = default
else
result = ''
end
end
return result
end
function p.style(frame)
local args = getArgs(frame, {frameOnly = true})
return p._style(args, frame)
end
function p.convert(frame)
local args = frame.args
local code = mw.text.split(mw.ustring.gsub(args1], '^%s*{{(.*)}}%s*$', '%1'), '%s*}}%s*{{%s*')
local system
local group = tonumber(args.offset or 0) or 0
local firstgroup = group + 1
local delete = {
's-rail' = true,
's-rail-next' = true,
's-rail-national' = true,
's-start' = true,
's-rail-start' = true,
'start' = true,
's-end' = true,
'end' = true
}
local order = {
'line', 'left', 'right', 'to-left', 'to-right',
'oneway-left', 'oneway-right', 'through-left', 'through-right',
'reverse', 'reverse-left', 'reverse-right',
'note-left', 'note-mid', 'note-right', 'transfer'
-- circular: use module subpage
-- state: not implemented
}
local replace = {
'previous' = 'left',
'next' = 'right',
'type' = 'to-left',
'type2' = 'to-right',
'branch' = 'type',
'note' = 'note-left',
'notemid' = 'note-mid',
'note2' = 'note-right',
'oneway1' = 'oneway-left',
'oneway2' = 'oneway-right',
'through1' = 'through-left',
'through2' = 'through-right'
}
local remove_rows = {}
local data = {}
local noclear = false
for i, v in ipairs(code) do
codei = mw.ustring.gsub(codei], '\n', ' ')
local template = mw.ustring.lower(mw.text.trim(mw.ustring.match(codei], '^[^|]+')))
codei = mw.ustring.match(codei], '(|.+)$')
if (mw.ustring.match(codei or '', 'noclear%s*=%s*[a-z]')) then
noclear = true
end
if template == 's-line' then
datai = {}
local this_system = mw.text.trim(mw.ustring.match(codei], '|%s*system%s*=([^|]+)'))
codei = mw.text.split(codei], '%s*|%s*')
for m, n in ipairs(codei]) do
local tmp = mw.text.split(n, '%s*=%s*')
if tmp3 then
tmp2 = mw.ustring.gsub(n, '^.-%s*=', '')
end
tmp1 = replacetmp1]] or tmp1
if tmp2 then
-- checks for matching brackets
local curly = select(2, mw.ustring.gsub(tmp2], "{", ""))-select(2, mw.ustring.gsub(tmp2], "}", ""))
local square = select(2, mw.ustring.gsub(tmp2], "%[", ""))-select(2, mw.ustring.gsub(tmp2], "%]", ""))
if not (curly == 0 and square == 0) then
local count = mw.clone(m)+1
while not (curly == 0 and square == 0) do
tmp2 = tmp2..'|'..codei][count
curly = curly+select(2, mw.ustring.gsub(codei][count], "{", ""))-select(2, mw.ustring.gsub(codei][count], "}", ""))
square = square+select(2, mw.ustring.gsub(codei][count], "%[", ""))-select(2, mw.ustring.gsub(codei][count], "%]", ""))
codei][count = ''
count = count+1
end
end
datai][tmp1]] = tmp2
end
end
if (this_system ~= system) or (not system) then
system = this_system
datai]['system' = system
else
datai]['system' = nil
end
local last = datai-1 or datai-2 or datai-3
if last then
for r, s in pairs({
'hide1' = {'left', 'to-left', 'note-left', 'oneway-left'},
'hide2' = {'right', 'to-right', 'note-right', 'oneway-right'},
'hidemid' = {'type', 'note-mid'}
}) do
if datai][r then
for m, n in ipairs(s) do
if not datai][n then
datai][n = lastn
end
end
end
end
end
codei = {}
local X = '|'
local Y = (i+group)..'='
if datai]['system' then
table.insert(codei], '|system')
table.insert(codei], Y)
table.insert(codei], datai]['system'])
table.insert(codei], '\n')
end
for m, n in ipairs(order) do
if datai][n then
table.insert(codei], X)
table.insert(codei], n)
table.insert(codei], Y)
table.insert(codei], datai][n])
end
end
codei = table.concat(codei])
elseif template == 's-note' then
codei = mw.ustring.gsub(codei], '|%s*text%s*=', '|header'..i+group..'=')
codei = mw.ustring.gsub(codei], '|%s*wide%s*=[^|]*', '')
elseif template == 's-text' then
codei = mw.ustring.gsub(codei], '|%s*text%s*=', '|note-row'..i+group..'=')
elseif deletetemplate then
codei = ''
table.insert(remove_rows, 1, i) -- at the start, so that the rows are deleted in reverse order
group = group-1
end
end
for i, v in ipairs(remove_rows) do
table.remove(code, v)
end
code = table.concat(code, '\n')
local t = {'{{Adjacent stations' .. (noclear and '|noclear=y\n' or ''), '\n}}'}
system = mw.ustring.match(code, '|system(%d*)=')
code = mw.ustring.gsub(code, '\n\n+', '\n')
if tonumber(system) > firstgroup then
-- If s-line isn't the first template then the system will have to be moved to the top
system = mw.ustring.match(code, '|system%d*=([^|]*[^|\n])')
code = mw.ustring.gsub(code, '|system%d*=[^|]*', '')
code = '\n|system'..firstgroup..'='..system..code
elseif not mw.ustring.match(code, '^[^{%[]*|[^=|]+2=') then
-- If there's only one parameter group then there's no need to have line breaks
code = mw.ustring.gsub(code, '\n', '')
code = mw.ustring.gsub(code, '(|[^=|]+)1=', '%1=')
t2 = '}}'
if not mw.ustring.match(code, '[%[{]') then
code = mw.ustring.gsub(code, '|[^=|]*=$', '')
code = mw.ustring.gsub(code, '|[^=|]*$', '')
end
end
if not mw.ustring.match(code, '[%[{]') then
code = mw.ustring.gsub(code, '|[^=|]*=|', '|')
code = mw.ustring.gsub(code, '|[^=|]*|', '|')
code = mw.ustring.gsub(code, '|[^=|]*=\n', '\n')
code = mw.ustring.gsub(code, '|[^=|]*\n', '\n')
end
return t1..code..t2
end
return p