Перейти к содержанию

Модуль:СтММ

Материал из Мегавики — свободной энциклопедии

Для документации этого модуля может быть создана страница Модуль:СтММ/doc

-- Этот модуль вызывается с помощью шаблонов СтММ и ЛММ

--[=[ Linter:

setmetatable(_G, {
	__newindex =
		function (_, n)
			error("attempt to write to undeclared variable "..n, 2)
		end,
	__index =
		function (_, n)
			error("attempt to read undeclared variable "..n, 2)
		end,
	})
--]=]

local p = {}
local jsontable = mw.loadJsonData('Шаблон:Интерактивная схема Московского метрополитена/data.json')

local function contains(tbl, x)
	local t
    local found = false
    for p, v in pairs(tbl) do
        if v == x then 
            found = p 
        end
    end
    return found
end

local function removeparen(text)
    return text:gsub( '^%s*(.+)%s+%b()%s*$', '%1' )
end

local function addquotes(text, icon)
	if (icon) then
		return text
	end
	return '<span class="stmm-quotes">«</span>' .. text .. '<span class="stmm-quotes">»</span>'
end

local function showicon(code, link)
	local iconsize = 15
	local filename
	if (mw.ustring.match(code, "^D5.$")) then
		code = 'D5'
	end
	if (code == 'D4А') then
		iconsize = 30
	elseif (mw.ustring.sub(code, 1, 1) == 'D') then
		iconsize = 22
	end
	filename = 'Moskwa Metro Line ' .. code .. '.svg'
	return '[[File:' .. filename .. '|' .. iconsize .. 'px|'
		.. 'link=' .. link .. '|' .. removeparen(link) .. ']]'
end

local function splitname(text)
	if (text) then
		local slash = mw.ustring.find(text, '/', 1, true)
		if (slash) then
			return mw.ustring.sub(text, 1, slash - 1), mw.ustring.sub(text, slash + 1)
		end
		return text
	end
end

local function errors(text, template)
	error(text .. '[[Категория:Ошибки в использовании шаблона ' .. (template or 'СтММ') .. ']]' , 0)
end

local function findstation(stationparam)
	local csi, newline, newstation, category
	local lines = {}
	local allanswers = {}
	local newjson = {}
	local alllines = {}
	for _, value in pairs(jsontable.lines) do
		newline = {article = value.article, train = value.train, stations = {}}
		if (value.number and not value.hidden) then
			table.insert(alllines, value.number)
		end
		for _, value0 in pairs(value.stations or {}) do
			if (not value0.hidden) then
				newstation = {article = value0.article, line = value.number, rp = removeparen(value0.name or value0.article), sn = value0.showname}
				if (stationparam == newstation.rp or stationparam == value0.oldname) then
					if (stationparam == value0.oldname) then
						category = '[[Категория:Страницы, требующие переименования станций в шаблоне СтММ]]'
					end
					table.insert(allanswers, {value0.article, newstation.sn or newstation.rp, newstation.line, value.article, value.train, value0.future, category,
						not value0.coords and not value0.future and not value.exists or value.future})
					table.insert(lines, newstation.line)
					if (value0.csi) then
						csi = {value.number, tostring(value0.csi), value.article, #allanswers, nil,
							value0.future or value0.csifuture}
					end
				end
				if (csi and csi[2] == value.number) then
					csi[5] = value.article
				end
				table.insert(newline.stations, newstation)
			end
		end
		if (value.number) then
			table.insert(newjson, newline)
		end
	end
	return lines, allanswers, csi, newjson, alllines
end

local function findnextstation(stationparam)
	local lines = {}
	local allanswers = {}
	for _, value in pairs(jsontable) do
		for _, value0 in pairs(value.stations or {}) do
			if (stationparam == value0.rp) then
				table.insert(allanswers, {value0.article, value0.rp, value0.line, value.article, value.train})
				table.insert(lines, value0.line)
			end
		end
	end
	return lines, allanswers
end

