Narutopedia
Register
Advertisement

Documentation for this module may be created at Module:HF/Infobox/doc

local Infobox = {}

------------------------------------
-- Libraries and Global functions --
------------------------------------
-- stands for High Frequency
local HF = require('Module:HF')
-- Parses invocation and template parameters, trims whitespace, and removes blanks.
local getArgs = require('Dev:Arguments').getArgs
-- Generates lists
local L = require('Dev:List')
-- MediaNav Functions
local MN = require('Module:HF/MediaNav')._MediaNav

-- The page title of whatever page is calling the function
local pageTitle = mw.title.getCurrentTitle().text

-- Pattern Constants
local stripLinkToTarget = '^%[*([^%[|]*)|?'
local stripPageTitleToBase = "%s?([^(]*)"
local basepattern = '^[^~]*'
local extra1pattern = '^[^~]*~([^~]*)'
local extra2pattern = '^[^~]*~[^~]*~([^~]*)'

------------------------------------------------
-- Local functions (used only in this Module) --
------------------------------------------------
local function nameCheck ( target )
	local nq = mw.smw.ask{ HF.Link(target:match(stripLinkToTarget)), '?Maintenance' }
	if type(nq) == 'table' 
	    and (
	        nq[1]['Maintenance'] == 'Name'
	        or (
	            type(nq[1]['Maintenance']) == 'table' 
                and table.concat(nq[1]['Maintenance']):match('Name')
                )
            )
	then
		return true
	else return nil
	end
end

local function arrayRemove (args)
	local hash = {}
	if (args[1] == nil) then return '' end
	local t = mw.text.split(args[1], ",")
	local s = mw.text.split(args[2], ",")

	for i, v in ipairs(t) do
		t[i] = mw.text.trim(v)
		hash[t[i]] = true
	end

	if args[3] == '' then args[3] = false end
	if args[3] and not hash[args[3]] then return table.concat(t, ", ") end

	for i, v in ipairs(s) do
		s[i] = mw.text.trim(v)
	end

	for j = #s, 1, -1 do
		for i = #t, 1, -1 do
			if t[i] == s[j] then
				table.remove(t, i)
			end
		end
	end
	return table.concat(t, ", ")
end

local function linkCheck ( candidate )
	return
		candidate:match('^%[%[')
		and candidate
		or HF.Link( candidate )
end

----------------------------------------------------------
-- Public functions (called from a Template or article) --
----------------------------------------------------------
-- Replaces {{Infobox/Slideshow}} and {{Infobox/Tabber}}
-- with a comparable tabbed gallery for inside a PI.
-- Also replaces the "Missing image" Maintenance function
-- Also replaces the {{SetPicture}}
function Infobox.imageGallery (frame)
	local infobox_args = getArgs(frame, { parentOnly = true })
	local invoke_args = getArgs(frame, { frameOnly = true })
	local image_string = infobox_args[invoke_args[1]]
	if image_string then
		local gallery = { '{{#tag:gallery|\n' }
		local image_items = mw.text.split( mw.text.trim(image_string), '\n')
		for _,item in ipairs(image_items) do
			table.insert(
				gallery,
				tostring(string.gsub( item, ';', '{{!}}'):match('[^:]*'))..'\n'
			)
			mw.smw.set{ ['Picture'] = 'File:' .. item:match("[^;:]*") }
		end
		table.insert( gallery, '}}')
	local gallery_preprocess =
		frame:newParserValue( table.concat( gallery, '\n' ) )
	return gallery_preprocess:expand()
	else
		mw.smw.set{ ['Maintenance'] = 'Missing image' }
		return nil
	end
end

function Infobox.nameDistinct (frame)
	local infobox_args = getArgs(frame, { parentOnly = true })
	local invoke_args = getArgs(frame, { frameOnly = true })
	if mw.text.trim(pageTitle:match(stripPageTitleToBase)) == infobox_args[invoke_args[1]] then
		return nil
	else
		return infobox_args[invoke_args[1]]
	end
end

function Infobox.namesOther ( frame )
	local args = getArgs(frame)
	local out = {}
	local names = args['other'] 
	    and mw.text.split( args['other'] or '', ',' ) 
	    or ''
	for _,name in ipairs( names ) do
		mw.smw.set{ ['Names'] = name:match("[^(]*"):gsub("'''", '') }
		table.insert( out, name )
	end
	return L.makeList( 'bulleted' , out )
end

