Module:Adjacent stations

This is an old revision of this page, as edited by Ythlev (talk | contribs) at 11:57, 22 January 2019 (New version). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

local getArgs = require('Module:Arguments').getArgs
local p, data, lineData = {}

local function dig(...)
	-- Digs through a table with sub-tables using arguments as keys, returning the value of the last key argument
	-- Analogous to returning a file given a file path with sub-folders
	-- Returns nil if any given sub-table does not exist
	local arg = {...}
	local a, i, n = arg[1], 1, select('#', ...)
	while a and i < n do
		a = a[arg[i + 1]]
		i = i + 1
	end
	if i == n then return a end
end

local function makeInvokeFunc(funcName)
	return function (frame)
		local args = getArgs(frame)
		if funcName ~= '_main' then
			local t = mw.title.new('Module:Adjacent stations/' .. (args.system or args[1]))
			data = t.exists and mw.loadData('Module:Adjacent stations/' .. (args.system or args[1]))
			if funcName ~= '_station' and (args.line or args[2]) then
				lineData = 
					dig(data, 'lines', args.line or args[2]) or
					dig(data, 'lines', dig(data, 'aliases', string.lower(args.line or args[2])))
			end
		end
		return p[funcName](args, frame)
	end
end

p.main = makeInvokeFunc('_main')
function p._main(args)
	local renderSuccessionBox = require('Module:Adjacent stations/renderSuccessionBox')
	return renderSuccessionBox(args)
end

p.station = makeInvokeFunc('_station')
function p._station(args, frame)
	local station = args.station or args[2]
	if station then
		if data then
			local stationFormat = data['station format'] or error(i18n[lang]['error_format'])
			local link = stationFormat[station] or stationFormat[1]
			return string.match(link, '%[%[.+%]%]') and (string.gsub(link, '%%1', station)) or
				table.concat({'[[', (string.gsub(link, '%%1', station)), '|', station, ']]'})
		else
			return frame:expandTemplate{
				title = (args.system or args[1]) .. ' stations',
				args = {
					['station'] = station,
					['line'] = args.line or args[3],
					['branch'] = args['type'] or args[4]
				}
			}
		end
	end
end

p.line = makeInvokeFunc('_line')
function p._line(args, frame)
	if data then
		if args['type'] or args[3] then
			local typ = dig(lineData, 'types', args['type'] or args[3], 'title')
			return table.concat({lineData['title'], ' (', typ, ')'})		
		else
			return
				lineData and lineData['title'] or
				(string.gsub(dig(data, 'lines', '_default', 'title'), '%%1', args.line or args[2] or '_default'))
		end
	else
		return frame:expandTemplate{
			title = (args.system or args[1]) .. ' stations',
			args = {
				args.line or args[2],
				['branch'] = args['type'] or args[3]
			}
		}
	end
end

p.color = makeInvokeFunc('_color')
function p._color(args, frame)
	if data then
		return
			dig(lineData, 'types', args['type'] or args[3], 'color') or
			lineData and lineData['color'] or
			dig(data, 'lines', '_default', 'color')
	else
		return frame:expandTemplate{
			title = (args.system or args[1]) .. ' color',
			args = {
				args.line or args[2],
				['branch'] = args['type'] or args[3]
			}
		}
	end
end

p.icon = makeInvokeFunc('_icon')
function p._icon(args)
	return
		dig(lineData, 'types', args['type'] or args[3], 'icon') or
		lineData and lineData['icon'] or
		data['system icon']
end

p.box = makeInvokeFunc('_box')
function p._box(args)
	local colour, root = p._color(args), mw.html.create('div')
	local style = args.style or args.inline
	local typeData = dig(lineData, 'types', args['type'] or args[3])
	if colour then
		colour = string.match(colour, '#') and colour or '#' .. colour
	end
	local linkedBox =
		style == 'link' or
		style == 'ldot' or
		style == 'lsquare' or
		style and string.match(style, 'route')
	if linkedBox then
		root
			:wikitext(string.match(p._line(args), '%[%[.+|'))
	end
	local box = root:tag('span')
	if
		style == 'dot' or
		style == 'ldot' or
		style == 'square' or
		style == 'lsquare' then
		box
			:css('line-height', 'initial')
	end
	if
		style == 'dot' or
		style == 'ldot' or
		style == 'square' or
		style == 'lsquare' or
		style == 'xroute' then
		box
			:css('color', colour)
	else
		box
			:css('background-color', colour)
	end
	if
		style == nil or
		style == 'link' or
		style == 'inline' or style == 'yes' or
		style == 'box' then
		box
			:css('border', '1px solid #000')
	elseif style and string.match(style, 'route') then
		local borderColour = typeData and typeData['border color'] or lineData and lineData['border color'] or colour
		box
			:css('border', '.075em solid ' .. borderColour)
			:css('padding', '0 .3em')
		if style ~= 'route' then
			box
				:css('border-radius', '.5em')
		end
	end
	if style == 'dot' or style == 'ldot' then
		box:wikitext('●')
	elseif style == 'square' or style == 'lsquare' then
		box:wikitext('■')
	elseif style and string.match(style, 'route') then
		box
			:css('color',
				typeData and typeData['text color'] or
				lineData and lineData['text color'] or
				style == 'xroute' and colour or
				'black'
			)
			:css('font-weight', args.bold == 'no' or 'bold')
			:css('font-size', 'inherit')
			:css('white-space', 'nowrap')
			:wikitext(args.line or args[2])
	else
		box
			:wikitext(string.rep('&nbsp;', style == 'small' and 1 or 4))
	end	
	if linkedBox then root:wikitext(']]') end
	if
		style == nil or
		style == 'inline' or style == 'yes' or
		style == 'small' or
		style == 'dot' or
		style == 'square' then
		root
			:wikitext('&nbsp;', p._line(args))
	end
	return root
end

return p