local function findstationhint(stationparam)
	local ahint, chint, rp, lowerp
	local lowerstation = mw.ustring.gsub(mw.ustring.lower(stationparam), ' +', ' ')
	for _, value in pairs(jsontable) do
		for _, value0 in pairs(value.stations or {}) do
			rp = value0.rp
			lowerp = mw.ustring.lower(rp)
			if (lowerp == lowerstation) then
				return rp
			elseif (mw.ustring.find(lowerstation, lowerp, 1, true)
					and (not ahint or (mw.ustring.len(rp) > mw.ustring.len(ahint)))) then
				ahint = rp
			elseif (not ahint and mw.ustring.find(lowerp, lowerstation, 1, true)
					and (not chint or (mw.ustring.len(rp) > mw.ustring.len(chint)))) then
				chint = rp
			end
		end
	end
	return ahint or chint
end

local function formatvariants(vars, cond)
	local err = ', возможные варианты: ' .. mw.ustring.gsub(mw.ustring.gsub(mw.text.jsonEncode(vars), '["%[%]]', ''),',', ', ')
	if (cond) then
		err = err .. '. Можно также использовать параметр «@@» вместо «@» для кроссплатформенных или общих станций'
	end
	return err
end

local function slashmode(line, symb, name)
	local iconmode, anarticle, notarticle, aname, curline, namearticle
	local sortkey = ''
	local italic = 'normal'
	local ans = ''
	
	if (line == '') then
		return errors('Пустой номер линии', 'ЛММ')
	end
	for _, value in ipairs(jsontable.lines) do
		if ((value.othernumber or value.number) == line and not value.hidden) then
			anarticle = value.article
			aname = value.othername or value.name or value.article
			namearticle = value.shortname or value.name or value.article
			if (value.future) then
				italic = 'italic'
			end
			curline = value.number
			break
		end
	end
	if (not anarticle) then
		return errors('Неизвестная линия «' .. line .. '»', 'ЛММ')
	end
	if (symb == '@') then
		ans = showicon(curline, anarticle) .. ' ' .. ans
		sortkey = '@' .. curline
	elseif (symb ~= '') then
		return errors('Перед / может использоваться только @', 'ЛММ')
	end
	ans = ans .. '[[' .. anarticle .. '|<span title="' .. aname .. ' (' .. curline .. ')">'
	if (name == '') then
		ans = ans .. aname
		sortkey = sortkey .. ' ' .. aname
	elseif (name == '-') then
		notarticle = mw.ustring.gsub(aname, ' линия', '')
		if (notarticle == aname) then
			notarticle = namearticle
		end
		ans = ans .. notarticle
		sortkey = sortkey .. ' ' .. notarticle
	else
		ans = ans .. name
		sortkey = sortkey .. ' ' .. name
	end
	return '<span style="white-space: nowrap;font-style: ' .. italic .. ';"><span style="display:none" class=sortkey>'
		.. sortkey .. '</span>' .. ans .. '</span>]]</span>'
end

local function getargs(frame)
	local args = {}
	for p, v in pairs(frame:getParent().args) do
		args[p] = mw.text.trim(v)
	end
	return args
end

