local i18n = {
errors = {
["parameter-missing"] = "Не указан обязательный параметр!",
["collapsible-block-not-closed"] = "Сворачивающийся блок не закрыт!",
["collapsible-block-not-open"] = "Сворачивающийся блок не был открыт либо лишняя команда закрытия",
["too-many-parameters"] = "Слишком много параметров.",
["no-icons"] = "Не указано ни одной иконки!",
["colspan-too-many-to-span"] = "Указанное значение строк для объединения не может быть удовлетворено.",
["unknown-keyword"] = "Неизвестное ключевое слово «%s».",
["invalid-keyword-at-position"] = "Неверное ключевое слово «%s» в данном месте."
},
["error-categories"] = {
default = '[[Category:Википедия:Статьи с неверно заполненными маршрутными картами]]'
--["parameter-missing"] = '[[Category:Википедия:Статьи с неверно заполненными маршрутными картами]]'
},
html = {
["cell-icon-fmt"] = '\
|style="width:20px"|[[File:BSicon_%s.svg|20px|alt=|link=]]',
["cell-overlapicon-fmt"] = '[[File:BSicon_%s.svg|20px|link=|alt=]]',
["cell-icon-fmt-with-overlap"] = '\
|style="width:20px"|<div style="position:relative;width:20px"><div style="position:absolute;left:0px;top:0px;padding:0">\
%s</div>[[File:BSicon_%s.svg|20px|link=|alt=]]</div>',
["cell-icon-with-info4-note2-fmt"]='<span style="font-size:80%%;float:right">%s</span>',
["row-general-fmt"] = '\
|-\
|style="padding:0;white-space:nowrap;background-color:transparent"|<center>\
{|cellspacing="0" cellpadding="0" style="background-color:transparent;line-height:0px !important"\
|-%s\
|}</center>\
|style="text-align:right;vertical-align:middle;padding:0.5em;font-size:80%%"|%s\
|colspan="2" style="vertical-align:middle;text-align:left"|%s',
["row-collapsible-begin-fmt"] = '\
|-\
|colspan="5" style="padding:0 !important;white-space:nowrap;background-color:white"|\
{|class="mw-collapsible mw-%s autocollapse" cellpadding="0" cellspacing="0" style="background-color:transparent;line-height:1.2 !important;padding:0 !important;align:left !important;margin:none !important;width:100%% !important;line-height:0px !important"\
|-\
|style="padding:0 !important;white-space:nowrap;text-align:center !important;width:0px !important"|\
{|cellspacing="0" cellpadding="0" style="background-color:transparent;float:none !important;margin:auto !important;width:auto !important;line-height:0px !important"\
|-%s\
|}\
|style="text-align:right;vertical-align:middle;padding:0 3px;font-size:90%%;border:0px !important" |%s\
!style="text-align:left;vertical-align:middle;white-space:nowrap;width:100%%;padding-right:3px;border:0px !important" colspan="2" |%s',
["row-collapsible-replace-begin-fmt"] = '\
|-\
|style="text-align:left;padding:0;white-space:nowrap"|\
<div style="position:relative">\
{|align="left" cellspacing="0" cellpadding="0" style="position:absolute;bottom:0px;background-color:#f9f9f9;line-height:0px !important"\
|-%s\
|}</div>\
|style="text-align:left;padding:0;white-space:nowrap;vertical-align:middle"|\
<div style="position:relative">\
{|align="left" cellspacing="0" cellpadding="0" style="position:absolute;bottom:0px;vertical-align:middle;bottom:0px;top:-18px;background-color:#f9f9f9;line-height:0px !important"\
|style="text-align:right;vertical-align:middle;padding:0 3px;font-size:90%%;border:0px !important"|%s\
!style="text-align:left;vertical-align:middle;white-space:nowrap;width:100%%;padding-right:3px;border:0px !important" colspan="2"|%s\
|}</div>',
["row-collapsible-end"] = '\n|}',
["colspan-fmt"] = '%s\n|-\n|colspan="4" |\n%s'
}
}
local function formaterror(key,param)
local result=mw.ustring.format('\n|-\n|<span class="error">%s</span>',mw.ustring.format(i18n.errors[key]or key..' %s',param or ''))
title=mw.title.getCurrentTitle()
if mw.site.namespaces[title.namespace].isContent then result=result..(i18n['errors-categories'][error]or
i18n['errors-categories'].default or '')end
return result
end
local p,q={},{}
-- Compatibility: Lua-5.0
-- Source: http://lua-users.org/wiki/SplitJoin
-- Author: http://lua-users.org/wiki/PhilippeLhoste
local function Split(str, delim, maxNb)
if delim==nil or delim=='' then error('Split(): expected a non-empty string at parameter #2')end
if str=='' or string.find(str, delim) == nil then return{ str }end
if maxNb == nil or maxNb < 1 then
maxNb = 0 -- No limit
end
local result = {}
local pat = "(.-)" .. delim .. "()"
local nb = 0
local lastPos
for part, pos in string.gfind(str, pat) do
nb = nb + 1
result[nb] = part
lastPos = pos
if nb == maxNb then break end
end
-- Handle the last field
if nb ~= maxNb then
result[nb + 1] = string.sub(str, lastPos)
end
return result
end
local function cell(icon,overlapIcons)
local tmp={}
icon=mw.text.trim(icon)
if #overlapIcons>0 then
for i,v in ipairs(overlapIcons) do table.insert(tmp,mw.ustring.format(i18n.html['cell-overlapicon-fmt'],v))end
return mw.ustring.format(i18n.html['cell-icon-fmt-with-overlap'],mw.text.trim(table.concat(tmp)),icon)else
return mw.ustring.format(i18n.html['cell-icon-fmt'],icon)end
end
local function row(pattern,collapse,collapse_replace)
local icons,info1,info2
local cells,overlapIcons,tmp={},{},Split(pattern,'~~',3)
if #tmp>2 then
info1=tmp[2]
info2=tmp[3]
else
info1=''
info2=tmp[2]or''
end
icons=Split(tmp[1],'\\')
for i,v in ipairs(icons)do
tmp=Split(v,'!~')
icons[i]=tmp[1]
table.remove(tmp,1)
table.insert(overlapIcons,tmp)
end
if #icons+#overlapIcons<1 then return formaterror('no-icons')end
info1=mw.getCurrentFrame():preprocess(info1);--expand possible templates in infos.
info2=mw.getCurrentFrame():preprocess(info2);
for i,v in ipairs(icons)do table.insert(cells,cell(v,overlapIcons[i]))end
cells=table.concat(cells)
if type(collapse)=='string' then--[[
if collapse_replace==0 then return mw.ustring.format(i18n.html["row-collapsible-begin-fmt"],collapse,cells,
info1,info2)else return mw.ustring.format(i18n.html['row-collapsible-replace-begin-fmt'],cells,info1,info2)]]--
return mw.ustring.format(i18n.html["row-collapsible-begin-fmt"],collapse,cells,info1,info2)elseif type(collapse)=="boolean"
then return mw.ustring.format(i18n.html['row-collapsible-replace-begin-fmt'],cells,info1,info2)
else return mw.ustring.format(i18n.html['row-general-fmt'],cells,info1,info2)end
end
q={'startCollapsible','collapsibleReplace','colspan',collapsible=0}
q.isKeyword=function(pattern,i,rows,justTest)
local tmp=Split(pattern,'-')
if tmp[2]=='' or tmp[1]>'' then return nil end--not a valid keyword
table.remove(tmp,1)--delete first, empty part before "-"
if type(q[tmp[1]])=="function" and tmp[1]~='isKeyword' then--valid keyword
if justTest then return true else return q[tmp[1]](tmp,i,rows)end
else if justTest then return false else return formaterror('unknown-keyword',tmp[1])end
end
end
q['startCollapsible']=function(params,i,rows)
table.remove(rows,i)
if i>#rows-3 then return formaterror('collapsible-block-not-closed')end--not enough lines to close the collapsible block
if q.isKeyword(rows[i],i,rows,true)then
return formaterror('invalid-keyword-at-position',rows[i])end--no valid keywords that can follow "startCollapsible" yet
local param1,param2=params[2]or '',params[3]or 0--params[1] is the keyword name so all indices are shifted by one.
q.collapsible=q.collapsible+1
local result
if param1=='' then param1='collapsed' end
if param2~=0 then
result=row(rows[i],param1)
result=result..row(rows[i+1],true)
table.remove(rows,i)
return result
else return row(rows[i],param1)end
end
q['endCollapsible']=function(params,i,rows)
if q.collapsible>0 then
q.collapsible=q.collapsible-1
return i18n.html['row-collapsible-end']
else return formaterror('collapsible-block-not-open')end
end
q['colspan']=function(params,i,rows)
local tmp,j,param1={},0
if params[2]=='end' then return '<!-- -colspan-end -->' else param1=tonumber(params[2])end
table.remove(rows,i)
if param1==nil then param1=#rows-i end
while j<param1 and i<=#rows do
j=j+1
local result=q.isKeyword(rows[i],i,rows)
if type(result)~="string" then table.insert(tmp,rows[i])elseif result=='<!-- -colspan-end -->' then
j=param1
else table.insert(tmp,result)end
if param1>1 then table.remove(rows,i)end
end
if j<param1 then j=formaterror('colspan-too-many-to-span') else j='' end
return mw.ustring.format(i18n.html['colspan-fmt'],j,mw.getCurrentFrame():preprocess(table.concat(tmp,'\n')))
end
function p.route(frame)
-- ВАЖНО: параметры должны быть следующего вида
-- иконка!~перекрывающая иконка\(ещё)\(если надо, то ещё и т. д.)~~время~~информация о пункте (станция) и т. д.)
-- Если передан параметр «pattern», то он обрабатывается первым и может содержать сколько угодно дополнительных
-- (первая строка в описанном выше формате)\n(вторая строка)
local rows,title,tmp={},nil,{}
rows=Split(frame.args['pattern'],'\n')
for i,v in ipairs(frame.args)do table.insert(rows,v)end
if mw.text.trim(table.concat(rows))=='' then return formaterror('parameter-missing')end
for i,v in ipairs(rows)do
local keyword=q.isKeyword(v,i,rows)
if type(keyword)~="string" then table.insert(tmp,row(v,nil))else table.insert(tmp,keyword)end
end
return table.concat(tmp)
end
return p