模組:Ttctools
模組解[開]
你可能想去為呢個Scribunto module開一個解版。 編者可以響呢個模組嘅沙盤 (開 | 鏡)同埋試例 (開)版度試驗佢。 請加個類到個/doc嘅細版度。 呢個模組嘅細版。 |
-- vim: set sw=4 ts=4 noet ai sm :
---- 呢個係用嚟喺維基架構之內處理多倫多公車局相關文章嘅大量重覆或者非常難排版嘅資訊
---- 2023年粵維原創
require ('strict');
local p = {};
local styles = 'Template:多倫多公車局/styles.css';
if true then
local z = require('模組:書名');
p.cvs = z.cvs;
p.cjk_p = z.cjk_p;
p.array_p = z.array_p;
end
--- 基本資料
local lines = {
['1'] = {
aliases = {'YUS'};
link = '多倫多地下鐵1號綫';
name = '一號綫';
icon = 'File:TTC - Line 1 - Yonge-University-Spadina line.svg';
livery = 'f8c300';
};
['2'] = {
aliases = {'BD'};
link = '多倫多地下鐵2號綫';
name = '二號綫';
icon = 'File:TTC - Line 2 - Bloor-Danforth line.svg';
livery = '00923f';
};
['3a'] = {
aliases = {'SRT'};
link = '士嘉堡 RT';
name = '士嘉堡 RT';
icon = 'File:TTC - Line 3 - Scarborough RT line.svg';
livery = '0082c9';
};
['3b'] = {
aliases = {'Ontario'};
link = '安大略綫';
name = '安大略綫';
icon = 'File:TTC - Line 3 - Scarborough RT line.svg';
livery = '0082c9';
};
['4'] = {
aliases = {'Sheppard'};
link = '多倫多地下鐵4號綫';
name = '雪柏綫';
icon = 'File:TTC - Line 4 - Sheppard line.svg';
livery = 'a21a68';
};
['5'] = {
aliases = {'ECLRT'};
link = '艾靈頓跨城輕鐵綫';
name = '艾靈頓跨城輕鐵綫';
icon = 'File:TTC - Line 5.svg';
livery = 'f87005'; -- 假定圖標嘅色冇錯
};
['6'] = {
aliases = {'FWLRT'};
link = '芬治西輕鐵綫';
name = '芬治西輕鐵綫';
icon = 'File:TTC - Line 6.svg';
livery = '888888'; -- 假定圖標嘅色冇錯
};
['7'] = {
aliases = {'EELRT'};
link = '艾靈頓東輕鐵綫';
name = '艾靈頓東輕鐵綫';
icon = 'File:TTC - Line 7.svg';
};
['WELRT'] = {
link = '湖濱東輕鐵綫';
name = '湖濱東輕鐵綫';
};
['501'] = {
-- 301 is roughly the same route but not identical (different in the middle)
aliases = {'301'};
link = '多倫多街車501號綫';
name = '501/301號綫';
icon = 'File:TTC - 501.svg';
};
['503'] = {
link = '多倫多街車503號綫';
name = '503號綫';
icon = 'File:TTC - 503.svg';
};
['504'] = {
-- 304 is roughly the same route but not identical (no Dundas West; quite different near Broadview)
aliases = {'304'};
link = '多倫多街車504號綫';
name = '504/304號綫';
icon = 'File:TTC - 504.svg';
};
['505'] = {
link = '多倫多街車505號綫';
name = '505號綫';
icon = 'File:TTC - 505.svg';
};
['506'] = {
-- 306 is very similiar but not identical; east of Sorauren is completely different
aliases = {'306'};
link = '多倫多街車506號綫';
name = '506/306號綫';
icon = 'File:TTC - 506.svg';
};
['507'] = {
link = '多倫多街車507號綫';
name = '507號綫';
icon = 'File:TTC - 507.svg';
};
['508'] = {
link = '多倫多街車508號綫';
name = '508號綫';
icon = 'File:TTC - 508.svg';
};
['509'] = {
link = '多倫多街車509號綫';
name = '509號綫';
icon = 'File:TTC - 509.svg';
};
['510'] = {
-- 310 is similiar but actually quite different in the middle
aliases = {'310'};
link = '多倫多街車510號綫';
name = '510/310號綫';
icon = 'File:TTC - 510.svg';
};
['511'] = {
link = '多倫多街車511號綫';
name = '511號綫';
icon = 'File:TTC - 511.svg';
};
['512'] = {
link = '多倫多街車512號綫';
name = '512號綫';
icon = 'File:TTC - 512.svg';
};
}
if true then -- 重組 lines 定義,將 aliases 全部加入索引
local index = {};
local annotation = '';
local prefix = '';
for k, v in pairs(lines) do
index[k] = v;
if v.aliases then
annotation = annotation .. prefix;
local prefix = annotation .. k .. ' 定義咗';
for _, alias in pairs(v.aliases) do
if lines[alias] or index[alias] then
error('lines 定義出錯,' .. k .. ' 嘗試定義 alias = ' .. alias .. ',但係已經有呢個名(' .. annotation .. ')');
end
index[alias] = v;
annotation = prefix .. alias;
prefix = '、';
end
end
prefix = ',';
end
lines = index;
end
--- Auxiliaries
local function interpret_boolean( s )
local it;
if type(s) == 'boolean' then
it = s;
else
it = s:match('^%s*true%s*$')
or s:match('^%s*yes%s*$')
or s:match('^%s*0*1%s*$');
end
return it;
end
local function new_Entrance (s)
-- not doing anything for now. Just check the keys to make sure no unknown keys (ie typos) are present
local self = {};
if not p.array_p(s) then
error('new_Entrance: 實際參數唔係陣列(數值:' .. p.cvs(s) .. ')');
end
for i, a in pairs(s) do
local node = {};
for k, v in pairs(a) do
if k == 'website' then
node.website = v;
elseif k == 'active' then
node.active_p = interpret_boolean(v);
elseif k == 'directional' or k == 'directional sign' then
node.directional = v;
elseif k == 'identification' or k == 'identification sign' then
node.identification = v;
elseif k == 'outside' then
node.outside = v;
elseif k == 'inside' then
node.inside = v;
elseif k == 'up' or k == 'dir' then
node.dir = v;
elseif k == 'at' or k == 'building' then
node.building = v;
elseif k == 'intersection' then
node.intersection = v;
elseif k == 'corner' then
node.corner = v;
elseif k == 'side' then
node.side = v;
elseif k == 'link' then
node.link = v;
elseif k == 'note' then
node.note = v;
elseif k == 'def' then
node.def = new_Entrance(v);
elseif k:sub(1, 2) ~= 'x-' then
error('new_Entrance: 實際參數遇到不明欄位「' .. k .. '」(數值:' .. p.cvs(v) .. ')');
end
end
table.insert(self, node);
end
return self;
end
local function icon_size( icon )
local it;
if icon:match('^File:TTC +- +Line ') then
it = 16;
elseif icon:match('^File:TTC +- +%d+%.') then
it = 28;
end
return it;
end
local function remove_tags( s )
local it;
if s then
it = s:gsub('<[^<>]*>', ''):gsub("'''", ''):gsub("''", '');
end
return it;
end
local function handle_breaks( s )
local it = s;
local sep = mw.ustring.char(0x200b); -- separator to match
local sep2 = sep; -- separator to add back
if mw.ustring.match(s, sep) then
local a = mw.text.split(s, sep, true);
local n = #a;
if a[n] == '' then
n = n - 1;
end
it = '';
for i = 1, n, 1 do
if i > 1 then
it = it .. sep2;
end
it = it .. '<span style="white-space:nowrap">' .. a[i] .. '</span>';
end
end
return it;
end
local function join_segments( a, b )
local it;
if #a == 0 or #b == 0 or (#a > 0 and #b > 0 and p.cjk_p(mw.ustring.sub(a, -1)) and p.cjk_p(mw.ustring.sub(b, 1, 1))) then
it = a .. b;
else
it = a .. ' ' .. b;
end
return it;
end
local function entrance_canonicalized( s )
-- try to reduce labelling "website version" of entrance names when the name is practically the same as what's on the sign
s = mw.ustring.gsub(mw.ustring.lower(s), '%s+street', ' st.');
s = mw.ustring.gsub(s, '%s+entrance', '');
s = mw.ustring.gsub(s, '%s%(([^%(%)]+)%)$', ' / %1');
s = mw.ustring.gsub(s, '%s+$', '');
return s;
end
local function show_icon( args )
local it;
if not args or not args.line then
error('冇指定路綫(實際參數:' .. p.cvs(args) .. ')');
elseif not lines[args.line] then
error('指定咗路綫' .. p.cvs(args.line) .. ',但係模組冇呢條綫嘅資料');
elseif not lines[args.line].icon then
error('指定咗路綫' .. p.cvs(args.line) .. ',但係手頭上嘅資料入面冇圖標');
end
local size = icon_size(lines[args.line].icon);
it = '<span class=ttc-icon>[[' .. lines[args.line].icon;
if size then
it = it .. '|' .. size .. 'px';
end
it = it .. ']]</span>';
return it;
end
local function show_name( args )
local it;
if not args or not args.line then
error('冇指定路綫(實際參數:' .. p.cvs(args) .. ')');
elseif not lines[args.line] then
error('指定咗路綫' .. p.cvs(args.line) .. ',但係模組冇呢條綫嘅資料');
elseif not lines[args.line].name then
error('指定咗路綫' .. p.cvs(args.line) .. ',但係手頭上嘅資料入面冇名');
end
local name = lines[args.line].name;
local link = lines[args.line].link;
if link and not args.no_link_p then
it = '[[' .. link;
if link ~= name then
it = it .. '|' .. name;
end
it = it .. ']]';
else
it = name;
end
return it;
end
local function show_icon_and_name( args )
local it;
if not args or not args.line then
error('冇指定路綫(實際參數:' .. p.cvs(args) .. ')');
elseif not lines[args.line] then
error('指定咗路綫' .. p.cvs(args.line) .. ',但係模組冇呢條綫嘅資料');
elseif not lines[args.line].name then
error('指定咗路綫' .. p.cvs(args.line) .. ',但係手頭上嘅資料入面冇名');
end
local name = lines[args.line].name;
local link = lines[args.line].link;
if lines[args.line].icon then
it = show_icon(args) .. ' ';
else
it = '';
end
it = it .. show_name(args);
return it;
end
local function show_livery( args )
local it;
if not args or not args.line then
error('冇指定路綫(實際參數:' .. p.cvs(args) .. ')');
elseif not lines[args.line] then
error('指定咗路綫' .. p.cvs(args.line) .. ',但係模組冇呢條綫嘅資料');
end
local livery = lines[args.line].livery;
if not livery then
it = '';
else
it = '#' .. livery;
end
return it;
end
-- 地下鐵出入口註釋
-- display a disclaimer about Toronto's bad EGD
local function make_disclaimer( subhead, message )
return '<div class=ttc-disclaimer>'
.. "<span class=disclaimer-icon>[[File:Stop-hand-caution.png|32px|alt='''" .. subhead .. "''':]]</span>"
.. '<span class=disclaimer-message>' .. message .. '</span></div>';
end
local function show_disclaimer( args )
local it = '';
local city = args.city;
if not city then
city = '多倫多';
end
local network = args.network;
if not network then
network = '地鐵網';
end
local source = args.source;
if not source then
source = '官方網站';
end
if source then
it = it .. join_segments('下列出入口次序係跟', source) .. ',未必合理。';
end
it = it .. join_segments(join_segments(city, network), "嘅出入口冇編號,好多時亦唔寫地標(淨寫街名");
if mw.ustring.match(network, '地') then -- FIXME
it = it .. "、東南西北、同(如果適用)[[多倫多街車|街車]]嘅行車方向)。";
else
it = it .. "同東南西北。";
end
it = it .. "同一個站入面,";
if mw.ustring.match(source, '官') then -- FIXME
it = it .. "一個出口可能唔止一個名,名好多時唔係網站寫嘅版本,甚至";
end
it = it .. "唔同出口可能會撞名。";
it = make_disclaimer('注意', it);
return it;
end
-- 車站樓層
-- produce a station structure diagram, mimicking the manual formatting expected on yuewiki
local function draw_station_description( s )
if not p.array_p(s) then
error('車站樓層參數唔係陣列(' .. p.cvs(s) .. ')');
elseif #s == 0 then
error('車站樓層參數係空陣列');
end
local it = '{|table border=0 cellspacing=0 cellpadding=3 class="ttc-station-structure"\n';
local blank_divider = '|style="padding:1px;" colspan=3|\n';
local solid_divider = '|style="border-bottom:solid 1px gray;padding:1px;" colspan=3|\n';
local dashed_divider = '|style="border-bottom:dashed 1px gray;padding:1px;" colspan=3|\n';
it = it .. '|-\n';
for i = 1, #s, 1 do
local curr = s[i];
local prev, next;
if i > 1 then
prev = s[i - 1];
end
if i < #s then
next = s[i + 1];
end
if type(curr) ~= 'table' then
error('車站樓層參數嘅第' .. i .. '個元素唔係物件');
elseif not curr.name then
error('車站樓層參數嘅第' .. i .. '個元素冇 name');
elseif not curr.def then
error('車站樓層參數嘅第' .. i .. '個元素冇 def');
elseif not p.array_p(curr.def) then
error('車站樓層參數嘅第' .. i .. '個元素嘅 def 唔係陣列');
elseif not #curr.def then
error('車站樓層參數嘅第' .. i .. '個元素嘅 def 係空陣列');
end
if prev and not curr.level then
it = it .. dashed_divider;
else
it = it .. solid_divider;
end
it = it .. '|-\n';
it = it .. blank_divider;
it = it .. '|-\n';
if p.array_p(curr.def[1]) then -- 唔係月台
local n = 0; -- need to first figure out total number of rows needed
for j = 1, #curr.def, 1 do
local det = curr.def[j][2];
n = n + #det;
end
for j = 1, #curr.def, 1 do
if j == 1 then
it = it .. '|width=50 rowspan=' .. n .. ' valign=top|';
it = it .. "'''";
if curr.level then
it = it .. curr.level .. '<br />';
end
it = it .. handle_breaks(curr.name) .. "'''\n";
end
local det = curr.def[j][2];
if j < #curr.def then
it = it .. '|style="border-bottom:solid 1px gray;" rowspan=' .. #det .. ' valign=top|' .. curr.def[j][1] .. '\n';
else
it = it .. '|rowspan=' .. #det .. ' valign=top|' .. curr.def[j][1] .. '\n';
end
for k = 1, #det, 1 do
if k == #det and j < #curr.def then
it = it .. '|style="border-bottom:solid 1px gray;" valign=top|' .. det[k] .. '\n';
else
it = it .. '|valign=top|' .. det[k] .. '\n';
end
it = it .. '|-\n';
end
end
else -- 月台
for j = 1, #curr.def, 1 do
if j == 1 then
it = it .. '|width=50 rowspan=' .. #curr.def .. ' valign=top|';
it = it .. "'''";
if curr.level then
it = it .. curr.level .. '<br />';
end
it = it .. handle_breaks(curr.name) .. "'''\n";
end
local tb;
if curr.def[j].type:match('^platform ') then
tb = '';
if j == 1 or not curr.def[j - 1].type:match('^platform ') then
tb = tb .. 'border-top:solid 2px black;';
end
if j == #curr.def or not curr.def[j + 1].type:match('^platform ') then
tb = tb .. 'border-bottom:solid 2px black;';
end
if curr.def[j].wall then
if j > 1 and curr.def[j - 1].type:match('^platform ') then
tb = tb .. 'border-top:dashed 1px gray;';
end
if j < #curr.def and curr.def[j + 1].type:match('^platform ') then
tb = tb .. 'border-bottom:dashed 1px gray;';
end
tb = tb .. 'background-color:#eee;';
end
end
if curr.def[j].type == 'track' then
if j < #curr.def and curr.def[j + 1].type == 'track' then
it = it .. '|style="border-bottom:solid 1px gray" width=100 valign=top|\n';
it = it .. '|style="border-bottom:solid 1px gray" width=285 valign=top|路軌\n';
else
it = it .. '|width=100|\n';
it = it .. '|width=285|路軌\n';
end
elseif curr.def[j].type == 'platform edge' then
it = it .. '|style="' .. tb .. 'border-left:solid 2px black;"|';
if curr.def[j].id then
it = it .. curr.def[j].id;
end
it = it .. '\n';
it = it .. '|style="' .. tb .. 'border-right:solid 2px black;"|'
if curr.def[j].dir then
it = it .. curr.def[j].dir;
end
if curr.def[j].note then
it = it .. ' <small>' .. curr.def[j].note .. '</small>\n';
end
it = it .. '\n';
elseif curr.def[j].type == 'platform type' then
it = it .. '|style="border-right:solid 2px black;border-left:solid 2px black;'
.. tb .. '" colspan=2|<center><small>' .. curr.def[j].desc .. '</small></center>\n';
end
it = it .. '|-\n';
end
end
end
it = it .. solid_divider;
it = it .. '|-\n';
it = it .. '|}';
return it;
end
-- 出入口
-- produce a list of entrances, somewhat mimicking the manual formatting expected on yuewiki
-- except Toronto EGD is garbage so the output will look somewhat like not identical to other lists
local function render_floor_sequence( s )
local it;
if type(s) == 'table' then
it = '';
for i = 1, #s, 1 do
if i > 1 then
if s[i] < s[i - 1] then
it = it .. '↗';
elseif s[i] == s[i - 1] then
it = it .. '→';
else
it = it .. '↘';
end
end
it = it .. s[i];
end
else
it = s;
end
return it;
end
local function show_entrance( a, fake_id, aux, parent )
local it;
local official, actual;
local comments = {};
local position;
official = a.website;
if a.identification then
actual = a.identification;
elseif a.directional then
actual = a.directional;
end
if official and not actual then
it = official;
if a.side then
it = it .. '(' .. a.side .. '冇牌出口' .. ')';
end
elseif official and entrance_canonicalized(official) ~= entrance_canonicalized(actual) then
it = "'''" .. actual .. "'''";
table.insert(comments, '網上名稱:' .. official);
elseif actual then
it = "'''" .. actual .. "'''";
elseif a.side then
it = a.side .. '冇牌出口'; -- 其實冇記認,淨係有嘜低轉左轉右
else -- you can't make this stuff up
it = "冇記認亦冇紀錄";
end
if actual then
if aux[actual] then
table.insert(aux[actual], fake_id);
else
aux[actual] = { fake_id };
end
end
if a.active_p ~= nil and not a.active_p then
it = '🚫 ' .. it; -- U+1F6ab
end
if not a.def then
position = {};
for _, x in pairs({parent, a}) do
if x then
if x.inside then
position.inside = x.inside;
end
if x.outside then
position.outside = x.outside;
end
if x.intersection then
position.intersection = x.intersection;
end
if x.corner then
position.corner = x.corner;
end
if x.building then
position.building = x.building;
end
if x.dir then
position.dir = x.dir;
end
end
end
end
if position then
if position.intersection and #position.intersection > 3 then
error(cvs.p('intersection ' .. position.intersection) .. ' 多過3個元素');
elseif position.intersection and #position.intersection == 3 then
local comment = position.intersection[1] .. ',' .. position.intersection[2];
comment = join_segments(join_segments(comment, join_segments('同', position.intersection[3])), '之間');
if position.corner then
comment = comment .. ',' .. position.corner;
end
table.insert(comments, '位置:' .. comment);
elseif position.intersection and #position.intersection == 2 then
local comment = join_segments(join_segments(position.intersection[1], '夾'), position.intersection[2]);
if position.corner then
comment = join_segments(comment, position.corner);
end
table.insert(comments, '位置:' .. comment);
elseif position.intersection and position.corner then
table.insert(comments, '位置:' .. join_segments(position.intersection[1], position.corner));
end
end
if #comments > 0 then
it = it .. '(' .. table.concat(comments, ';') .. ')';
end
if position then
if position.inside then
if position.outside then
it = it .. ',' .. render_floor_sequence(position.inside);
else
it = it .. ',站入面係' .. render_floor_sequence(position.inside);
if type(position.inside) == 'number' or position.inside:match('^%d+$') then
it = it .. '字樓';
end
end
end
if position.outside then
if position.dir then
if position.dir > 0 then
it = it .. '↗';
elseif position.dir < 0 then
it = it .. '↘';
else
it = it .. '→';
end
else
it = it .. ',';
end
it = it .. join_segments('出', position.outside);
end
if position.building then
it = it .. '(' .. position.building .. ')';
end
if a.note then
it = it .. ',' .. a.note;
end
end
it = it .. '\n';
return it;
end
local function find_dup_entrances( aux )
local it;
local next_number = 1;
for actual, fake_ids in pairs(aux) do
if #fake_ids > 1 then
if not it then
it = {};
it.number_for_name = {};
it.notes = {};
end
for _, fake_id in pairs(fake_ids) do
if not it.number_for_name[actual] then
it.number_for_name[actual] = next_number;
it.notes[next_number] = fake_ids;
next_number = next_number + 1;
end
it[fake_id] = actual;
end
end
end
return it;
end
local function conjoin( L )
local it;
if #L == 1 then
it = L[1];
elseif #L == 2 then
it = join_segments(join_segments(L[1], '同'), L[2]);
elseif L > 2 then
it = join_segments(table.concat(L, '、', 1, #L - 1) '同', L[#L]);
end
return it;
end
local function chart_entrances( s )
if not p.array_p(s) then
error('出入口參數唔係陣列(' .. p.cvs(s) .. ')');
elseif #s == 0 then
error('出入口參數係空陣列');
end
local it;
local aux = {};
local items = {};
for i, a in pairs(s) do
local A = mw.ustring.char(64 + i);
table.insert(items, { indent = '*', fake_id = A, value = show_entrance(a, A, aux) });
if a.def then
for j, b in pairs(a.def) do
local B = A .. j;
table.insert(items, {indent = '**', fake_id = B, value = show_entrance(b, B, aux, a)});
end
end
end
if items then
local dups = find_dup_entrances(aux);
it = '<div class=ttc-entrances>\n';
for _, node in pairs(items) do
it = it .. node.indent;
if dups and dups[node.fake_id] then
it = it .. '<sup>(' .. node.fake_id .. ')</sup> ';
end
it = it .. node.value;
end
it = it .. '</div>';
if dups then
local comment = '(唔係真嘅號碼,只係為方便討論)';
local message = '呢個站有已知嘅撞名出口:\n';
for number, fake_ids in pairs(dups.notes) do
message = message .. '*出口 ' .. conjoin(fake_ids) .. comment .. join_segments('都係叫 ', dups[fake_ids[1]]) .. '\n';
comment = ' ';
end
it = it .. '\n\n' .. make_disclaimer('小心', message);
end
end
return it;
end
-- Entry point
p.main = function (frame, ruby_mode_p)
local parent = frame:getParent();
local s;
local args = {};
local f;
local need_styles_p;
for _, a in pairs({frame, parent}) do
if a then
for k, v in pairs(a.args) do
v = v:gsub('^%s+', ''):gsub('%s+$', '');
if type(k) == 'number' then
if v == 'icon' or v == '圖標' then
f = show_icon;
need_styles_p = true;
elseif v == 'icon and name' or v == '圖標同名' then
f = show_icon_and_name;
need_styles_p = true;
elseif v == 'name' or v == '名' then
f = show_name;
elseif v == 'livery' or v == 'linecolor' or v == 'linecolour' or v == '顏色' then
f = show_livery;
elseif v == 'no link' or v == 'disable link' or v == '唔連' or v == '唔連文章' then
args.no_link_p = true;
elseif v == '出入口註釋' then
f = show_disclaimer;
need_styles_p = true;
elseif lines[v] then
args.line = v;
else
error('不明參數 「' .. v .. '」');
end
elseif k == 'line' or k == '路綫' then
args.line = v;
elseif k == 'link' or k == '連' or k == '連結' or k == '拎' then
args.no_link_p = not interpret_boolean(v);
elseif k == '出入口' then
local a, b = pcall(mw.text.jsonDecode, v);
if a then
f = function () return chart_entrances(new_Entrance(b)); end;
need_styles_p = true;
else
error(k .. '參數出錯,可能係 JSON 語法錯誤(' .. p.cvs(v) .. ')');
end
elseif k == '車站樓層' then
local a, b = pcall(mw.text.jsonDecode, v);
if a then
f = function () return draw_station_description(b); end;
need_styles_p = true;
else
error(k .. '參數出錯,可能係 JSON 語法錯誤(' .. p.cvs(v) .. ')');
end
-- 出入口註譯
elseif k == 'locality' or k == '地區' then
args.locality = v;
elseif k == 'network' or k == '網絡' then
args.network = v;
elseif k == 'source' or k == '出處' then
args.source = v;
else
error('不明參數 「' .. k .. '」');
end
end
end
end
local it;
if f then
it = f(args);
else
error('冇指定顯示乜嘢');
end
-- request our style sheet
if styles and need_styles_p then
if it:match('^{|') then
it = '\n' .. it;
end
it = table.concat ({ frame:extensionTag('templatestyles', '', {src=styles}), it });
end
it = it:gsub('\n$', '');
return it;
end
p.test = function ()
assert(icon_size('File:TTC - Line 4 - Sheppard line.svg') == 16);
assert(icon_size('File:TTC - 509.svg') == 28);
local a, b;
a, b = pcall(p.main, {
['getParent'] = function ()
return {
extensionTag = function () return '' end;
args= { 'icon', line = '1' };
};
end;
extensionTag = function () return '' end;
args = {
};
});
assert(a and b:match('Line 1.*16px'));
a, b = pcall(p.main, {
['getParent'] = function ()
return {
extensionTag = function () return '' end;
args= { 'icon', line = 'YUS' };
};
end;
extensionTag = function () return '' end;
args = {
};
});
assert(a and b:match('Line 1.*16px'));
a, b = pcall(p.main, {
['getParent'] = function ()
return {
extensionTag = function () return '' end;
args= { 'livery', line = 'YUS' };
};
end;
extensionTag = function () return '' end;
args = {
};
});
assert(a and b == '#f8c300');
a, b = pcall(p.main, {
['getParent'] = function ()
return {
extensionTag = function () return '' end;
args= { 'livery', line = '509' };
};
end;
extensionTag = function () return '' end;
args = {
};
});
assert(a and b == '');
a, b = pcall(new_Entrance, mw.text.jsonDecode('[{ "website":"Yonge Street (Mel Lastman Square)", "def":[ { "outside":"地面", "xyzzy":"賴士民廣場" } ] } ]'));
assert(not a and mw.ustring.match(b, '不明欄位'));
a, b = pcall(new_Entrance, mw.text.jsonDecode('[{ "website":"Yonge Street (Mel Lastman Square)", "def":[ { "outside":"地面", "x-xyzzy":"賴士民廣場" } ] } ]'));
assert(a);
end
p.chart_entrances = chart_entrances;
p.new_Entrance = new_Entrance;
return p;