Модуль:HF/Infobox

Материал из Викимультии — энциклопедии мультипликации
Перейти к навигации Перейти к поиску


Документация
local Infobox = {}
-------------------------------------
-- Библиотеки и глобальные функции --
-------------------------------------
-- обозначает высокочастотный
local HF = require('Module:HF')
-- Анализирует параметры вызова и шаблона, удаляет пробелы и удаляет пробелы.
local getArgs = require('Module:Arguments').getArgs
-- Создает списки
local L = require('Module:List')
-- Функции MediaNav
local MN = require('Module:HF/MediaNav')._MediaNav

-- Заголовок любой страницы, вызывающей функцию
local pageTitle = mw.title.getCurrentTitle().text

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

-----------------------------------------------------------
-- Локальные функции (используются только в этом модуле) --
-----------------------------------------------------------
local function nameCheck ( target )
	local nq = mw.smw.ask{ HF.Link(target:match(stripLinkToTarget)), '?Обслуживание' }
	if type(nq) == 'table' 
	    and (
	        nq[1]['Обслуживание'] == 'Название'
	        or (
	            type(nq[1]['Обслуживание']) == 'table' 
                and table.concat(nq[1]['Обслуживание']):match('Название')
                )
            )
	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

---------------------------------------------------------
-- Открытые функции (вызываются из шаблона или статьи) --
---------------------------------------------------------
-- Заменяет {{Infobox/Slideshow}} и {{Infobox/Tabber}}
-- с сопоставимой галереей с вкладками для внутри PI.
-- Также заменяет функцию обслуживания «Недостающее изображение»
-- Также заменяет {{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{ ['Изображение'] = 'Файл:' .. item:match("[^;:]*") }
		end
		table.insert( gallery, '}}')
	local gallery_preprocess =
		frame:newParserValue( table.concat( gallery, '\n' ) )
	return gallery_preprocess:expand()
	else
		mw.smw.set{ ['Обслуживание'] = 'Недостающее изображение' }
		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['другие названия'] 
	    and mw.text.split( args['другие названия'] or '', ',' ) 
	    or ''
	for _,name in ipairs( names ) do
		mw.smw.set{ ['Названия'] = 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

-- Дебют в манге
function Infobox.debutManga(frame)
	local args = getArgs(frame)
	local debut = args['дебют в манге']
	local query =
		mw.smw.ask {
			( HF.Link('Категория:Главы манги «%s»') ):format( args['боруто'] == 'Да' and 'Боруто: Следующее поколение Наруто' or 'Наруто' ),
			( HF.Link('Глава номер::%s') ):format( Infobox.base( debut ) ),
			'?Глава номер=',
			'mainlabel=-'
		}
	mw.smw.set {
		['Дебют в манге'] = Infobox.base( debut ),
		['Дебют в манге тип'] = args['тип манги'] or 'Глава',
		['Манга'] = ( args['боруто'] == 'Да' and 'Боруто: Следующее поколение Наруто' or 'Наруто' )
	}
	if type(query) == 'table' then
		local volume = query[1][1]

		local volume_link =
			MN {
				'Том',
				volume,
				['DisplayType'] = 'Number',
				['боруто'] = args['боруто']
			}

		local chapter_link =
			MN {
				args['тип манги'] or 'Глава',
				Infobox.base( debut ),
				['DisplayType'] = 'Number',
				['боруто'] = args['боруто']
			}

		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

-- Дебют в аниме
function Infobox.debutAnime(frame)
	local args = getArgs(frame)
	local debut = args['дебют в аниме']
	local Boruto = args['боруто аниме'] == 'Да' and true or nil
	local Shippuden = args['ураганные хроники'] == 'Да' and true or nil
	local number = tonumber( Infobox.base( debut ) ) + ( Boruto and 720 or ( Shippuden and 220 or 0 ))
	mw.smw.set { ['Дебют в аниме'] = number }
	return MN {
		'Эпизод',
		Infobox.base( debut ),
		['DisplayType'] = 'Number',
		['ураганные хроники'] = args['ураганные хроники'],
		['боруто'] = args['боруто аниме']
	}
end

-- Дебют в романе
function Infobox.debutNovel(frame)
	local args = getArgs(frame)
	local debut = args['дебют в романе']
	mw.smw.set { ['Дебют в романе'] = mw.text.trim( Infobox.base( debut ) ):match(stripLinkToTarget) }
	return ("''%s''"):format( linkCheck( Infobox.base( debut ) ) .. ( Infobox.extra1( debut ) or '' ) )
end

-- Дебют в фильме
function Infobox.debutMovie(frame)
	local args = getArgs(frame)
	local debut = args['дебют в фильме']
	mw.smw.set {
		['Дебют в фильме'] = mw.text.trim( Infobox.base( debut ) ):match(stripLinkToTarget)
	}
	return ("''%s''"):format( linkCheck( Infobox.base( debut ) ) .. ( Infobox.extra1( debut ) or '' ) )
end

-- Дебют в игре
function Infobox.debutGame(frame)
	local args = getArgs(frame)
	local debut = args['дебют в игре']
	mw.smw.set {
		['Дебют в игре'] = mw.text.trim( Infobox.base( debut ) ):match(stripLinkToTarget)
	}
	return ("''%s''"):format( Infobox.base( debut ) .. ( Infobox.extra1( debut ) or '' ) )
end

-- Дебют в OVA
function Infobox.debutOVA(frame)
	local args = getArgs(frame)
	local debut = args['дебют в ova']
	mw.smw.set {
		['Дебют в 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['медиа'] or args['дзюцу медиа'] or args['предмет медиа'] or args['появляется в'] or '' ),
		'Фильм канон', 'Фильм'
	}
	for _,medium in ipairs( mw.text.split( media, ',%s*') ) do
		mw.smw.set { ['Появляется в'] = medium }
	end
	return Infobox.arraymap( media:gsub('Фильм канон', 'Фильм') or '', ',%s*', '%s', ', ' )
end

-------------------------------------------------------------------
-- Экспортируемые функции (используются в этом и других модулях) --
-------------------------------------------------------------------
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['Обслуживание'] == 'Название'
			    or (
			        type(v['Обслуживание']) == 'table' 
		            and table.concat(v['Обслуживание']):match('Название')
	                ) then
				table.insert( out, ("''%s''"):format(link) )
			else
				table.insert( out, link )
			end
		end
		return L.makeList( 'bulleted' , out )
	else
		return nil
	end
end
-------------------------------------------------
-- Вывод (отправьте его обратно как угодно) --
-------------------------------------------------
return Infobox