模組:Adjacent stations
外觀
![]() | 此模組使用Lua語言: |
有關以下模塊的模板 |
模塊:Adjacent stations |
---|
(討論 | 沙盒 | 子頁面) |
{{Infobox station}} |
(沙盒 | 測試樣例) |
{{Station link}} |
(沙盒 | 測試樣例) |
{{Rail color}} |
(沙盒 | 測試樣例) |
{{Rail icon}} |
(沙盒 | 測試樣例) |
{{Line link}} |
(沙盒 | 測試樣例) |
{{Rail color box}} |
(沙盒 | 測試樣例) |
{{Adjacent stations}} |
(沙盒 | 測試樣例) |
{{Line terminus link}} |
(沙盒 | 測試樣例) |
{{RenderStations}} |
(沙盒 | 測試樣例) |
![]() | 此模組被引用於約42,000個頁面。 為了避免造成大規模的影響,所有對此模組的編輯應先於沙盒或測試樣例上測試。 測試後無誤的版本可以一次性地加入此模組中,但是修改前請務必於討論頁發起討論。 模板引用數量會自動更新。 |
本模組實現{{Adjacent stations}}、{{Rail icon}}、{{Rail color box}}、{{Line link}}、{{Station link}}和{{Rail color}}的功能。欲了解如何使用這些模板,請參閱其文件。(本模組的convert
函式的指引置於{{Adjacent stations}}的文件。)
前述的模板依賴於本模組的子模組所存放的資料。例如,{{Rail icon|MTR}}從Module:Adjacent stations/MTR生成。
下列範例對建立和編輯資料會有幫助,但有一定Lua基礎能避免一些錯誤。如果你之前編寫或是使用過Lua,你可以跳過下一小節。
術語
- Lua有不同的資料類型(data types)。此處將會涉及到的有布林型(boolean)、字串(string)、數字(number)和表(table)。
- 布林型資料只能是
true
(真)或false
(假)。 - 字串即文字,以字元列表的形式儲存。Lua有數種方式在代碼中表記字串,此處的範例使用雙引號包裹的方式表記(如
"这是一个字符串"
)。 - 數字即數值,像
0.5
或42
。 - 表是可以包含其他對象的結構,並支援巢狀。
- 空表在代碼中形如
{}
。 - 表有鍵(key)和值(value)典型結構如
["key"] = value
;鍵值對(key-value pair)之間由西文逗號分隔。此處使用的鍵都是字串或數字。 {"text", "more text"}
等價於{[1] = "text", [2] = "more text"}
。
- 空表在代碼中形如
- 布林型資料只能是
- 使用
local variable_name = "value"
可以定義一個變數(variable)。 - 空白(whitespace)包括制表符、換行符、空格及其任意組合。空白在Lua中不影響結果,但除了內建的文字,此處的所有範例都經過了縮排處理,根據鍵分行,以提高可讀性。
- 返回語句(return statement,如
return variable_name
)退出當前函式,並回報variable_name
的值。此處的「函式」指主模組中呼叫子頁面的代碼,而variable_name
應為表類型。
基本結構
下面展示兩個模組:
空白 | local p = {
["system title"] = "",
["system icon"] = "",
["station format"] = {
"",
[""] = "",
},
["lines"] = {
[""] = {
["title"] = "",
["color"] = "",
["left terminus"] = "",
["right terminus"] = "",
},
},
}
return p
|
範例 | local x = "%1站 (高雄捷運)"
local y = "%1站 (臺灣)"
local p = {
["system title"] = "[[高雄捷運]]",
["station format"] = {
"%1站",
-- 紅線
["大湖"] = x,
["岡山車站"] = "[[岡山車站 (高雄捷運)|岡山車站]]",
["橋頭火車站"] = "[[橋頭車站 (台灣)|橋頭火車站]]",
["高雄車站"] = "%1",
["都會公園"] = y,
["左營"] = "[[高鐵左營站#高雄捷運左營/高鐵站|左營/高鐵]]",
["左營/高鐵"] = "[[高鐵左營站#高雄捷運左營/高鐵站|左營/高鐵]]",
["中央公園"] = y,
["凱旋"] = y,
["小港"] = "[[小港站 (捷運)|小港]]",
-- 橘線
["哈瑪星"] = x,
["文化中心"] = y,
["鳳山西站"] = "%1",
["鳳山"] = x,
-- 環狀輕軌
["哈瑪星(輕軌)"] = "[[哈瑪星站 (高雄輕軌)|哈瑪星]]",
["鼓山"] = "[[鼓山車站]]",
["台鐵美術館"] = "[[美術館車站]]",
["科工館"] = "[[科工館車站]]",
-- 黃線
["民族"] = "[[民族車站|民族]]",
["大港"] = x,
},
["lines"] = {
["紅"] = {
["title"] = "[[File:Kaohsiung Rapid Transit Red Line.svg|20px]] [[高雄捷運紅線|紅線]]",
["color"] = "e20b65",
["left terminus"] = "小港",
["right terminus"] = "南路竹"
},
["橘"] = {
["title"] = "[[File:Kaohsiung Rapid Transit Orange Line.svg|20px]] [[高雄捷運橘線|橘線]]",
["color"] = "faa73f",
["left terminus"] = "哈瑪星",
["right terminus"] = "大寮"
},
["環"] = {
["title"] = "[[File:Kaohsiung Rapid Transit Circular Line.svg|20px]] [[高雄環狀輕軌|環狀輕軌]]",
["color"] = "7cbd52",
["circular"] = true,
["left terminus"] = "逆行",
["right terminus"] = "順行"
},
["黃"] = {
["title"] = "[[File:Kaohsiung Rapid Transit Yellow Line.svg|20px]] [[高雄捷運黃線|黃線]]",
["color"] = "ffc100",
["left terminus"] = "坔埔",
["right terminus"] = {"旅運中心", "前鎮高中"}
}
},
["aliases"] = {
["r"] = "紅",
["o"] = "橘",
["c"] = "環",
["y"] = "黃"
}
}
return p
|
範例模組為Module:Adjacent stations/高雄捷運。
- 首先需要兩條記錄,
"station format"
和"lines"
。前者用於生成指向車站條目的連結,後者包括各線路的表。 "system title"
是標題行中間的文字。"station format"
定義車站條目名稱的規則和例外。第一個變數"%1 metro station"
是預設值。例外由鍵值對列出(如"岡山"
–"岡山車站"
),此處鍵是輸入值。模組顯示輸入值,並根據處理後的值連結到條目,其中%1
將被輸入值替代。或者,也可以直接鍵入完整的維基連結,這樣顯示文字就可以與輸入值不同。"lines"
列出線路。此處的名稱僅在內部使用,並不用於顯示,所以請儘量簡短。"line title"
是顯示線上路所在行中間的文字;"left terminus"
是預設的左側終點站,"right terminus"
則是預設的右側終點站。- 每個
"color"
記錄線路的顏色。 - 首行定義的
x
是用于格式化車站名稱的字串。"station format"
表中,x
被用於數個需要「 (高雄捷運)」字尾的車站。這個方法是可選的,但在數個車站條目命名遵循另一條規則時相當有用。
以下是Module:Adjacent stations/台灣高鐵:
local p = {
["system title"] = "[[台灣高速鐵路]]",
["system color"] = "c35617",
["name format"] = "color: #FFFFFF; background-color: #C35617;",
["station format"] = {
"高鐵%1站",
["南港"] = "[[南港車站|南港]]",
["臺北"] = "[[臺北車站|臺北]]",
["板橋"] = "[[板橋車站_(臺灣)|板橋]]",
},
["lines"] = {
["_default"] = {
["title"] = "[[台灣高鐵]]",
["color"] = "c35617",
["left terminus"] = "南港",
["right terminus"] = "左營"
}
}
}
return p
- 這個模組包括一條虛擬線路
["_default"]
。此處的標題和顏色被用於所有線路,除非被具體線路覆蓋。當呼叫時不指定line=
,此表就會被使用。
層級和參數列
- 表的第一層是整個系統的資料和輸出選項。
- 系統表下層是線路的列表。
- 第三層是具體線路的資料。
- 每條線可以有多個「類型」。「類型」可以是服務類型(如不同速度等級)或線路的支線。
- 第五層是具體類型的資料。
未指明類型的鍵和值都是字串。
主層 (1)
參數 | 類型 | 被{{Adjacent stations}}使用 | 描述 |
---|---|---|---|
["lang"]
|
字串 | 是 | 預設且僅有"zh-CN" ,影響偏好設定字串的選擇,本語言維基不使用此在地化方案,而是交由字詞轉換完成。
|
["system title"]
|
字串 | 是 | 標題行中間的文字。 |
["system icon"]
|
字串 | 是 | {{Adjacent stations}}標題行中間和{{Rail icon}}使用的圖示。 |
["system icon format"]
|
字串 | 否 | 圖示類型,由{{Rail icon}}使用。如果指定並且值不為"image" ,圖示資料將交由{{Rail color box}}預處理。
|
["system color"]
|
字串 | 否 | RGB十六進制三元值(三或六個字元長,如"BE2D2C" 或"039" )。呼叫{{Rail color}}時僅用一個參數時返回。
|
["header stop noun"]
|
字串 | 是 | 標題行左右儲存格的「上一」和「下一」後使用的名詞。預設值為"station" 。
|
["name format"]
|
字串 | 否 | {{Infobox station}}表頭的CSS,亦可使用|1=header 呼叫style 函式取值。值可以為字串或巢狀表,其中使用表的首層(對應{{Infobox station}}的|style2= )。第二層目前未使用。巢狀表的第一項(無鍵項或鍵為1 )為預設。
|
["header background color"]
|
字串 | 否 | {{Infobox station}}次表頭使用的RGB十六進制三元值,亦可使用|1=subheader 呼叫style 函式取值。預設為亮灰色。值可以為字串或巢狀表,結構類似"name format" 。
|
["header text color"]
|
字串 | 否 | {{Infobox station}}次表頭使用的RGB十六進制三元值,亦可使用|1=subheader 呼叫style 函式取值。預設根據背景色計算。值可以為字串或巢狀表,結構類似"name format" 。
|
["station format"]
|
表或字串 | 是 | 表包括車站格式化字串。首條沒有鍵的記錄(也即鍵為1 的記錄)為預設,餘下的記錄須有匹配輸入的鍵。沒有維基連結括號的格式化字串將會被轉化為連結,輸入(通常為車站名)將會被用作顯示文字。本表可以巢狀表,用於表記傳遞給模板的線路和線路類型選項。
所有巢狀層級下的字串都可以使用 |
["lines"]
|
表 | 是 | 包含資料的線路表。 |
["aliases"]
|
表 | 是 | 包含線路(作為值)的別名(作為鍵)的表。所有的鍵都是小寫,因為輸入將被小寫化,以實現大小寫不敏感。 |
車站格式表 (2)
參數 | 類型 | 被{{Adjacent stations}}使用 | 描述 |
---|---|---|---|
[1]
|
字串 | 是 | 預設格式。 |
["non-default station name"]
|
字串或表 | 是 | 不標準的車站格式,或是由線路確定的格式表。 |
依賴線路的格式表 (3)
參數 | 類型 | 被{{Adjacent stations}}使用 | 描述 |
---|---|---|---|
[1]
|
字串 | 是 | 預設格式。 |
["line name"]
|
字串或表 | 是 | 不標準的車站格式,或是由類型確定的格式表。 |
依賴類型的格式表 (4)
參數 | 類型 | 被{{Adjacent stations}}使用 | 描述 |
---|---|---|---|
[1]
|
字串 | 是 | 預設格式。 |
["type name"]
|
字串 | 是 | 不標準的車站格式。 |
線路表 (3)
可以添加虛擬線路["_default"]
以為所有線路設定預設值。目前對兩個參數有效。
參數 | 類型 | 被{{Adjacent stations}}使用 | 描述 |
---|---|---|---|
["title"]
|
字串 | 是 | 中間儲存格顯示的文字,通常是指向線路條目的連結。若不指定,將會使用["_default"] 下的值(預設值中的%1 為經別名處理的輸入的線路)。
|
["short name"]
|
字串 | 否 | {{Rail color box}}使用的縮寫。 |
["icon"]
|
字串 | 否 | {{Rail icon}}使用的圖像。 |
["icon format"]
|
字串 | 否 | {{Rail icon}}使用的圖像格式。如果指定並且值不為"image" ,圖像資料將交由{{Rail color box}}預處理。
|
["color"]
|
字串 | 是 | RGB十六進制三元值。如果線路自身沒有指定值,將會回落到["_default"] 顏色,乃至系統顏色;類型將依次嘗試取得所線上路、["_default"] 和系統顏色。顏色用於{{Adjacent stations}}的第二和第四列,以及{{Rail color box}}和{{Rail icon}}的強調色。預設地,若類型和線路皆有顏色,那麼線路顏色將會作為中間儲存格背景色(見下一小節)。將類型背景色設為"" 或"transparent" 可以避免。
|
["background color"]
|
字串 | 是 | RGB十六進制三元值(三或六個字元)。顏色是可選的,並只在中間儲存格線路名稱後的背景顯示。本模組會透明化顏色,使其上的文字可識讀。 |
["border color"]
|
字串 | 否 | {{Rail color box}}使用的RGB十六進制三元值。 |
["text color"]
|
字串 | 否 | {{Rail color box}}使用的RGB十六進制三元值。 |
["left terminus"]
|
字串 | 是 | 通常是線路的左終點。若預設有多個值,應巢狀為順序表(如["left terminus"] = {"Chesham", "Amersham"} )。表中的["via"] 鍵可用於在其後加上「經」以及車站連結。
|
["right terminus"]
|
字串 | 是 | 通常是線路的右終點,表現同["left terminus"] 。
|
["note-mid"]
|
字串 | 是 | 顯示線上路和類型下方的預設小號文字。呼叫時由|note-mid= 覆蓋。
|
["circular"]
|
布林型 | 是 | 若值為true ,終點文字將不會顯示「往」。可以被類型覆蓋。
|
["oneway-left"]
|
布林型 | 是 | 若值為true ,那麼左終點站處將會顯示「單向執行」。
|
["oneway-right"]
|
布林型 | 是 | 對應oneway-left的右側版本。 |
["types"]
|
表 | 是 | 巢狀線路類型表的表。 |
類型表 (5)
參數 | 類型 | 被{{Adjacent stations}}使用 | 描述 |
---|---|---|---|
["title"]
|
字串 | 是 | 線路類型的名稱。在{{Adjacent stations}}中顯示為普通大小的文字,位於中間儲存格線路名稱的下方;在{{Rail color box}}中,某些選項下將顯示線上路名稱後,以帶空格的同n寬連接號(亦用於不停站文字)。設為"" 可避免顯示。
|
["short name"]
|
字串 | 否 | {{Rail color box}}使用的縮寫。 |
["icon"]
|
字串 | 否 | {{Rail icon}}使用的圖像。 |
["icon format"]
|
字串 | 否 | {{Rail icon}}使用的圖像格式。如果指定並且值不為"image" ,圖像資料將交由{{Rail color box}}預處理。
|
["color"]
|
字串 | 是 | RGB十六進制三元值。如果線路自身沒有指定值,將會回落到["_default"] 顏色,乃至系統顏色;類型將依次嘗試取得所線上路、["_default"] 和系統顏色。顏色用於{{Adjacent stations}}的第二和第四列,以及{{Rail color box}}和{{Rail icon}}的強調色。預設地,若類型和線路皆有顏色,那麼線路顏色將會作為中間儲存格背景色(見下一小節)。將類型背景色設為"" 或"transparent" 可以避免。
|
["background color"]
|
字串 | 是 | RGB十六進制三元值(三或六個字元)。顏色是可選的,並只在中間儲存格線路名稱後的背景顯示。本模組會透明化顏色,使其上的文字可識讀。 |
["border color"]
|
字串 | 否 | {{Rail color box}}使用的RGB十六進制三元值。 |
["text color"]
|
字串 | 否 | {{Rail color box}}使用的RGB十六進制三元值。 |
["left terminus"]
|
字串 | 是 | 通常是線路的左終點。若預設有多個值,應巢狀為順序表(如["left terminus"] = {"Chesham", "Amersham"} )。表中的["via"] 鍵可用於在其後加上「經」以及車站連結。
|
["right terminus"]
|
字串 | 是 | 通常是線路的右終點,表現同["left terminus"] 。
|
["note-mid"]
|
字串 | 是 | 顯示線上路和類型下方的預設小號文字。呼叫時由|note-mid= 覆蓋。
|
["circular"]
|
布林型 | 是 | 若值為true ,終點文字將不會顯示「往」。
|
關於開發者
本模組及其配套模版是由英語維基人進行編寫和維護。中文維基版將會及時同步英文版本。如果您需要增加新功能,您需要在英文版本的討論頁面提出。
子模組
- ARL
- Adif
- Alpico交通
- Altamont Corridor Express
- Amsterdam Metro
- Amsterdam Metro/doc
- Amtrak
- BART
- BART/doc
- BE
- BTS Skytrain
- Beijing Suburban Railway
- Beijing Subway/sandbox
- Beijing Subway/testcases
- Belgium Railway
- Bern S-Bahn
- Bern S-Bahn/doc
- Brightline
- Brightline/doc
- Brussels Metro
- Brussels tram
- CRH
- CR Chengdu
- CR Kunming
- CR Shanghai
- CTrail
- CTrain
- Caltrain
- Canadian National Railway
- Canadian National Railway/doc
- Changzhou Metro
- China Railway High-speed
- Copenhagen Metro
- Copenhagen S-train
- DB Fernverkehr
- DGRT
- Danhai light rail
- Dongguan Rail Transit
- ERL
- Eurostar
- Exo
- Exo/doc
- Ferries in NSW
- Foshan Metro
- Fuzhou Metro
- GO Transit
- GZM
- Gautrain
- Guangzhou Metro
- HFM
- HZM
- Hangzhou Metro
- Hapi-line Fukui
- Hefei Rail Transit
- IDF
- IDF/doc
- IGR岩手銀河鐵道
- IR石川鐵道
- Israel Railways
- JR Central
- JR East
- Jakarta MRT
- KLRT
- KLRT/doc
- KRT
- KTM
- KTM ETS
- KTM Intercity
- KTM Komuter
- Kaohsiung Rapid Transit
- Keio
- Kunming Metro
- LIRR
- LIRR former
- LIRR former/doc
- Lanzhou Rail Transit
- Los Angeles Metro Busway
- Los Angeles Metro Rail
- Luas
- Luas/doc
- MARC
- MARC/sandbox
- MARC/testcases
- MARTA
- MARTA/doc
- MBTA
- MBTA/doc
- MRL
- MRL/doc
- MRT
- MRTJ
- MTR
- MTR Light Rail
- MUNI
- Macau LRT
- Metra
- Metro-North Railroad
- Metro Trains Melbourne
- Metro Trains Melbourne/doc
- Metrolink (California)
- Metrorail Gauteng
- Metrorail Western Cape
- Metrovalencia
- Metrovalencia/doc
- Mexico City Metro
- Miami-Dade Transit
- Montreal Metro
- Montreal Metro/doc
- NBRT
- NICTD
- NJM
- NJ Transit
- NJ Transit/doc
- NS International
- NYCDOT
- NYCS
- Nanjing Metro
- Nantong Rail Transit
- National Railway Company of Belgium
- New York, Westchester and Boston Railway
- New York City Subway
- New York City Subway/doc
- NingboRT
- Ningbo Rail Transit
- North County Transit District
- North County Transit District/doc
- O-Train
- Odakyu
- Ontario Northland Railway
- PANYNJ
- PANYNJ/doc
- PATH
- Paris Métro
- Pennsylvania Railroad
- Premier Classe
- Pune Metro
- Pune Metro/doc
- REM
- RTD
- RZD
- Rapid KL
- Rapid KL/doc
- Regionalverkehr Bern-Solothurn
- Regionalverkehr Bern-Solothurn/doc
- Rocky Mountaineer
- Rocky Mountaineer/doc
- SEPTA
- SFRTA
- SMRT
- SNCF
- SRT Red Lines
- SRT Red Lines/doc
- SXM
- SZM
- SZRT
- San Diego Trolley
- Seoul Metropolitan Subway
- Seoul Metropolitan Subway/doc
- Shaoxing Metro
- Shenyang Metro
- Shenyang Metro/doc
- Shenzhen Metro
- Shosholoza Meyl
- Skyrail Service
- Sound Transit
- Sound Transit/doc
- Southern Pacific Railroad
- Suzhou Rail Transit
- Swiss Federal Railways
- TER-CVL
- TER-CVL/doc
- TER-GES
- TER-GES/doc
- TER-HDF
- TER-HDF/doc
- TER-HDF/testcases
- TER Hauts-de-France
- TGV
- TGV/doc
- THSR
- TMRT
- TNRT
- TRA
- TRTS
- TaiNan Rapid Transit
- Taichung Mass Rapid Transit
- Taipei Metro
- Taiwan High Speed Rail
- Taiwan Railways Administration
- Thalys
- Toei Subway
- Tokyo Metro
- Tokyu
- Transilien
- Transilien/doc
- Via Rail
- Via Rail/doc
- Virginia Railway Express
- WMATA
- WMATA/doc
- Washington Metro
- Washington Metro/doc
- XAM
- XZM
- XZM/doc
- XiamenRT
- Xuzhou Metro
- Xuzhou Metro/doc
- ZZM
- Zhengzhou Metro
- Zhengzhou Metro/doc
- Zürich S-Bahn
- Zürich S-Bahn/doc
- blank
- doc
- experimental
- experimental/doc
- i18n
- renderSuccessionBox
- sandbox
- successionBox
- testcases
- testcases/Test module
- 一畑電車
- 三一快速鐵路
- 三一鐵路快線
- 三一鐵路快線/doc
- 三岐鐵道
- 三木鐵道
- 三河鐵道
- 三重交通
- 三陸鐵道
- 上信電鐵
- 上毛電氣鐵道
- 上海地鐵
- 上海地鐵/doc
- 上海市域鐵路
- 上海市域鐵路/doc
- 上海磁懸浮/sandbox
- 上田丸子電鐵
- 上田交通
- 上田溫泉電軌
- 上田電鐵
- 下北交通
- 東莞軌道交通
- 中國鐵路
- 中國鐵路/doc
- 中國鐵路上海局集團
- 中國鐵路烏魯木齊局集團
- 中國鐵路蘭州局集團
- 中國鐵路北京局集團
- 中國鐵路南寧局集團
- 中國鐵路南昌局集團
- 中國鐵路呼和浩特局集團
- 中國鐵路哈爾濱局集團
- 中國鐵路太原局集團
- 中國鐵路廣州局集團
- 中國鐵路成都局集團
- 中國鐵路昆明局集團
- 中國鐵路武漢局集團
- 中國鐵路瀋陽局集團
- 中國鐵路濟南局集團
- 中國鐵路西安局集團
- 中國鐵路鄭州局集團
- 中國鐵路青藏集團
- 中國高速鐵路
- 烏魯木齊地鐵
- 九州旅客鐵道
- 九州鐵道
- 井原鐵道
- 京成電氣軌道
- 京成電鐵
- 京濱急行電鐵
- 京王電鐵
- 京福電氣鐵道
- 京都丹後鐵道
- 京都市營地下鐵
- 京阪電氣鐵道
- 仙台市地下鐵
- 仙台機場鐵道
- 伊予鐵道
- 伊勢鐵道
- 伊豆急行
- 伊豆箱根鐵道
- 伊賀鐵道
- 佛山地鐵
- 佛山地鐵/doc
- 信樂高原鐵道
- 信濃鐵道
- 優等列車
- 光州都市鐵道
- 光谷空軌
- 六甲山觀光
- 蘭州軌道交通
- 別府鐵道
- 加悅鐵道
- 加能越鐵道
- 加越能鐵道
- 北九州高速鐵道
- 北京地鐵
- 北京地鐵/doc
- 北京市郊鐵路
- 北大阪急行電鐵
- 北惠那鐵道
- 北條鐵道
- 北海道拓殖鐵道
- 北海道旅客鐵道
- 北海道池北高原鐵道
- 北海道鐵道 (第二代)
- 北總鐵道
- 北越急行
- 北陸鐵道
- 十和田觀光電鐵
- 千葉都市單軌電車
- 南京地鐵
- 南京地鐵/doc
- 南寧軌道交通
- 南昌地鐵
- 南昌地鐵/doc
- 南海電氣鐵道
- 南通軌道交通
- 南部縱貫鐵道
- 南阿蘇鐵道
- 廈門軌道交通
- 叡山電鐵
- 台中捷運
- 台中捷運/doc
- 台北捷運
- 台州軌道交通
- 台灣高鐵
- 合肥軌道交通
- 合肥軌道交通/doc
- 吉隆坡捷運
- 吉隆坡機場快鐵
- 吉隆坡機場快鐵/doc
- 名古屋導向巴士
- 名古屋市營地下鐵
- 名古屋臨海高速鐵道
- 名古屋鐵道
- 呼和浩特地鐵
- 和歌山電鐵
- 哈爾濱地鐵
- 哥本哈根地鐵
- 哥本哈根市郊鐵路
- 嘉興
require('strict')
local p = {}
local lang = 'zh-CN' -- 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 line[k] = line[k] 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 .. ' 曾是 "' .. key .. '" 但既没有找到它的条目,也没有找到默认值。选择是: ' .. table.concat(formatKeys, ', ')
end
local function getStation(station, _Format)
if type(_Format) == 'table' then
local lineNformats = _Format
_Format = lineNformats[lineN] or lineNformats[1]
if not _Format then
error(somethingMissing('lineN', lineN, lineNformats))
elseif type(_Format) == 'table' then
local typeNformats = _Format
_Format = typeNformats[typeN] or typeNformats[1]
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, (Format[var1] or Format[1]))
or type(var1) == 'table' and #var1 > 0 and getStation(var1[var2], (Format[var1[var2]] or Format[1]))
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
t[i] = i18n[lang]['comma'](subst(var, i))
end
if #var > 1 then t[#var] = i18n[lang]['or'](subst(var, #var)) end
if var['via'] then
if i18n[lang]['via-first'] then
table.insert(t, 1, i18n[lang]['via'](subst(var, 'via')))
else
table.insert(t, i18n[lang]['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
_args[k] = v:match('^%s*(.-)%s*$')
if _args[k] and _args[k] ~= '' 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 boolean[a] then
v = yesno(v)
end
if not args[b] then
args[b] = {[a] = v}
table.insert(index, b)
elseif args[b][a] then
return error(i18n[lang]['error_duplicate'](a .. b))
else
args[b][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="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
data[v] = args[v]['system'] and getData(args[v]['system'])
-- If an address has no system, the row uses data from the previous address
or data[index[i - 1]]
or (args[v]['header'] and getData(args[index[i+1]]['system']))
or error(i18n[lang]['error_unknown'](args[v]['system']))
local lang = data[v]['lang'] or lang
if args[v]['system'] and not args[v]['hide-system'] then -- Header row
local stop_noun = data[v]['header stop noun'] or i18n[lang]['stop_noun']
table.insert(wikitable, table.concat({'\n|-',
'\n!', style['header cell'], i18n[lang]['preceding'](stop_noun),
'\n!', style['header midcell'], (data[v]['system icon'] and data[v]['system icon'] .. ' ' or ''), (data[v]['system title'] or ('[['.. args[v]['system'] ..']]')),
'\n!', style['header cell'], i18n[lang]['following'](stop_noun)
}))
table.insert(wikitable, '')
table.insert(wikitable, '')
table.insert(wikitable, '')
end
if args[v]['header'] then -- Subheader
table.insert(wikitable, '\n|-\n!colspan="5" class="hmA"|'.. args[v]['header'])
table.insert(wikitable, '')
table.insert(wikitable, '')
table.insert(wikitable, '')
end
if args[v]['line'] or args[v]['left'] or args[v]['right'] or args[v]['nonstop'] then
if not args[v]['line'] and i > 1 and not args[v]['system'] then
args[v]['line'] = args[index[i - 1]]['line']
end
lineN = args[v]['line'] or '_default'
typeN = args[v]['type']
if data[v]['aliases'] then
lineN = data[v]['aliases'][mw.ustring.lower(lineN)] or lineN
if typeN then typeN = data[v]['aliases'][mw.ustring.lower(typeN)] or typeN end
end
-- get the line table
local line = data[v]['lines'] and (mw.clone(data[v]['lines'][lineN]) or error(i18n[lang]['error_unknown'](args[v]['line']))) or error(i18n[lang]['error_line'])
local default = data[v]['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 args[v]['nonstop'] then
table.insert(wikitable,
table.concat({'\n|-\n|colspan="5" ',
style['body cell'],
((args[v]['nonstop'] == 'former') and i18n[lang]['nonstop_past'] or i18n[lang]['nonstop_present'])(p._box({data = data[v], line = lineN, Type = typeN, inline = 'yes'}))
})
)
table.insert(wikitable, '')
table.insert(wikitable, '')
table.insert(wikitable, '')
else
local Format = data[v]['station format'] or i18n[lang]['error_format']
local color, 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']
elseif Type['background color'] then
background_color = Type['background color']
color = line['color'] or default['color'] or ''
else
background_color = line['background color']
color = line['color'] or default['color'] or ''
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 ''
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 args[v][b] then -- If no station is given on one side, the station is assumed to be the terminus on that side
local _through = args[v]['through-' .. b] or args[v]['through']
local _through_data = getLine(data[v], _through)
if _through_data then _through = _through_data['title'] or _through end
sideCell[i] = _through and "''" .. i18n[lang]['through'](trimq(_through)) .. "''"
or "''" .. trimq((args[v]['reverse-' .. b]
or args[v]['reverse']) and i18n[lang]['reverse']
or i18n[lang]['terminus']) .. "''"
else
local terminusT
local terminusN = Type and Type[b .. ' terminus'] or line[b .. ' 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 (terminusN[2] or terminusN['via'])) then
if args[v]['to-' .. b] then
terminusT = args[v]['to-' .. b]
local _or = mw.ustring.match(terminusT, i18n[lang]['or-format'])
if _or then
terminusT = mw.ustring.gsub(terminusT, i18n[lang]['or-format'], '\127_OR_\127')
terminusT = mw.ustring.gsub(terminusT, i18n[lang]['comma-format'], '\127_OR_\127')
end
local _via = (mw.ustring.match(terminusT, i18n[lang]['via-format']))
if _via then
terminusT = mw.ustring.gsub(terminusT, i18n[lang]['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 = terminusN[args[v]['to-' .. b]] or terminusN[args[v]['to']] or terminusN[1]
end
local mainText = args[v]['note-' .. b] and getTerminusText(args[v][b], Format) .. small(args[v]['note-' .. b]) or getTerminusText(args[v][b], Format)
local subText = (args[v]['oneway-' .. b] or line['oneway-' .. b]) and i18n[lang]['oneway']
or args[v][b] == terminusT and i18n[lang]['terminus']
or circular and terminusT
or i18n[lang]['towards'](getTerminusText(terminusT, Format))
subText = small(subText, true)
sideCell[i] = mainText .. subText
end
end
table.insert(wikitable, '\n|-')
table.insert(wikitable, '\n|' .. style['body cell'] .. sideCell[1])
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
((args[v]['note-mid'] and small(args[v]['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
(args[v]['transfer'] and small('于' .. getTerminusText(args[v]['transfer'], Format) .. '换乘', true) or ''),
'\n|', style['body banner'], color, '"|'}))
table.insert(wikitable, '\n|' .. style['body cell'] .. sideCell[2])
end
end
if args[v]['note-row'] then -- Note
table.insert(wikitable, '\n|-\n|colspan="5" ' .. style['body cell'] .. args[v]['note-row'])
table.insert(wikitable, '')
table.insert(wikitable, '')
table.insert(wikitable, '')
end
end
local function combine(t, n)
if t[n + 4] ~= '' and t[n + 4] == t[n] then
t[n + 4] = '' -- The cell in the next row is deleted
local rowspan = 2
while t[n + rowspan * 4] == t[n] do
t[n + rowspan * 4] = ''
rowspan = rowspan + 1
end
t[n] = mw.ustring.gsub(t[n], '\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 p[funcName](args, frame)
end
end
p.main = makeInvokeFunction('_main')
function p._color(args, frame)
local data = args.data
if args[1] or data then
data = data or getData(args[1], true)
if not data then return getColor(nil, args[1], args[2], args[3], frame) end
return getColor(data, nil, args[2], args[3])
end
end
p.color = makeInvokeFunction('_color')
function p._box(args, frame)
local system = args[1] or args.system
lineN = args[2] or args.line
if not (system or lineN) then return '' end
local line, Type, line_data
local inline = args[3] 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(i18n[lang]['error_unknown'](lineN))
line = line_data['title'] or default['title'] or error(i18n[lang]['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(i18n[lang]['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;width:1.5em;height:1.5em;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
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']
lineN = Type_data['short name'] or line_data['short name'] or lineN
else
border_color = line_data['border color'] or color
text_color = line_data['text color']
lineN = line_data['short name'] or lineN
end
else
border_color = color
end
local greatercontrast = require('Module:Color contrast')._greatercontrast
text_color = text_color and '#' .. text_color or greatercontrast{color}
local bold = (yesno(args.bold) == false) or ';font-weight:bold'
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
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;width:1.5em;height:1.5em;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 = args[1] 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, args[2] or args.line)
local icon
local icon_format
if line then
local line_type = args[3] or args.type
if line_type then
line_type = data.aliases and data.aliases[mw.ustring.lower(line_type)] or line_type
line_type = line.types and line.types[line_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] = (args[2] or args.line), [3] = icon_format, type = (args[3] 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, regex[1]) then
icon = mw.ustring.gsub(icon, regex[1], 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 = args[1] or args.system
local line = args[2] or args.line
if not line then return '' end
local Type = args[3] 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(i18n[lang]['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(i18n[lang]['error_missing']('title'))
else
line = frame:expandTemplate{ title = system .. ' lines', args = {line, ['branch'] = Type} }
if mw.text.trim(line) == '' then return error(i18n[lang]['error_unknown'](lineN)) end
end
if Type then
if line == '' then
line = Type
else
line = line .. ' – ' .. Type
end
end
return line
end
end
p.line = makeInvokeFunction('_line')
function p._station(args, frame)
local system = args[1] or args.system
local station = args[2] or args.station
if not station then return '' end
lineN = args[3] or args.line
typeN = args[4] 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 = args[1] or args.system
lineN = args[2] or args.line
local side = mw.ustring.sub(mw.ustring.lower(args[3] 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(i18n[lang]['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 Type[prefix .. ' terminus'] or line[prefix .. ' terminus'], data['station format'] or i18n[lang]['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 = args[1] or args.style
local system = args[2] or args.system
local line = args[3] or args.line
local station = args[4] 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 = var[line] or var[1]
if type(var) == 'table' then
var = var[station] or var[1]
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(args[1], '^%s*{{(.*)}}%s*$', '%1'), '%s*}}%s*{{%s*')
local system
local group = 0
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
code[i] = mw.ustring.gsub(code[i], '\n', ' ')
local template = mw.ustring.lower(mw.text.trim(mw.ustring.match(code[i], '^[^|]+')))
code[i] = mw.ustring.match(code[i], '(|.+)$')
if (mw.ustring.match(code[i] or '', 'noclear%s*=%s*[a-z]')) then
noclear = true
end
if template == 's-line' then
data[i] = {}
local this_system = mw.text.trim(mw.ustring.match(code[i], '|%s*system%s*=([^|]+)'))
code[i] = mw.text.split(code[i], '%s*|%s*')
for m, n in ipairs(code[i]) do
local tmp = mw.text.split(n, '%s*=%s*')
if tmp[3] then
tmp[2] = mw.ustring.gsub(n, '^.-%s*=', '')
end
tmp[1] = replace[tmp[1]] or tmp[1]
if tmp[2] then
-- checks for matching brackets
local curly = select(2, mw.ustring.gsub(tmp[2], "{", ""))-select(2, mw.ustring.gsub(tmp[2], "}", ""))
local square = select(2, mw.ustring.gsub(tmp[2], "%[", ""))-select(2, mw.ustring.gsub(tmp[2], "%]", ""))
if not (curly == 0 and square == 0) then
local count = mw.clone(m)+1
while not (curly == 0 and square == 0) do
tmp[2] = tmp[2]..'|'..code[i][count]
curly = curly+select(2, mw.ustring.gsub(code[i][count], "{", ""))-select(2, mw.ustring.gsub(code[i][count], "}", ""))
square = square+select(2, mw.ustring.gsub(code[i][count], "%[", ""))-select(2, mw.ustring.gsub(code[i][count], "%]", ""))
code[i][count] = ''
count = count+1
end
end
data[i][tmp[1]] = tmp[2]
end
end
if (this_system ~= system) or (not system) then
system = this_system
data[i]['system'] = system
else
data[i]['system'] = nil
end
local last = data[i-1] or data[i-2] or data[i-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 data[i][r] then
for m, n in ipairs(s) do
if not data[i][n] then
data[i][n] = last[n]
end
end
end
end
end
code[i] = {}
local X = '|'
local Y = (i+group)..'='
if data[i]['system'] then
table.insert(code[i], '|system')
table.insert(code[i], Y)
table.insert(code[i], data[i]['system'])
table.insert(code[i], '\n')
end
for m, n in ipairs(order) do
if data[i][n] then
table.insert(code[i], X)
table.insert(code[i], n)
table.insert(code[i], Y)
table.insert(code[i], data[i][n])
end
end
code[i] = table.concat(code[i])
elseif template == 's-note' then
code[i] = mw.ustring.gsub(code[i], '|%s*text%s*=', '|header'..i+group..'=')
code[i] = mw.ustring.gsub(code[i], '|%s*wide%s*=[^|]*', '')
elseif template == 's-text' then
code[i] = mw.ustring.gsub(code[i], '|%s*text%s*=', '|note-row'..i+group..'=')
elseif delete[template] then
code[i] = ''
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) > 1 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|system1='..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=')
t[2] = '}}'
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 t[1]..code..t[2]
end
return p