function Infobox.linkSBP ( frame )
	local invoke_args = getArgs(frame, { frameOnly = true })
	return HF.ExternalLink(
		('%s/wiki/Special:SearchByProperty?property=%s&value=%s')
			:format(
				mw.site.server,
				invoke_args['property'],
				mw.uri.encode( invoke_args['value'], 'QUERY' )
			),
		invoke_args['link'] or ''
	)
end

-- Manga debut processing
-- Replaces function for {{Infobox/Debut}}
function Infobox.debutManga(frame)
	local args = getArgs(frame)
	local debut = args['manga debut'] or args['debut manga']
	local SasukeRetsuden = args['sasuke retsuden'] == 'Yes' and true or nil
	local KonohaShinden = args['konoha shinden'] == 'Yes' and true or nil
	local BlueVortex = args['blue vortex'] == 'Yes' and true or nil
	local query =
		mw.smw.ask {
			( HF.Link('Concept:Chapter of %s Manga') ):format( args['boruto'] == 'Yes' and 'Boruto' or args['sasuke retsuden'] == 'Yes' and 'Sasuke Retsuden' or args['konoha shinden'] == 'Yes' and 'Konoha Shinden' or args['blue vortex'] == 'Yes' and 'Boruto Two Blue Vortex' or 'Naruto' ),
			( HF.Link('Chapter number::%s') ):format( Infobox.base( debut ) ),
			'?Volume number=',
			'mainlabel=-'
		}
	mw.smw.set {
		['Debut manga'] = Infobox.base( debut ),
		['Debut manga type'] = args['manga type'] or 'Chapter',
		['Manga'] = ( args['boruto'] == 'Yes' and 'Boruto' or args['sasuke retsuden'] == 'Yes' and 'Sasuke Retsuden'  or args['konoha shinden'] == 'Yes' and 'Konoha Shinden' or args['blue vortex'] == 'Yes' and 'Blue Vortex' or 'Naruto' )
	}
	if type(query) == 'table' then
		local volume = query[1][1]

		local volume_link =
			MN {
				'Volume',
				volume,
				['DisplayType'] = 'Number',
				['boruto'] = args['boruto'],
				['sasukeretsuden'] = args['sasuke retsuden'],
				['konohashinden'] = args['konoha shinden'],
				['bluevortex'] = args['blue vortex']
			}

		local chapter_link =
			MN {
				args['manga type'] or 'Chapter',
				Infobox.base( debut ),
				['DisplayType'] = 'Number',
				['boruto'] = args['boruto'],
				['sasukeretsuden'] = args['sasuke retsuden'],
				['konohashinden'] = args['konoha shinden'],
				['bluevortex'] = args['blue vortex']
			}

		return ( volume_link or '' ) ..
			(( volume_link and chapter_link ) and ', ' or '') ..
			( chapter_link or '' ) ..
			( Infobox.extra1( debut ) and (' <sup>(%s)</sup>'):format( Infobox.extra1( debut ) ) or '' )
	else
		return nil
	end
end

-- Anime debut processing
-- Replaces function for {{Infobox/Debut}}
function Infobox.debutAnime(frame)
	local args = getArgs(frame)
	local debut = args['anime debut'] or args['debut anime']
	local Boruto = args['boruto anime'] == 'Yes' and true or nil
	local Shippuden = (args['shippuden'] or args['debut shippuden']) == 'Yes' and true or nil
	local number = tonumber( Infobox.base( debut ) ) + ( Boruto and 720 or ( Shippuden and 220 or 0 ))
	mw.smw.set { ['Debut anime'] = number }
	return MN {
		'Episode',
		Infobox.base( debut ),
		['DisplayType'] = 'Number',
		['shippuden'] = args['shippuden'] or args['debut shippuden'],
		['boruto'] = args['boruto anime']
	}
end

-- Novel debut processing
-- Replaces function for {{Infobox/Debut}}
function Infobox.debutNovel(frame)
	local args = getArgs(frame)
	local debut = args['novel debut']
	mw.smw.set { ['Debut novel'] = mw.text.trim( Infobox.base( debut ) ):match(stripLinkToTarget) }
	return ("''%s''"):format( linkCheck( Infobox.base( debut ) ) .. ( Infobox.extra1( debut ) or '' ) )
end

-- Movie debut processing
-- Replaces function for {{Infobox/Debut}}
function Infobox.debutMovie(frame)
	local args = getArgs(frame)
	local debut = args['movie debut']
	mw.smw.set {
		['Debut movie'] = mw.text.trim( Infobox.base( debut ) ):match(stripLinkToTarget)
	}
	return ("''%s''"):format( linkCheck( Infobox.base( debut ) ) .. ( Infobox.extra1( debut ) or '' ) )