function p.station(frame)
	local startparam = 1
	local argsnumber = 0
	local iconparam = false
	local interchangeparam = false
	local hyphenparam = false
	local lineparam = ''
	local icon = ''
	local err = ''
	local ts = ''
	local title = ''
	local addcat = ''
	local sortkey = ''
	local exists = ''
	local italic = 'normal'
	local args = getargs(frame)
	local allowlines
	local stationparam, stationname, allanswers, hint, articleans, nameans,
		csiparam, csi, unknownpar, lines, hintlines, hintanswers, indexans, alllines

	for p, _ in ipairs(args) do
		argsnumber = math.max(argsnumber, p)
	end
	if (args[1] == '@') then
		iconparam = true
		startparam = 2
	elseif (args[1] == '-') then
		iconparam = true
		hyphenparam = true
		startparam = 2
	elseif (args[1] == '&') then
		iconparam = true
		interchangeparam = true
		startparam = 2
	elseif (args[1] == '@@') then
		csiparam = args[2]
		startparam = 2
	end
	if (not csiparam and argsnumber - startparam > 1) then
		return errors('Слишком много параметров')
	end
	for p, _ in pairs(args) do
		if (not contains({1, 2, 3}, p)) then
			if (csiparam) then
				unknownpar = true
			else
				return errors('Неизвестный параметр «' .. p .. '»')
			end
		end
	end
	stationparam, stationname = splitname(args[startparam])
	if (stationparam == '') then
		return errors('Пустое название станции')
	end
	if (stationname == '') then
		return errors('Пустой замещающий текст для отображения вместо названия станции')
	end
	if (stationparam == stationname) then
		return errors('Замещающий текст совпадает с названием станции')
	end
	if (csiparam and (args[startparam + 1] or unknownpar)) then
		return errors('Параметр «@@» должен использоваться исключительно с названием станции')
	end
	if (args[startparam + 1]) then
		lineparam = args[startparam + 1]
	end
	if (not stationparam) then
		return errors('Название станции не указано')
	end
	allowlines = jsontable.allowlines and jsontable.allowlines[stationparam]
	lines, allanswers, csi, jsontable, alllines = findstation(stationparam)
	if (not csi and csiparam) then
		return errors('Параметр «@@» должен использоваться только для кроссплатформенных или общих станций')
	end
	if (#allanswers == 0) then
		if (contains(alllines, stationparam) and lineparam ~= '') then
			return errors('Возможно, вы используете старый синтаксис: теперь следует указывать станцию до линии')
		end
		hint = findstationhint(stationparam)
		if (hint) then
			hintlines, hintanswers = findnextstation(hint)
			if (#hintanswers <= 1) then
				err = '. В номере линии нет необходимости'
			elseif (contains(hintlines, lineparam)) then
				err = ', она может использовать указанный номер линии: ' .. lineparam
			else
				err = '. Требуется также номер линии' .. formatvariants(hintlines)
			end
			err = ', но, возможно, вы имели в виду «' .. hint .. '»' .. err
		end
		return errors('Станция «' .. mw.ustring.gsub(stationparam, '  +', '<много пробелов>') .. '» неизвестна' .. err)
	end
	if (mw.text.jsonEncode(args[startparam + 1]) == '""') then
		if (#allanswers == 1) then
			return errors('Номер линии пуст и не требуется')
		elseif (#allanswers > 1) then
			return errors('Пустой номер линии' .. formatvariants(lines, csi and iconparam and not hyphenparam))
		end
	end
	if (#allanswers == 1 and lineparam ~= '') then
		return errors('Номер линии не требуется: ' .. lineparam)
	end
	if (allowlines and lineparam == '' and #allanswers > 1) then
		lineparam = allowlines
		addcat = '[[Категория:Страницы, требующие добавления номеров линий в шаблоне СтММ]]'
	end
	if (not csiparam and ((#allanswers > 1 and not csi) or (#allanswers > 2 and csi)) and lineparam == '' and addcat == '') then
		return errors('Существует несколько станций с таким названием. Требуется номер линии' .. formatvariants(lines, csi and iconparam and not hyphenparam))
	end
	if (not csiparam and #allanswers > 1) then
		for key, value in pairs (allanswers) do
			if (value[3] == lineparam) then
				indexans = key
			end
		end
		if (csi and lineparam == '') then
			indexans = 1
		end
	elseif (csi and csiparam) then
		indexans = csi[4]
	else
		indexans = 1
	end
	if (not indexans) then
		return errors('Неверный номер линии: ' .. lineparam .. formatvariants(lines, csi and iconparam and not hyphenparam))
	end
	articleans = allanswers[indexans][1]
	nameans = allanswers[indexans][2]
	if (iconparam or csiparam) then
		if (hyphenparam) then
			icon = '&nbsp;—'
		elseif (csi and lineparam == '') then
			icon = icon .. showicon(csi[1], csi[3]) .. showicon(csi[2], csi[5])
			sortkey = '@' .. csi[1] .. ' @' .. csi[2]
		else
			icon = showicon(allanswers[indexans][3], allanswers[indexans][4])
			sortkey = '@' .. allanswers[indexans][3]
		end
	end
	ts = frame:extensionTag{
			name = 'templatestyles',
			args = { src = 'Шаблон:СтММ/styles.css' }
		}
	if (allanswers[indexans][6]) then
		italic = 'italic'
	elseif (icon ~= '' and mw.ustring.sub(allanswers[indexans][3], 1, 1) == 'D' and allanswers[indexans][8]) then
		exists = 'color:gray;text-decoration:underline;'
	end
	if (icon ~= '') then
		icon = icon .. ' '
	end
	if (stationname) then
		title = ', надпись ' .. stationname
	end
	sortkey = sortkey .. ' ' .. (stationname or nameans)
	return ts .. '<span style="white-space: nowrap;font-style: ' .. italic .. ';"><span style="display:none" class=sortkey>'
			.. sortkey .. '</span>' .. icon .. addquotes('[[' .. articleans .. '|<span title="'
			.. allanswers[indexans][2] .. ' (' .. allanswers[indexans][3] .. ')" style="' .. exists .. '">' ..
			(stationname or nameans) .. '</span>]]', not tonumber(mw.ustring.sub(allanswers[indexans][3], 1, 1))
			or allanswers[indexans][5] or iconparam or csiparam) .. '</span>' .. (allanswers[indexans][7] or '') .. addcat
end

function p.line(frame)
	local args = getargs(frame)
	local ans = ''
	local alllines = {}
	local allnumbers = {}
	local allarticles = {}
	local found
	local isslash = true
	local countargs = 0

	for p,v in pairs(args) do
		countargs = countargs + 1
		if (p ~= 1 and p ~= 2) then
			isslash = false
		end
	end
	if (isslash and (countargs ~= 2 or not mw.ustring.find(args[2], '/', 1, true))) then
		isslash = false
	end
	if (isslash) then
		return slashmode(args[1], splitname(args[2]))
	end

	for p, v in pairs(args) do
		if (mw.ustring.find(v, '/', 1, true)) then
			return errors('Параметр / используется исключительно c одним безымянным параметром и после него', 'ЛММ')
		end
		if (type(p) ~= 'number') then
			return errors('Неизвестный параметр «' .. p .. '»', 'ЛММ')
		end
		if (v == '') then
			return errors('Пустой параметр № ' .. p, 'ЛММ')
		end
	end
	if (not args[1]) then
		return errors('Нет параметров', 'ЛММ')
	end
	for _, value in ipairs(jsontable.lines) do
		if (value.number and not value.hidden) then
			table.insert(alllines, value.number)
			table.insert(allnumbers, value.othernumber or value.number)
			table.insert(allarticles, value.article)
		end
	end
	for _, value in ipairs(args) do
		found = contains(allnumbers, value)
		if (not found) then
			return errors('Неизвестная линия «' .. value .. '»', 'ЛММ')
		end
		ans = ans .. showicon(alllines[found], allarticles[found])
	end
	return '<span style="white-space: nowrap"><span style="display:none" class=sortkey>@'
		.. alllines[found] .. '</span>' .. ans .. '&nbsp;</span>'
end

local function getprep(frame, text)
	return frame:preprocess(text)
end

local function fulldouble(frame)
	local cur
	local ans = '<table class=wikitable><tr><th colspan=2>@@</th></tr>' 
	for _, value in pairs(jsontable.lines) do
		for _, value0 in pairs(value.stations or {}) do
			if (value0.csi) then
				cur = '{{СтММ|@@|' .. removeparen(value0.name or value0.article) .. '}}'
				ans = ans .. '<tr><td>' .. cur .. '</td><td>' .. frame:preprocess(cur) .. '</td></tr>'
				--ans = ans .. '\n* ' .. removeparen(value0.article) .. ', ' .. value.number .. ', ' .. value0.csi
			end
		end
	end
	ans = ans .. '</table>'
	return ans
end

function p.full(frame)
	if (frame.args[1] == '0') then
		return fulldouble(frame)
	end
	local ans = '<table class=wikitable>'
	local found = false
	local rp
	local value
	local left, right, text
	value = jsontable.lines[tonumber(frame.args[1])]
	if (value.number) then
		found = true
		ans = ans .. '<tr><th>' .. value.number .. '</th><th>' .. (value.name or value.article) .. '</th></tr>'
		for _, value0 in pairs(value.stations or {}) do
			rp = removeparen(value0.name or value0.article)
			if (mw.ustring.sub(value.number, 1, 1) == 'D') then
				_, left = pcall(getprep, frame, '{{СтММ|' .. rp .. '}}')
				_, right = pcall(getprep, frame, '{{СтММ|' .. rp .. '|' .. value.number .. '}}')
				if (not mw.ustring.find(left, 'strong')) then
					ans = ans .. '<tr><td>{{СтММ|' .. rp .. '}}</td><td>' .. left .. '</td></tr>'
				end
				if (not mw.ustring.find(right, 'strong')) then
					ans = ans .. '<tr><td>{{СтММ|' .. rp .. '|' .. value.number .. '}}</td><td>'
						.. right .. '</td></tr>'
				end
			end
			_, left = pcall(getprep, frame, '{{СтММ|@|' .. rp .. '}}')
			_, right = pcall(getprep, frame, '{{СтММ|@|' .. rp .. '|' .. value.number .. '}}')
			if (not mw.ustring.find(left, 'strong')) then
				ans = ans .. '<tr><td>{{СтММ|@|' .. rp .. '}}</td><td>' .. left .. '</td></tr>'
			end
			if (not mw.ustring.find(right, 'strong')) then
				ans = ans .. '<tr><td>{{СтММ|@|' .. rp .. '|' .. value.number .. '}}</td><td>' .. right .. '</td></tr>'
			end
		end
	end
	if (not found) then
		errors('Wrong line id: ' .. frame.args[1])
	end
	ans = ans .. '</table>'
	return ans
end

local function is_disambig(page) --Модуль:Hatnote
	for _, c in ipairs(page.categories) do
		if c == 'Страницы значений по алфавиту' then
			return true
		end
	end
	return false
end

function p.replace(frame)
	local template = frame.args[1] or 'nothing'
	return errors('[[Шаблон:' .. template .. ']] удалён, пользуйтесь шаблоном [[Шаблон:СтММ|СтММ]]', template)
end

local function findonelinehint(station, stations)
	local lowerstation = mw.ustring.gsub(mw.ustring.lower(station), ' +', ' ')
	local lowerp
	for _, value0 in pairs(stations) do
		lowerp = mw.ustring.lower(removeparen(value0.name or value0.article))
		if (lowerstation == lowerp or mw.ustring.find(lowerstation, lowerp, 1, true) or mw.ustring.find(lowerp, lowerstation, 1, true)) then
			return removeparen(value0.name or value0.article)
		end
	end
end

function p.mosmetroicon(frame)
	local args = getargs(frame)
	local station = ''
	local goodline = false
	local csi = ''
	local countstmm = 0
	local isstmm = true
	local goodline = false
	local errortext = ''
	local category = ''
	local hint

	if (not args[1] or args[1] == '') then
		return errors('В первом параметре должен быть номер линии', 'MOSMETRO icon')
	end
	if (args.style and args[3] and args[3] ~= '') then
		return errors('Нельзя использовать одновременно третий параметр (название станции) и параметр «style»', 'MOSMETRO icon')
	end
	if (args.style and not (args.text and args.text ~= '')) then
		return errors('Нельзя использовать параметр «style» без параметра «text»', 'MOSMETRO icon')
	end
	if (args.small and not (args.text and args.text ~= '')) then
		return errors('Нельзя использовать параметр «small» без параметра «text»', 'MOSMETRO icon')
	end
	if (args.text and args.text == '') then
		return errors('Пустой параметр «text»', 'MOSMETRO icon')
	end
	if (args[3] and not args[2]) then
		return errors('При наличии третьего параметра следует использовать второй, даже если он пуст', 'MOSMETRO icon')
	end
	if (args[2] == '' and not args[3]) then
		return errors('Пустой второй параметр без третьего', 'MOSMETRO icon')
	end
	if (args.text and args.text == '') then
		return errors('Пустой параметр «text»', 'MOSMETRO icon')
	end
	if (args.style and args.style == '') then
		return errors('Пустой параметр «style»', 'MOSMETRO icon')
	end
	if (args.small and args.small == '') then
		return errors('Пустой параметр «small»', 'MOSMETRO icon')
	end
	if (args.alt and args.alt == '') then
		return errors('Пустой параметр «alt»', 'MOSMETRO icon')
	end
	for p,v in pairs(args) do
		if (v ~= '') then
			countstmm = countstmm + 1
			if (p ~= 1 and p ~= 2 and p ~= 3 and p ~= 4 and p ~= 5 and p ~= 'text' and p ~= 'small' and p ~= 'style' and p~= 'alt') then
				return errors('Неизвестный параметр «' .. p .. '»', 'MOSMETRO icon')
			elseif (p ~= 1 and p ~= 'text') then
				isstmm = false
			end
		end
	end
	if (countstmm > 2 or countstmm == 1 and args.text and args.text ~= ''
			or countstmm == 0 or jsontable.oldlines and (jsontable.oldlines[args[1]] or jsontable.oldlines[tonumber(args[1])])) then
		isstmm = false
	end
	if (args[5]) then
		return errors('Возможно, вы используете старый синтаксис: теперь нет необходимости указывать пятый параметр', 'MOSMETRO icon')
	end
	if (args[4]) then
		return errors('Возможно, вы используете старый синтаксис: четвертый параметр больше не нужен, а станцию следует указывать в третьем параметре', 'MOSMETRO icon')
	end
	if (args[2] and args[2] == '' and args[3] and args[3] == '') then
		return errors('Пустые второй и третий параметр', 'MOSMETRO icon')
	end
	if (args[3] and args[3] == '') then
		return errors('Пустой третий параметр', 'MOSMETRO icon')
	end
	if (args[2] and args[2] ~= '') then
		local px = mw.ustring.find(args[2], 'px')
		if (px and px > 1 and mw.ustring.len(args[2]) > 2) then
			px = mw.ustring.gsub(args[2], 'px', px)
		else
			px = args[2]
		end
		if (tonumber(px) == 0 or mw.ustring.len(mw.ustring.gsub(px, '%d*', '')) > 0) then
			return errors('Второй параметр должен быть положительным целым числом', 'MOSMETRO icon')
		end
	end
	if (args[3] and args.text and args.text ~= '1') then
		return errors('Параметр «text» может равняться только «1» для станции', 'MOSMETRO icon')
	end
	if (not args[3] and args.text and args.text ~= '1' and args.text ~= '2') then
		return errors('Параметр «text» может равняться только «1» или «2» для линии', 'MOSMETRO icon')
	end
	if (jsontable.oldlines and (jsontable.oldlines[args[1]] or jsontable.oldlines[tonumber(args[1])]) and args[3]) then
		return errors('Для упразднённых линий нельзя указывать название станции', 'MOSMETRO icon')
	end
	if (isstmm) then
		if (countstmm == 1) then
			return errors('Для отображения стандартной иконки линии пользуйтесь шаблоном [[Шаблон:ЛММ|ЛММ]]', 'MOSMETRO icon')
		else
			return errors('Для отображения стандартной иконки и названия линии пользуйтесь шаблоном [[Шаблон:ЛММ|ЛММ]]', 'MOSMETRO icon')
		end
	end
	for _, value in ipairs(jsontable.lines) do
		if ((value.othernumber or value.number) == args[1] or jsontable.oldlines and (jsontable.oldlines[args[1]] or jsontable.oldlines[tonumber(args[1])])) then
			goodline = true
			if (args[3] and args[3] ~= '') then 
				for p, value0 in pairs(value.stations or {}) do
					if (value0.oldname and args[3] == removeparen(value0.oldname) or args[3] == removeparen(value0.name or value0.article)) then
						if (value0.oldname and args[3] == removeparen(value0.oldname)) then
							category = '[[Категория:Страницы, требующие переименования станций в шаблоне MOSMETRO icon]]'
						end
						station = value0.article
						if (value0.csimi) then
							csi = '1'
						end
						break
					end
				end
				if (station == '' and value.stations and #value.stations) then
					hint = findonelinehint(args[3], value.stations)
				end
			end
		end
	end
	if (not goodline) then
		return errors('Несуществующая линия: ' .. args[1], 'MOSMETRO icon')
	end
	if (args[3] and args[3] ~= '' and station == '') then
		errortext = 'Нет станции «' .. mw.ustring.gsub(args[3], '  +', '<много пробелов>') .. '» на линии ' .. args[1]
		if (hint) then
			errortext = errortext .. ', но, возможно, вы имели в виду «' .. hint .. '»'
		end
		return errors(errortext, 'MOSMETRO icon')
	end
	return frame:preprocess('{{#invoke:MoscowMetro|interchange|line=' .. args[1] .. '|size=' .. (args[2] or '') .. '|station_dabbed=' .. station .. '|CPIC=' .. csi
		.. '|text=' .. (args.text or '') .. '|small=' .. (args.small or '') .. '|style=' .. (args.style or '') .. '|alt=' .. (args.alt or '') .. '}}' .. category)
end

function p.peresadkanametro(frame)
	errors('В соответствии с новым синтаксисом, для станций Москвы следует использовать шаблон MOSMETRO icon, для остальных станций следует указывать только один параметр: ПересадкаНаМетро|статья о станции[[Категория:Ошибки в использовании шаблона ПересадкаНаМетро]]')
end

function p.double(frame)
	if (frame.args[1] == '0') then
		return fulldouble(frame)
	end
	local ans = '<table class=wikitable>'
	local found = false
	local rp
	local value
	local left, right, text
	value = jsontable.lines[tonumber(frame.args[1])]
	if (value.number) then
		found = true
		ans = ans .. '<tr><th>' .. value.number .. '</th><th>' .. (value.name or value.article) .. '</th></tr>'
		for _, value0 in pairs(value.stations or {}) do
			rp = removeparen(value0.name or value0.article)
			if (mw.ustring.sub(value.number, 1, 1) == 'D') then
				_, left = pcall(getprep, frame, '{{СтММ|' .. rp .. '}}')
				_, right = pcall(getprep, frame, '{{СтММ|' .. rp .. '|' .. value.number .. '}}')
				if (not mw.ustring.find(left, 'strong')) then
					ans = ans .. '<tr><td>{{СтММ|' .. rp .. '}}</td><td>' .. left .. '</td></tr>'
				end
				if (not mw.ustring.find(right, 'strong')) then
					ans = ans .. '<tr><td>{{СтММ|' .. rp .. '|' .. value.number .. '}}</td><td>'
						.. right .. '</td></tr>'
				end
			end
			_, left = pcall(getprep, frame, '{{СтММ|@|' .. rp .. '}}')
			_, right = pcall(getprep, frame, '{{СтММ|@|' .. rp .. '|' .. value.number .. '}}')
			if (not mw.ustring.find(left, 'strong')) then
				ans = ans .. '<tr><td>{{СтММ|@|' .. rp .. '}}</td><td>' .. left .. '</td></tr>'
			end
			if (not mw.ustring.find(right, 'strong')) then
				ans = ans .. '<tr><td>{{СтММ|@|' .. rp .. '|' .. value.number .. '}}</td><td>' .. right .. '</td></tr>'
			end
		end
	end
	if (not found) then
		errors('Wrong line id: ' .. frame.args[1])
	end
	ans = ans .. '</table>'
	return ans
end

--[==[ Схема шаблона Московские маршруты
?param-text: сплиний(param-1)
 else: ?[[Файл:Logo train transilien.svg|15px|link=param-r/23|бсвл]]
       is-station(param-1): спстанций(param-1)
        else: [[Файл:Moskwa Metro Line param-1 (line?inv:alt)(искл).svg|15px|link=param-l1..сплиний(param-1)|бсвл]]
              ?param-line and ~= 0:
            		<span цвет=param-style..(param-1{12357}?white:black>[[сплиний(param-1)|param-2..сплиний(param-1)]]</span>
               else: ?[[Файл:Moskwa Metro Line param-2/34 alt.svg|15px|link=param-l2/34..сплиний(param-2/34)|бсвл]]
                     ?[[param-c (станция МЦК)|param-c]]
                     ?[[param-m (станция монорельса)|param-m]]
                     ?[[param-s (станция метро?(, param-d)(искл))|param-s]]

?[[Файл:Logo train transilien.svg|15px|link=param-r/23|бсвл]]
[[Файл:Moskwa Metro Line param-1 alt.svg|15px|link=param-l1..сплиний(param-1)|бсвл]]
?[[Файл:Moskwa Metro Line param-2/34 alt.svg|15px|link=param-l2/34..сплиний(param-2/34)|бсвл]]
?[[param-l1|param-cn]]
?[[param-c (станция МЦК)|param-c]]
?[[param-m (станция монорельса)|param-m]]
?nodisambig([[param-s (станция метро?(, param-d)(искл))|param-s]])
?param-sn

]==]
return p