Module:Adjacent stations

local p, data, defaultData, lineData, typeData, isFuncAdjacent = {} 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, n = { ... }, select ( '#', ... ) local a, i = arg[1], 1 while a and i < n do		a = a[arg[i + 1]] i = i + 1 end return a or nil end local function makeInvokeFunc ( funcName ) return function ( frame ) local args = require ( 'Module:Arguments' ).getArgs ( frame ) if funcName == '_adjacent' then isFuncAdjacent = true local tableTools = require ( 'Module:TableTools' ) args = tableTools.numData ( args ) if args.other then args[1] = args[1] or {} for k, _ in pairs ( args.other ) do args[1][k] = args[1][k] or args['other'][k] end end return p[funcName]( tableTools.compressSparseArray ( args )) else args.system = args.system or args[1] if args.system then local s = 'Module:Adjacent stations/' .. args.system data = mw.title.new ( s ).exists and mw.loadData ( s ) end if funcName ~= '_infobox' then args.line = args.line or args[funcName == '_station' and 3 or 2] if data and args.line then args.line = dig ( data, 'lines', args.line ) and args.line or						dig ( data, 'aliases', string.lower ( args.line )) end args['type'] = args['type'] or args[funcName == '_station' and 4 or 3] if funcName ~= '_station' then defaultData = dig ( data, 'lines', '_default' ) lineData = dig ( data, 'lines', args.line ) typeData = dig ( lineData, 'types', args['type'] ) end end return p[funcName]( args, frame ) end end end p.infobox = makeInvokeFunc ( '_infobox' ) function p._infobox ( args, frame ) local data = dig ( data, 'infobox station') or data if args[3] == 'header' then return dig ( data, 'header', args[2] or 1) or		dig ( data, 'name format', args[2] or 1) or		(args[2] or args.system) and frame:expandTemplate { title = ( args[2] or args.system ) .. ' style', args = { 'name_format' } }	elseif args[3] == 'sub-header' then if dig ( data, 'sub-header') then return dig ( data, 'sub-header', args[2] or 1) else local t = {} t[1] = 'background:' t[2] = dig ( data, 'header background color', args[2] or 1) or				(args[2] or args.system) and frame:expandTemplate { title = ( args[2] or args.system ) .. ' style', args = { 'thbgcolor' } } or				'#EFEFEF' t[2] = string.match ( t[2], '#') and t[2] or '#' .. t[2] t[3] = ';color:' t[4] = dig ( data, 'header text color', args[2] or 1) or				(args[2] or args.system) and frame:expandTemplate { title = ( args[2] or args.system ) .. ' style', args = { 'thcolor' } } or				require ( 'Module:Color contrast' )._greatercontrast ({ t[2] }) t[4] = string.match ( t[4], '#') and t[4] or '#' .. t[4] return table.concat ( t ) end end end local function stationTitle ( station, args, n ) if station and data then local data = isFuncAdjacent and data[n] or data local line = isFuncAdjacent and args[n]['line'] or args['line'] local typ = isFuncAdjacent and args[n]['type'] or args['type'] local link if type ( data['station format'] ) == 'table' then local defaultFormat = data['station format'] if type ( defaultFormat[station] ) == 'table' then local stationFormat = defaultFormat[station] if line then line = stationFormat[line] and line or						dig ( data, 'aliases', string.lower ( line )) end if type ( stationFormat[line] ) == 'table' then local lineFormat = stationFormat[line] link = lineFormat[typ] or lineFormat[1] else link = stationFormat[line] or stationFormat[1] end elseif type ( defaultFormat[station] ) == 'number' then link = defaultFormat[defaultFormat[station]] else link = defaultFormat[station] or defaultFormat[1] end else link = data['station format'] end link = ( string.gsub ( link, '%%1', station )) return string.match ( link, '%[%[.-%]%]' ) and link or			table.concat ({, station,  }) end end p.station = makeInvokeFunc ( '_station' ) function p._station ( args, frame ) args.station = args.station or args[2] if data then return stationTitle ( args.station, args ) else return frame:expandTemplate { title = args.system and args.system .. ' stations', args = { ['station'] = args.station, ['line'] = args.line, ['branch'] = args['type'] }		}	end end p.color = makeInvokeFunc ( '_color' ) function p._color ( args, frame ) if data then return mw.text.nowiki (			typeData and typeData['color'] or			lineData and lineData['color'] or			defaultData and defaultData['color']					) else return frame:expandTemplate { title = args.system and args.system .. ' color', args = { args.line, ['branch'] = args['type'] } }	end end local root = mw.html.create ( 'div' ) local function renderBox ( style, colour, lineName, lineTitle ) if colour then colour = string.match ( colour, '#' ) and colour or '#' .. colour end local box = mw.html.create ( 'span' ) -- Colour settings 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 ) if style == 'route' or style == 'croute' then box :css ( 'color',					typeData and typeData['text color'] or					lineData and lineData['text color'] or					require ( 'Module:Color contrast' )._greatercontrast ({ colour })				) end end -- Border settings if style == 'legend' or style == nil or		style == 'linked' or style == 'link' or		style == 'inline' or style == 'yes' or		style == 'box' then box:css ( 'border', '1px solid black' ) elseif style and string.match ( style, 'route' ) then box :css ( 'border', '.075em solid ' .. ( typeData and typeData['border color'] or				lineData and lineData['border color'] or				colour )			)		if style ~= 'route' then box:css ( 'border-radius', '.5em' ) end end -- Additional style-specific settings if style == 'legend' or style == nil then root :addClass ( 'legend' ) :css ( '-webkit-column-break-inside', 'avoid' ) :css ( 'page-break-inside', 'avoid' ) :css ( 'break-inside', 'avoid-column' ) box :addClass ( 'legend-color' ) :css ( 'display', 'inline-block' ) :css ( 'width', '1.5em' ) :css ( 'height', '1.5em' ) :css ( 'margin', '1px' ) elseif style == 'dot' or		style == 'ldot' or		style == 'square' or		style == 'lsquare' then box:css ( 'line-height', 'initial' ) elseif style and string.match ( style, 'route' ) then box :css ( 'font-weight', 'bold' ) :css ( 'font-size', 'inherit' ) :css ( 'white-space', 'nowrap' ) :css ( 'padding', '0 .3em' ) end -- Text for the span tag local boxText = { ['inline'] = string.rep ( ' ',4 ), ['yes'] = string.rep ( ' ', 4 ), ['box'] = string.rep ( ' ', 4 ), ['linked'] = string.rep ( ' ', 4 ), ['link'] = string.rep ( ' ', 4 ), ['small'] = string.rep ( ' ', 1 ), ['legend'] = string.rep ( ' ', 1 ), ['dot'] = '●', ['ldot'] = '●', ['square'] = '■', ['lsquare'] = '■', ['route'] = lineName, ['croute'] = lineName, ['xroute'] = lineName }	box:wikitext ( boxText[style] or string.rep ( ' ', 1 )) -- Adds link to text if style == 'linked' or style == 'link' or		style == 'ldot' or		style == 'lsquare' or		style and string.match ( style, 'route' ) then if string.match ( lineTitle, '%[%[.-%]%]' ) then if string.match ( lineTitle, '|' ) then root:wikitext (( string.gsub ( lineTitle, '%[%[(.-)|.-%]%]',  .. tostring ( box ) ..  ))) else root:wikitext (( string.gsub ( lineTitle, '%[%[(.-)%]%]',  .. tostring ( box ) ..  ))) end else root:wikitext ( tostring ( box )) end else root:wikitext ( tostring ( box )) end end p.line = makeInvokeFunc ( '_line' ) function p._line ( args, frame ) if data then local s = typeData and typeData['title'] and table.concat ({ lineData['title'], ' (', typeData['title'], ')' }) or			lineData and lineData['title'] or			defaultData and ( string.gsub ( defaultData['title'], '%%1', args.line or '_default' )) if args.icon then if args.icon == 'image' then args.style = nil return p._icon ( args ) .. ' ' .. s			elseif args.icon == 'legend' or				args.icon == 'inline' or				args.icon == 'small' or				args.icon == 'dot' or				args.icon == 'square' then renderBox ( args.icon, p._color ( args ), args.line, s ) root:wikitext ( ' ', s ) return root end else return s		end else return frame:expandTemplate { title = args.system and args.system .. ' lines', args = { args.line, ['branch'] = args['type'] } }	end end p.icon = makeInvokeFunc ( '_icon' ) function p._icon ( args, frame ) if data then local s = typeData and typeData['icon'] or			lineData and lineData['icon'] or			data and data['system icon'] if not s or			args.style == 'box' or			args.style == 'linked' or args.style == 'link' or			args.style == 'ldot' or			args.style == 'lsquare' or			args.style and string.match ( args.style, 'route' ) then renderBox ( args.style or 'inline', p._color ( args ), args.line, p._line ( args )) return root else return s		end else return frame:expandTemplate { title = 'Rail-interchange', args = { string.lower ( args.system ), string.lower ( args.line ),	['size'] = args.size } }	end end p.box = makeInvokeFunc ( '_box' ) function p._box ( args, frame ) local lineTitle = p._line ( args, frame ) local style = args.style or args.inline or args[3] or		dig ( typeData, 'icon format' ) or		dig ( lineData, 'icon format' ) or		dig ( data, 'system icon format' ) renderBox ( style, p._color ( args, frame ), args.line, lineTitle ) if style == 'legend' or style == nil or		style == 'inline' or style == 'yes' or		style == 'small' or		style == 'dot' or		style == 'square' then root:wikitext ( ' ', lineTitle ) end return root end p.main = makeInvokeFunc ( '_adjacent' ) p.adjacent = makeInvokeFunc ( '_adjacent' ) function p._adjacent ( args ) local yesNo = require ( 'Module:Yesno' ) local i18n = require ( 'Module:Adjacent stations/i18n' ) local root, lang = mw.html.create ( 'table' ), 'en-GB' root:addClass ( 'wikitable adjacent-stations' ) local function renderHeader ( stopNoun, systemIcon, systemTitle ) root :tag ( 'tr' ) :tag ( 'th' ) :addClass ( 'hcA' ) :wikitext ( i18n[lang]['preceding']( stopNoun )) :done :tag ( 'th' ) :attr ( 'colspan', 3 ) :css ( 'vertical-align', 'middle' ) :wikitext (						systemIcon and systemTitle and systemIcon .. ' ' .. systemTitle or						systemTitle or						systemIcon					) :done :tag ( 'th' ) :addClass ( 'hcA' ) :wikitext ( i18n[lang]['following']( stopNoun )) end local function renderSubHeader ( subHeader ) root :tag ( 'tr' ) :tag ( 'th' ) :attr ( 'colspan', 5 ) :addClass ( 'hmA' ) :wikitext ( subHeader ) end local function renderSideCell ( row, rowSpan, adjacent, terminus, oneWay, circular, through, Reverse, note ) local mainText, subText = mw.html.create ( 'div' ) if adjacent then mainText:wikitext ( adjacent ) subText = mw.html.create ( 'div' ) subText:addClass ( 'isA' ) if adjacent == terminus then subText:wikitext ( 'Terminus' ) else subText:wikitext ( oneWay and 'one-way operation' or circular and terminus or i18n[lang]['towards']( terminus )) end else mainText:css ( 'font-style', 'italic' ) mainText:wikitext ( Reverse and 'Reverses direction' or through and i18n[lang]['through']( through ) or 'Terminus' ) end row :tag ( 'td' ) :attr ( 'rowspan', rowSpan ) :addClass ( 'bcA' ) :node ( mainText ) :tag ( 'div' ) :css ( 'font-size', 'smaller' ) :wikitext ( note ) :done :node ( subText ) end local function renderMidCells ( row, rowSpan, colour, backgroundColour, lineTitle, typeTitle, note, transfer ) if colour then colour = string.match ( colour, '#' ) and colour or '#' .. colour end row :tag ( 'td' ) :attr ( 'rowspan', rowSpan ) :addClass ( 'bbA' ) :css ( 'background-color', colour ) :done :tag ( 'td' ) :attr ( 'rowspan', rowSpan ) :addClass ( 'bcA' ) :css ( 'background-color', backgroundColour ) :wikitext ( lineTitle ) :tag ( 'div' ) :wikitext ( typeTitle ) :done :tag ( 'div' ) :css ( 'font-size', 'smaller' ) :wikitext ( note ) :done :tag ( 'div' ) :addClass ( 'isA' ) :wikitext ( i18n[lang]['transfer']( transfer )) :done :done :tag ( 'td' ) :attr ( 'rowspan', rowSpan ) :addClass ( 'bbA' ) :css ( 'background-color', colour ) end local function renderNonStopRow ( title, colour, isFormer ) if colour then colour = string.match ( colour, '#' ) and colour or '#' .. colour end root :tag ( 'tr' ) :tag ( 'td' ) :attr ( 'colspan', 5 ) :addClass ( 'bcA' ) :tag ( 'div' ) :tag ( 'span' ) :css ( 'border', '1px solid black' ) :css ( 'background-color', colour ) :wikitext ( string.rep ( ' ', 4 )) :done :wikitext ( ' ', isFormer == true and i18n[lang]['nonstop_past']( title ) or i18n[lang]['nonstop_present']( title )) end local function renderNoteRow ( note ) root :tag ( 'tr' ) :tag ( 'td' ) :attr ( 'colspan', 5 ) :addClass ( 'bcA' ) :wikitext ( note ) end local function makeTerminusFunc ( n, fallback ) return function ( side ) local termini = fallback ( side .. ' terminus' ) if type ( termini ) == 'string' then return stationTitle ( termini, args, n ) elseif type ( termini ) == 'table' then local i, t, to = 1, {}, args[n]['to-' .. side] or args[n]['to'] while termini[i] and to ~= termini[i] do					t[i] = stationTitle ( termini[i], args, n ) i = i + 1 end local via = stationTitle ( termini['via'], args, n ) return stationTitle ( termini[i], args, n ) or via and mw.text.listToText ( t, nil, ' or ' ) .. ' via ' .. via or					mw.text.listToText ( t, nil, ' or ' ) end end end data = {} local j, k, l = 2, 2, 2 for i, v in ipairs ( args ) do		if v.header then renderSubHeader ( v.header ) end args[i]['system'] = args[i]['system'] or i > 1 and args[i - 1]['system'] if args[i]['system'] then data[i] = mw.loadData ( 'Module:Adjacent stations/' .. args[i]['system'] ) lang = dig ( data[i], 'lang' ) or 'en-GB' defaultData = function ( n ) return dig ( data[n], 'lines', '_default' ) end if args[i]['line'] then args[i]['line'] = dig ( data[i], 'lines', args[i]['line'] ) and args[i]['line'] or					dig ( data[i], 'aliases', string.lower ( args[i]['line'] )) or					error ( i18n[lang]['error_unknown']( args[i]['line'] )) else args[i]['line'] = i == 1 and '_default' or args[i - 1]['line'] end lineData = function ( n, line ) return dig ( data[n], 'lines', line or v.line ) or				dig ( data[n], 'lines', dig ( data[n], 'aliases', string.lower ( line or v.line ))) end typeData = function ( n ) return dig ( lineData ( n ), 'types', v['type'] ) end local function fallback ( parameter, n ) return dig ( typeData ( n or i ), parameter ) or dig ( lineData ( n or i ), parameter ) or dig ( defaultData ( n or i ), parameter ) end local terminus = makeTerminusFunc ( i, fallback ) if i == 1 or args[i]['system'] ~= args[i - 1]['system'] then renderHeader (					data[i]['header stop noun'] or i18n[lang]['stop_noun'],					data[i]['system icon'],					data[i]['system title']			) end if v.nonstop then renderNonStopRow ( fallback ( 'title' ), fallback ( 'color' ), v.nonstop == 'former' ) else local row = root:tag ( 'tr' ) if i > j - 2 then while args[j] and args[j]['left'] == args[i]['left'] and args[j]['to-left'] == args[i]['to-left'] and args[j]['oneway-left'] == args[i]['oneway-left'] and args[j]['note-left'] == args[i]['note-left'] and ( args[j]['through-left'] or args[j]['through'] ) == ( args[i]['through-left'] or args[i]['through'] ) and ( args[j]['reverse-left'] or args[j]['reverse'] ) == ( args[i]['reverse-left'] or args[i]['reverse'] ) and fallback ( 'oneway-left', j ) == fallback ( 'oneway-left' ) and fallback ( 'circular', j ) == fallback ( 'circular' ) and not args[j]['nonstop'] and not args[j]['note-row'] do						j = j + 1 end renderSideCell (						row,						j - i,						stationTitle ( v.left, args, i ),						yesNo ( fallback ( 'circular' )) and fallback ( 'left terminus' ) or terminus ( 'left' ),						yesNo ( v['oneway-left'] or fallback ( 'oneway-left' )),						yesNo ( fallback ( 'circular' )),						( v['through-left'] or v['through'] ) and dig ( lineData ( i, v['through-left'] or v['through'] ), 'title' ),						yesNo ( v['reverse-left'] or v['reverse'] ),						v['note-left']				) j = j + 1 end if i > k - 2 then while args[k] and args[k]['line'] == args[i]['line'] and args[k]['type'] == args[i]['type'] and args[k]['note-mid'] == args[i]['note-mid'] and not args[k]['nonstop'] and not args[k]['note-row'] do						k = k + 1 end renderMidCells (						row,						k - i,						fallback ( 'color' ),						fallback ( 'background color' ),						lineData ( i )['title'] or ( string.gsub ( dig ( defaultData ( i ), 'title' ), '%%1', v.line )),						typeData ( i ) and typeData ( i )['title'],						v['note-mid'] or lineData ( i )['note-mid'],						stationTitle ( v.transfer, args, i )				) k = k + 1 end if i > l - 2 then while args[l] and args[l]['right'] == args[i]['right'] and args[l]['to-right'] == args[i]['to-right'] and args[l]['oneway-right'] == args[i]['oneway-right'] and args[l]['note-right'] == args[i]['note-right'] and ( args[l]['through-right'] or args[l]['through'] ) == ( args[i]['through-right'] or args[i]['through'] ) and ( args[l]['reverse-right'] or args[l]['reverse'] ) == ( args[i]['reverse-right'] or args[i]['reverse'] ) and fallback ( 'oneway-right', l ) == fallback ( 'oneway-right' ) and fallback ( 'circular', l ) == fallback ( 'circular' ) and not args[l]['nonstop'] and not args[l]['note-row'] do						l = l + 1 end renderSideCell (						row,						l - i,						stationTitle ( v.right, args, i ),						yesNo ( fallback ( 'circular' )) and fallback ( 'right terminus' ) or terminus ( 'right' ),						yesNo ( v['oneway-right'] or fallback ( 'oneway-right' )),						yesNo ( fallback ( 'circular' )),						( v['through-right'] or v['through'] ) and dig ( lineData ( i, v['through-right'] or v['through'] ), 'title' ),						yesNo ( v['reverse-right'] or v['reverse'] ),						v['note-right']				) l = l + 1 end end end if v['note-row'] then renderNoteRow ( v['note-row'] ) end end return root 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 = {} 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 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', '\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