end

-- Game debut processing
-- Replaces function for {{Infobox/Debut}}
function Infobox.debutGame(frame)
	local args = getArgs(frame)
	local debut = args['game debut']
	mw.smw.set {
		['Debut game'] = mw.text.trim( Infobox.base( debut ) ):match(stripLinkToTarget)
	}
	return ("''%s''"):format( linkCheck( Infobox.base( debut ) ) .. ( Infobox.extra1( debut ) or '' ) )
end

-- OVA debut processing
-- Replaces function for {{Infobox/Debut}}
function Infobox.debutOVA(frame)
	local args = getArgs(frame)
	local debut = args['ova debut']
	mw.smw.set {
		['Debut ova'] = mw.text.trim( Infobox.base( debut ) ):match(stripLinkToTarget)
	}
	return ("''%s''"):format( linkCheck( Infobox.base( debut ) ) .. ( Infobox.extra1( debut ) or '' ) )
end

-- Media debut processing
-- Replaces function for {{Infobox/Debut}}
function Infobox.debutMedia(frame)
	local args = getArgs(frame)
	local media = arrayRemove {
		( args['media'] or args['jutsu media'] or args['tool media'] or '' ),
		'Movie canon', 'Movie'
	}
	for _,medium in ipairs( mw.text.split( media, ',%s*') ) do
		mw.smw.set { ['Appears in'] = medium }
	end
	return Infobox.arraymap( media:gsub('Movie canon', 'Movie') or '', ',%s*', '%s', ', ' )
end

---------------------------------------------------------
-- Exported functions (used in this and other Modules) --
---------------------------------------------------------
function Infobox.base( str )
	return ( type(str) == 'string' and str:match( basepattern ) )
			and mw.text.trim(str:match( basepattern ))
				or nil
end
function Infobox.extra1( str )
	return ( type(str) == 'string' and str:match( extra1pattern ) )
			and mw.text.trim( str:match( extra1pattern ) )
			or nil
end
function Infobox.extra2( str )
	return ( type(str) == 'string' and str:match( extra2pattern ) )
			and mw.text.trim( str:match( extra2pattern ) )
			or nil
end

function Infobox.arraymap ( str, delimiter, formula, new_delimiter )
	delimiter = delimiter or ',%s*'
	local array = type(str) == 'string' and mw.text.split( str, delimiter ) or nil
	local out = {}
	if type(array) == 'table' then
		for _, v in ipairs( array ) do
				table.insert( out , ( formula ):format( v ) )
		end
		return table.concat( out, new_delimiter )
	else return nil
	end
end

function Infobox.processInput( item, options, frame )
	local out = {}
  local exists = #item > 0 and true or nil
	item = options['Replace'] and tostring( item:gsub( options['Replace'][1], options['Replace'][2] )) or item
	local itemName, extrainfo1, extrainfo2 =
		item:match('^([^~\r\n]*)~?([^~\r\n]*)~?([^~\r\n]*)')
	extrainfo1 = #extrainfo1 > 0 and (' (%s)'):format( extrainfo1 ) or nil
	extrainfo2 = #extrainfo2 > 0 and (' <sup>(%s)</sup>'):format( extrainfo2 ) or nil
	local itemTitle = itemName:match(stripLinkToTarget)
	local itemLabel = itemTitle:match(stripPageTitleToBase)
	if options['SemanticPropertyName']
		and type( options['SemanticPropertyName'] ) == 'string' then

		local property = {}
		--[==[
		if options.SemanticPattern ~= nil then
			for _,match in itemName:match(options.SemanticPattern) do
				property = {}
				property[options.SemanticPropertyName] = match
				mw.smw.set ( property )
			end
		else
		--]==]
			property[ options['SemanticPropertyName'] ] = itemName
			mw.smw.set ( property )
		--[==[
		end
		--]==]
	elseif options['SemanticPropertyName']
		and type( options['SemanticPropertyName'] ) == 'table' then
			local properties = {}
			for _,property_name in ipairs( options['SemanticPropertyName'] ) do
				properties[property_name] = itemName
			end
			mw.smw.set ( properties )
	end
	if options['PrependTemplate'] and exists then
		local PrependTemplate =
			frame:newTemplateParserValue {
				title = options['PrependTemplate'],
				args = { item, options['PrependText'] or nil }
			}
		table.insert(
			out,
			PrependTemplate:expand()
		)
	end
	if type(options['Label']) == 'table' and type(options['Item Attribute']) == 'string' then
		table.insert( out, options['Label'][options['Item Attribute']] )
	elseif type(options['Label']) == 'string' then
		table.insert( out, options['Label'] )
	end
	if options['Warning'] and options['SemanticPropertyName'] then
		mw.smw.set { ['Has improper value for'] = options['SemanticPropertyName'] }
		local warning = frame:preprocess(('{{#info:%s|warning}}'):format(options['Warning']))
		table.insert( out, warning:expand() )
	elseif options['Warning'] then
		local warning = frame:preprocess(('{{#info:%s|warning}}'):format(options['Warning']))
		table.insert( out, warning:expand() )
	end
	if options['Link'] == 'Wikipedia' and exists and options['Print'] ~= 'none' then
		table.insert( out, HF.Link('wikipedia:' .. itemTitle, itemLabel) )
	elseif options['Link'] == 'Unnamed' and exists and options['Print'] ~= 'none' then
		table.insert(
			out,
			nameCheck(itemTitle) == true
			and ("''%s''"):format( HF.Link( itemTitle, itemLabel ) )
			or HF.Link( itemTitle, itemLabel )
		)
	elseif options['Link'] == 'Unit'
		and type(options['Unit']) == 'string'
		and exists
		and options['Print'] ~= 'none'
		 then

		table.insert( out, itemName .. options['Unit'] )
	elseif options['Link'] == 'default' and exists and options['Print'] ~= 'none' then
		table.insert( out, HF.Link( itemTitle, itemLabel ) )
	elseif options['Link'] == 'none' and exists and options['Print'] ~= 'none' then
		table.insert( out, itemName )
	end
	if options['AppendTemplate'] and exists then
		local AppendTemplate =
			frame:newTemplateParserValue {
				title = options['AppendTemplate'],
				args = { item, options['AppendText'] or nil }
			}
		table.insert(
			out,
			AppendTemplate:expand()
		)
	end
	if options['SearchByProperty']
		and options['SemanticPropertyName']
		and exists then

		local propcount =
			mw.smw.ask {
				HF.Link( options['SemanticPropertyName'] .. '::' .. itemTitle )
			}
		if type( propcount ) == 'table' and #propcount > 1 then
			local search_icon = '[[File:Icon_-_Search.png|12px|link=]]'
			local queryoptions =
				mw.uri.buildQueryString {
					property = mw.uri.encode( options['SemanticPropertyName'], 'WIKI' ),
					value = mw.uri.encode( itemTitle, 'WIKI' )
				}
			local _linkSBP = mw.html.create( 'abbr' )
				:attr(
					'title',
					('Search the other %s pages containing the property `%s` with the value `%s`')
						:format( #propcount, options['SemanticPropertyName'], itemTitle )
				)
				:wikitext(
				    HF.ExternalLink(
				        tostring( mw.uri.fullUrl( 'Special:SearchByProperty', queryoptions) ),
				        search_icon )
			    )
				:allDone()
			table.insert( out, tostring( _linkSBP ) )
		end
	end
	if options['ExtraInfo']
		and options['ExtraInfo'] ~= false
		and type( extrainfo1 ) == 'string'
		then
		table.insert( out, extrainfo1 )
	end
	if options['ExtraInfo']
		and options['ExtraInfo'] ~= false
		and type( extrainfo2 ) == 'string'
		then
		table.insert( out, extrainfo2 )
	end
	if exists then
		return table.concat( out )
	end
end

function Infobox.arrayTable ( input, delimiter, options, frame )
	delimiter = delimiter or ',%s*'
	options = options or {}
	local array = type(input) == 'string' and mw.text.split( input, delimiter ) or nil
	local out = {}
	if type(array) == 'table' then
	    for _, item in ipairs( array ) do
	        local i = Infobox.processInput( item, options, frame )
		    table.insert( out, i )
		end
		return out
	else return nil
	end
end

function Infobox.mediaDebutList ( query )
	if type( query ) == 'table' then
		local out = {}
		for _,v in ipairs( query ) do
			local link = HF.Link(
				v['main']:match('^%[*([^%[|]*)|?'),
				v['main']:match('[^(]*'):match('^%[*:?([^%[|]*)|?')
			)
			if v['Maintenance'] == 'Name'
			    or (
			        type(v['Maintenance']) == 'table' 
		            and table.concat(v['Maintenance']):match('Name')
	                ) then
				table.insert( out, ("''%s''"):format(link) )
			else
				table.insert( out, link )
			end
		end
		return L.makeList( 'bulleted' , out )
	else
		return nil
	end
end
-------------------------------------------------
-- Output (send it back to whatever called it) --
-------------------------------------------------
return Infobox
Advertisement