Модуль:HF/Infobox/Jutsu: различия между версиями

Материал из Викимультии — энциклопедии мультипликации
Перейти к навигации Перейти к поиску
[непроверенная версия][отпатрулированная версия]
Нет описания правки
Нет описания правки
 
(не показано 13 промежуточных версий этого же участника)
Строка 1: Строка 1:
local Infobox = {}
local Infobox = {}
 
-------------------------------------
------------------------------------
-- Библиотеки и глобальные функции --
-- Libraries and Global functions --
-------------------------------------
------------------------------------
-- "Высокочастотные" функции
-- "High Frequency" functions
local HF = require('Module:HF')
local HF = require('Module:HF')
-- Parses invocation and template parameters, trims whitespace, and removes blanks.
-- Анализирует параметры вызова и шаблона, урезает пробелы и удаляет пробелы.
local getArgs = require('Module:Arguments').getArgs
local getArgs = require('Module:Arguments').getArgs
-- Generates lists
-- Формирует списки
local L = require('Module:List')
local L = require('Module:List')
-- Language functions
-- Языковые функции
local language = mw.language.new('ru')
local language = mw.language.new('ru')


-- Helper functions (local to not have to worry about namespaces)
-- Вспомогательные функции (локальные, чтобы не беспокоиться о пространствах имен)
local arraymap = require('Module:HF/Infobox').arraymap
local arraymap = require('Module:HF/Infobox').arraymap
local arrayTable = require('Module:HF/Infobox').arrayTable
local arrayTable = require('Module:HF/Infobox').arrayTable
Строка 19: Строка 18:
local extra1 = require('Module:HF/Infobox').extra1
local extra1 = require('Module:HF/Infobox').extra1


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


-- Convenient constants
-- Полезные константы
local stripLinkToTarget = '^%[*([^%[|]*)|?'
local stripLinkToTarget = '^%[*([^%[|]*)|?'
local stripPageTitleToBase = "[^(]*"
local stripPageTitleToBase = "[^(]*"
Строка 28: Строка 27:
local extra1pattern = '^[^~]*~([^~]*)'
local extra1pattern = '^[^~]*~([^~]*)'


------------------------------------------------
-------------------------------------------------------------
-- Local functions (used only in this Module) --
-- Локальные функции (используются только в данном модуле) --
------------------------------------------------
-------------------------------------------------------------
-- Replaces {{IsUnnamed}}
-- Replaces {{IsUnnamed}}
local function nameCheck ( target )
local function nameCheck ( target )
Строка 37: Строка 36:
    and (
    and (
        nq[1]['Обслуживание'] == 'Название'
        nq[1]['Обслуживание'] == 'Название'
        or (type(nq[1]['Обслуживание']) == 'table' and table.concat(nq[1]['Обслуживание']):match('Name'))
        or (type(nq[1]['Обслуживание']) == 'table' and table.concat(nq[1]['Обслуживание']):match('Название'))
    )
    )
         then
         then
Строка 45: Строка 44:
end
end


----------------------------------------------------------
---------------------------------------------------------
-- Public functions (called from a Template or article) --
-- Открытые функции (вызываются из шаблона или статьи) --
----------------------------------------------------------
---------------------------------------------------------
-- Creates the infobox main title
-- Creates the infobox main title
function Infobox.titleJutsu(frame)
function Infobox.titleJutsu(frame)
Строка 53: Строка 52:
local out = {}
local out = {}
if mw.title.getCurrentTitle().isContentPage == true then
if mw.title.getCurrentTitle().isContentPage == true then
table.insert( out, HF.Category('Дзюцу') )
table.insert( out, HF.Category('Дзюцу по алфавиту') )
local _editFormURL = mw.html.create('span')
:css('float','right'):css('font-size','x-small')
            :wikitext( HF.Link('Special:FormEdit/Jutsu/' .. pageTitle, 'edit') ):allDone()
local editFormURL = tostring(_editFormURL)
if args['название'] then
if args['название'] then
mw.smw.set {
mw.smw.set {
Строка 64: Строка 59:
}
}
end
end
-- Название кандзи
if args['кандзи'] then
if args['кандзи'] then
mw.smw.set {
mw.smw.set {
Строка 72: Строка 68:
mw.smw.set { ['Обслуживание'] = 'Кандзи' }
mw.smw.set { ['Обслуживание'] = 'Кандзи' }
end
end
--Название киридзи
if args['киридзи'] then
if args['киридзи'] then
mw.smw.set{
mw.smw.set{
Строка 78: Строка 76:
}
}
end
end
if args['команда'] then
local teams = mw.text.split( args['команда'], ',%s*' )
if args['команды'] then
local teams = mw.text.split( args['команды'], ',%s*' )
for _, v in ipairs(teams) do
for _, v in ipairs(teams) do
mw.smw.set{ ['Команда'] = mw.text.trim(v) }
mw.smw.set{ ['Команда'] = mw.text.trim(v) }
end
end
end
end
if args['клан'] then
local teams = mw.text.split( args['клан'], ',%s*' )
for _, v in ipairs(teams) do
mw.smw.set{ ['Клан'] = mw.text.trim(v) }
end
end
if args['изображение'] then
if args['изображение'] then
local images = mw.text.split( args['изображение'], '\n')
local images = mw.text.split( args['изображение'], '\n')
Строка 94: Строка 101:
mw.smw.set{ ['Обслуживание'] = 'Отсутствующее изображение' }
mw.smw.set{ ['Обслуживание'] = 'Отсутствующее изображение' }
end
end
if args['безымянное дзюцу'] == 'Да' then
if args['безымянное дзюцу'] == 'Да' then
mw.smw.set{ ['Обслуживание'] = 'Название' }
mw.smw.set{ ['Обслуживание'] = 'Название' }
table.insert( out, ("''%s''"):format( pageTitle:match("[^(]*") ) )
table.insert( out, (''%s''):format( pageTitle:match("[^(]*") ) )
else
else
table.insert( out, pageTitle:match("[^(]*") )
table.insert( out, pageTitle:match("[^(]*") )
end
end
local popup = frame:newParserValue(
"{{#queryformlink:form=Image query|link text=" ..
return table.concat( out ) .. ( args['ref'] or '' )
"[[File:Camera font awesome.svg|15px|link=]]" ..
"|query string=Image_query[jutsu]=" .. pageTitle ..
"&_run|wpRunQuery=true|popup|tooltip=Images of " .. pageTitle .. " }}"
)
return table.concat( out ) .. popup:expand() .. ( args['ref'] or '' ) .. editFormURL
elseif mw.title.getCurrentTitle().namespace == 10
elseif mw.title.getCurrentTitle().namespace == 10
    and not pageTitle:match('/testcases') then
    and not pageTitle:match('/testcases') then
Строка 116: Строка 119:
table.insert( out, args['название'] or pageTitle:match("[^(]*") )
table.insert( out, args['название'] or pageTitle:match("[^(]*") )
end
end
return table.concat( out ) .. ( args['ref'] or '' )
return table.concat( out ) .. ( args['ref'] or '' )
end
end
Строка 125: Строка 129:
type(args['классификация дзюцу']) == 'string'
type(args['классификация дзюцу']) == 'string'
and mw.text.split( args['классификация дзюцу'], ',%s*' )
and mw.text.split( args['классификация дзюцу'], ',%s*' )
if type(classifications) == 'table' then
if type(classifications) == 'table' then
local out = {}
local out = {}
local icons = {}
local icons = {}
local kekkei = {
local kekkei = {
['kekkei mōra'] = true,
['кэккэй мора'] = true,
['kekkei tōta'] = true,
['кэккэй тота'] = true,
['kekkei genkai'] = true
['кэккэй гэнкай'] = true
}
}
for _,classification in ipairs(classifications) do
for _,classification in ipairs(classifications) do
Строка 138: Строка 143:
local options = {
local options = {
['SemanticPropertyName'] = 'Клан',
['SemanticPropertyName'] = 'Клан',
['PrependText'] = 'Клан ниндзя',
['PrependText'] = 'Клан',
['PrependTemplate'] = 'Карточка/Значки',
['PrependTemplate'] = 'Карточка/Наруто/Значки',
['Print'] = 'none',
['Print'] = 'none',
['Link'] = 'default'
['Link'] = 'default'
Строка 149: Строка 154:
['SemanticPropertyName'] = 'Кэккэй Гэнкай',
['SemanticPropertyName'] = 'Кэккэй Гэнкай',
['PrependText'] = 'Кэккэй Гэнкай',
['PrependText'] = 'Кэккэй Гэнкай',
['PrependTemplate'] = 'Карточка/Значки',
['PrependTemplate'] = 'Карточка/Наруто/Значки',
['Print'] = 'none',
['Print'] = 'none',
['Link'] = 'default'
['Link'] = 'default'
Строка 171: Строка 176:
local options = {
local options = {
['SemanticPropertyName'] = 'Природа чакры',
['SemanticPropertyName'] = 'Природа чакры',
['PrependText'] = 'Природа',
['PrependText'] = 'Стихия',
['PrependTemplate'] = 'Карточка/Значки',
['PrependTemplate'] = 'Карточка/Наруто/Значки',
['Link'] = 'default'
['Link'] = 'default'
}
}
Строка 184: Строка 189:
local out = {}
local out = {}
for _, v in ipairs( array ) do
for _, v in ipairs( array ) do
table.insert( out , HF.Link('Ранг дзюцу::'..v, v..'-rank') )
table.insert( out , HF.Link('Ранг дзюцу::'..v, v..'-ранг') )
end
end
return table.concat( out, ',' )
return table.concat( out, ',' )
Строка 204: Строка 209:
['Короткий'] = 'Короткий диапазон (0-5м)',
['Короткий'] = 'Короткий диапазон (0-5м)',
['Средний'] = 'Средний диапазон (5-10м)',
['Средний'] = 'Средний диапазон (5-10м)',
['Длинный'] = 'Дальность действия (10 м+)',
['Длинный'] = 'Длинный диапазон (10м+)',
['Короткий, Средний, Длинный'] = 'Все диапазоны',
['Короткий, Средний, Длинный'] = 'Все диапазоны',
['Короткий, Средний'] = 'Короткий и средний диапазон (0-10м)',
['Короткий, Средний'] = 'Короткий в Средний диапазон (0-10м)',
['Средний, Длинный'] = 'Средний и длинный диапазон (5 м+)',
['Средний, Длинный'] = 'Средний в Длинный диапазон (+)',
['Короткий, Длинный'] = 'Короткий или длинный диапазон (0-5м или 10м+)'
['Короткий, Длинный'] = 'Короткий или Длинный диапазон (0-5м или 10м+)'
}
}
arrayTable ( args['диапазон дзюцу'], ',%s*', { ['SemanticPropertyName'] = 'Диапазон дзюцу' } )
arrayTable ( args['диапазон дзюцу'], ',%s*', { ['SemanticPropertyName'] = 'Диапазон дзюцу' } )
return ranges[args['диапазон дзюцу']] or args['jutsu range']..'-range'
return ranges[args['диапазон дзюцу']] or args['диапазон дзюцу']..'-диапазон'
end
end


Строка 218: Строка 223:
local options = {
local options = {
['SemanticPropertyName'] = 'Родительское дзюцу',
['SemanticPropertyName'] = 'Родительское дзюцу',
['Link'] = 'Безымянное',
['Link'] = 'Unnamed',
['UnnamedFormat'] = true
['UnnamedFormat'] = true
}
}
local Parents = arrayTable ( args['родительское дзюцу'], ',%s*', options )
local parents = arrayTable ( args['родительское дзюцу'], ',%s*', options )
return L.makeList( 'unbulleted', Parents )
return L.makeList( 'unbulleted', parents )
end
end


Строка 229: Строка 234:
local out = {}
local out = {}
local mtypes = {
local mtypes = {
['Фильм'] = 'Дзюцу/НеКанон',
['Фильм'] = 'Дзюцу/НеКанонический',
['Игра'] = 'Дзюцу/НеКанон',
['Игра'] = 'Дзюцу/НеКанонический',
['Игра, Фильм'] = 'Дзюцу/НеКанон'
['Игра, Фильм'] = 'Дзюцу/НеКанонический'
}
}
local mq = mw.smw.ask {
local mq = mw.smw.ask {
(HF.Link('Concept:%s')):format( mtypes[args['дзюцу медиа']] or 'Дзюцу/Канон' ),
(HF.Link('Concept:%s')):format( mtypes[args['дзюцу медиа']] or 'Дзюцу/Канонический' ),
(HF.Link('Родительское дзюцу::%s')):format( mw.title.getCurrentTitle().prefixedText ),
(HF.Link('Родительское дзюцу::%s')):format( mw.title.getCurrentTitle().prefixedText ),
'?Появляется в',
'?Появляется в',
Строка 243: Строка 248:
}
}
local hasNCderivatives = mw.smw.ask {
local hasNCderivatives = mw.smw.ask {
(HF.Link('Concept:%s')):format( 'Дзюцу/НеКанон' ),
(HF.Link('Concept:%s')):format( 'Дзюцу/НеКанонический' ),
(HF.Link('Родительское дзюцу::%s')):format( mw.title.getCurrentTitle().prefixedText )
(HF.Link('Родительское дзюцу::%s')):format( mw.title.getCurrentTitle().prefixedText )
}
}
if type(mq) == 'table' then
if type(mq) == 'table' then
for _, Parent in ipairs(mq) do
for _, parent in ipairs(mq) do
local mainlink =
local mainlink =
(
(
    Parent['Обслуживание'] == 'Название'
    parent['Обслуживание'] == 'Название'
    or (
    or (
        type(Parent['Обслуживание']) == 'table'
        type(parent['Обслуживание']) == 'table'
        and table.concat(Parent['Обслуживание']):match('Название')
        and table.concat(parent['Обслуживание']):match('Название')
            )
            )
    )
    )
and ("''%s''"):format(
and (''%s''):format(
HF.Link(
HF.Link(
Parent['main']:match(stripLinkToTarget),
parent['main']:match(stripLinkToTarget),
Parent['main']:match('%[%[:?([^|]*)|?'):match(stripPageTitleToBase)
parent['main']:match('%[%[:?([^|]*)|?'):match(stripPageTitleToBase)
)
)
)
)
or HF.Link(
or HF.Link(
Parent['main']:match(stripLinkToTarget),
parent['main']:match(stripLinkToTarget),
Parent['main']:match('%[%[:?([^|]*)|?'):match(stripPageTitleToBase)
parent['main']:match('%[%[:?([^|]*)|?'):match(stripPageTitleToBase)
)
)
local dq = mw.smw.ask {
local dq = mw.smw.ask {
(HF.Link('Concept:%s')):format( mtypes[args['дзюцу медиа']] or 'Дзюцу/Канон' ),
(HF.Link('Concept:%s')):format( mtypes[args['дзюцу медиа']] or 'Дзюцу/Канонический' ),
(HF.Link('Родительское дзюцу::%s')):format( Parent['main']:match(stripLinkToTarget) ),
(HF.Link('Родительское дзюцу::%s')):format( parent['main']:match(stripLinkToTarget) ),
('userparam=%s'):format( args['дзюцу медиа'] or 'Аниме, Манга' ),
('userparam=%s'):format( args['дзюцу медиа'] or 'Аниме, Манга' ),
'mainlabel=main',
'mainlabel=main',
Строка 324: Строка 329:


function Infobox.jutsuUsers(frame)
function Infobox.jutsuUsers(frame)
  local args = getArgs(frame)
local args = getArgs(frame)
  local out = {}
local out = {}
  -- Valid media types
-- Valid media types
  local mtypes = {
local mtypes = {
    anime = true, manga = true, novel = true,
['нет'] = true, ['аниме'] = true, ['манга'] = true,
    game = true, movie = true, ['фильм канон'] = true
['роман'] = true, ['игра'] = true, ['фильм'] = true, ['фильм канон'] = true
  }
}
   -- Divides users into actionable items (even if there's only one)
   -- Divides users into actionable items (even if there's only one)
   local users = args['пользователи'] and mw.text.split( args['пользователи'], ',%s*' )
   local users = args['пользователи'] and mw.text.split( args['пользователи'], ',%s*' )
Строка 351: Строка 356:
     --- AdditionalInfo
     --- AdditionalInfo
     -- Puppetry handling
     -- Puppetry handling
     local puppetry = user:match('~~puppet~(.*)$')
     local puppetry = user:match('~~марионетка~(.*)$')
     if puppetry then
     if puppetry then
       puppetry = (' ([[Марионетка]] использует %s)')
       puppetry = (' (Использование марионеток %s)')
         :format(mw.text.listToText(mw.text.split(puppetry, '~')))
         :format(mw.text.listToText(mw.text.split(puppetry, '~')))
     end
     end
     -- "with" handling
     -- "with" handling
     local with = user:match('~~with~([^%~]*)')
     local with = user:match('~~с~([^%~]*)')
       and (' (with %s)'):format(user:match('~~with~([^%~]*)'))
       and (' (с %s)'):format(user:match('~~с~([^%~]*)'))
     local AdditionalInfo = puppetry or with or ''
     local AdditionalInfo = puppetry or with or ''


Строка 365: Строка 370:
     if media
     if media
       and mtypes[media:lower()]
       and mtypes[media:lower()]
       and media:lower() ~= 'movie canon'
       and media:lower() ~= 'фильм канон'
     then
     then
       Media = ('<sup> (%s only)</sup>')
       Media = ('<sup> (%s)</sup>')
         :format( language:ucfirst( media ) )
         :format( language:ucfirst( media ) )
     elseif media
     elseif media
       and media:lower() == 'movie canon'
       and media:lower() == 'фильм канон'
       then
       then
         Media = '<sup> (Movie only)</sup>'
         Media = '<sup> (Фильм)</sup>'
     end
     end


     --- Summons
     --- Summons
     local cq = mw.smw.ask {
     local cq = mw.smw.ask {
       (HF.Link('Contract::%s')):format( prime:match(stripLinkToTarget) ),
       (HF.Link('Контракт::%s')):format( prime:match(stripLinkToTarget) ),
       'mainlabel=main'
       'mainlabel=main'
     }
     }
Строка 387: Строка 392:
     end
     end
     local Summons = ((#sl > 0)
     local Summons = ((#sl > 0)
         and ( pageTitle == 'Summoning Technique' or pageTitle == 'Destruction Bug Host Technique' ))
         and ( pageTitle == 'Техника Призыва' or pageTitle == 'Destruction Bug Host Technique' ))
       and ( ' (%s)' ):format( table.concat( sl, ", " ) )
       and ( ' (%s)' ):format( table.concat( sl, ", " ) )
       or ''
       or ''
Строка 396: Строка 401:
       or 'null'
       or 'null'
     mw.smw.set {
     mw.smw.set {
       ['User tech'] = prime .. ';' .. setmtype
       ['Пользователи техники'] = prime .. ';' .. setmtype
     }
     }



Текущая версия от 15:52, 14 февраля 2021


Документация
local Infobox = {}
-------------------------------------
-- Библиотеки и глобальные функции --
-------------------------------------
-- "Высокочастотные" функции
local HF = require('Module:HF')
-- Анализирует параметры вызова и шаблона, урезает пробелы и удаляет пробелы.
local getArgs = require('Module:Arguments').getArgs
-- Формирует списки
local L = require('Module:List')
-- Языковые функции
local language = mw.language.new('ru')

-- Вспомогательные функции (локальные, чтобы не беспокоиться о пространствах имен)
local arraymap = require('Module:HF/Infobox').arraymap
local arrayTable = require('Module:HF/Infobox').arrayTable
local base = require('Module:HF/Infobox').base
local extra1 = require('Module:HF/Infobox').extra1

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

-- Полезные константы
local stripLinkToTarget = '^%[*([^%[|]*)|?'
local stripPageTitleToBase = "[^(]*"
local basepattern = '^[^~]*'
local extra1pattern = '^[^~]*~([^~]*)'

-------------------------------------------------------------
-- Локальные функции (используются только в данном модуле) --
-------------------------------------------------------------
-- Replaces {{IsUnnamed}}
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

---------------------------------------------------------
-- Открытые функции (вызываются из шаблона или статьи) --
---------------------------------------------------------
-- Creates the infobox main title
function Infobox.titleJutsu(frame)
	local args = getArgs(frame)
	local out = {}
	if mw.title.getCurrentTitle().isContentPage == true then
		table.insert( out, HF.Category('Дзюцу по алфавиту') )
		if args['название'] then
			mw.smw.set {
				['Название'] = args['название'],
				['Названия'] = args['название']
			}
		end
		-- Название кандзи
		if args['кандзи'] then
			mw.smw.set {
				['Кандзи'] = args['кандзи'],
				['Названия'] = args['кандзи']
			}
		else
			mw.smw.set { ['Обслуживание'] = 'Кандзи' }
		end
		
		--Название киридзи
		if args['киридзи'] then
			mw.smw.set{
				['Киридзи'] = args['киридзи']:match(stripLinkToTarget),
				['Названия'] = args['киридзи']
			}
		end
		
		if args['команды'] then
			local teams = mw.text.split( args['команды'], ',%s*' )
			for _, v in ipairs(teams) do
				mw.smw.set{ ['Команда'] = mw.text.trim(v) }
			end
		end
		
		if args['клан'] then
			local teams = mw.text.split( args['клан'], ',%s*' )
			for _, v in ipairs(teams) do
				mw.smw.set{ ['Клан'] = mw.text.trim(v) }
			end
		end
		
		if args['изображение'] then
			local images = mw.text.split( args['изображение'], '\n')
			for _, image in ipairs(images) do
				if type(image) == 'string' then
					mw.smw.set{ ['Изображение'] = 'File:' .. image:match("[^:;]*") }
				end
			end
		else
			mw.smw.set{ ['Обслуживание'] = 'Отсутствующее изображение' }
		end
		
		if args['безымянное дзюцу'] == 'Да' then
			mw.smw.set{ ['Обслуживание'] = 'Название' }
			table.insert( out, (''%s''):format( pageTitle:match("[^(]*") ) )
		else
				table.insert( out, pageTitle:match("[^(]*") )
		end
		
		return table.concat( out ) .. ( args['ref'] or '' )
	elseif mw.title.getCurrentTitle().namespace == 10
	    and not pageTitle:match('/testcases') then
	    return nil
	else
		if args['безымянное дзюцу'] == 'Да' then
			table.insert( out, ("''%s''"):format( args['название'] or pageTitle:match("[^(]*") ) )
		else
			table.insert( out, args['название'] or pageTitle:match("[^(]*") )
		end
		
		return table.concat( out ) .. ( args['ref'] or '' )
	end
end

function Infobox.jutsuClassification(frame)
	local args = getArgs(frame)
	local classifications =
		type(args['классификация дзюцу']) == 'string'
		and mw.text.split( args['классификация дзюцу'], ',%s*' )
	
	if type(classifications) == 'table' then
		local out = {}
		local icons = {}
		local kekkei = {
			['кэккэй мора'] = true,
			['кэккэй тота'] = true,
			['кэккэй гэнкай'] = true
		}
		for _,classification in ipairs(classifications) do
			if classification:match(extra1pattern) then
				if classification:match(basepattern):lower() == 'hiden' then
					local options = {
						['SemanticPropertyName'] = 'Клан',
						['PrependText'] = 'Клан',
						['PrependTemplate'] = 'Карточка/Наруто/Значки',
						['Print'] = 'none',
						['Link'] = 'default'
					}
					local clans = arrayTable( classification:match('^[^~]*~(.*)'), '~', options, frame )
					table.insert( icons, table.concat( clans ) )
				elseif kekkei[classification:match(basepattern):lower()] then
					local options = {
						['SemanticPropertyName'] = 'Кэккэй Гэнкай',
						['PrependText'] = 'Кэккэй Гэнкай',
						['PrependTemplate'] = 'Карточка/Наруто/Значки',
						['Print'] = 'none',
						['Link'] = 'default'
					}
					local clans = arrayTable( classification:match('^[^~]*~(.*)'), '~', options, frame )
					table.insert( icons, table.concat( clans ) )
				end
			end
			if classification:match(basepattern) and #classification > 1 then
				mw.smw.set { ['Классификация дзюцу'] = classification:match(basepattern) }
				table.insert( out, HF.Link(classification:match(basepattern)) )
			end
		end
		return table.concat( icons ) .. table.concat( out, ', ' )
	else return nil
	end
end

function Infobox.jutsuType(frame)
	local args = getArgs(frame)
	local options = {
		['SemanticPropertyName'] = 'Природа чакры',
		['PrependText'] = 'Стихия',
		['PrependTemplate'] = 'Карточка/Наруто/Значки',
		['Link'] = 'default'
	}
	local values = arrayTable ( args['тип дзюцу'], ',%s*', options, frame )
	return L.makeList( 'unbulleted' , values )
end

function Infobox.jutsuRank(frame)
	local args = getArgs(frame)
	local array = mw.text.split( args['ранг дзюцу'], ',' )
	local out = {}
	for _, v in ipairs( array ) do
		table.insert( out , HF.Link('Ранг дзюцу::'..v, v..'-ранг') )
	end
	return table.concat( out, ',' )
end

function Infobox.jutsuClass(frame)
	local args = getArgs(frame)
	local options = {
		['SemanticPropertyName'] = 'Тип класса дзюцу',
		['Link'] = 'none'
	}
	local classes = arrayTable ( args['тип класса дзюцу'], ',%s*', options, frame )
	return table.concat( classes, ', ' )
end

function Infobox.jutsuRange(frame)
	local args = getArgs(frame)
	local ranges = {
		['Короткий'] = 'Короткий диапазон (0-5м)',
		['Средний'] = 'Средний диапазон (5-10м)',
		['Длинный'] = 'Длинный диапазон (10м+)',
		['Короткий, Средний, Длинный'] = 'Все диапазоны',
		['Короткий, Средний'] = 'Короткий в Средний диапазон (0-10м)',
		['Средний, Длинный'] = 'Средний в Длинный диапазон (5м+)',
		['Короткий, Длинный'] = 'Короткий или Длинный диапазон (0-5м или 10м+)'
	}
	arrayTable ( args['диапазон дзюцу'], ',%s*', { ['SemanticPropertyName'] = 'Диапазон дзюцу' } )
	return ranges[args['диапазон дзюцу']] or args['диапазон дзюцу']..'-диапазон'
end

function Infobox.jutsuParent(frame)
	local args = getArgs(frame)
	local options = {
		['SemanticPropertyName'] = 'Родительское дзюцу',
		['Link'] = 'Unnamed',
		['UnnamedFormat'] = true
	}
	local parents = arrayTable ( args['родительское дзюцу'], ',%s*', options )
	return L.makeList( 'unbulleted', parents )
end

function Infobox.jutsuMedia(frame)
	local args = getArgs(frame)
	local out = {}
	local mtypes = {
		['Фильм'] = 'Дзюцу/НеКанонический',
		['Игра'] = 'Дзюцу/НеКанонический',
		['Игра, Фильм'] = 'Дзюцу/НеКанонический'
	}
	local mq = mw.smw.ask {
		(HF.Link('Concept:%s')):format( mtypes[args['дзюцу медиа']] or 'Дзюцу/Канонический' ),
		(HF.Link('Родительское дзюцу::%s')):format( mw.title.getCurrentTitle().prefixedText ),
		'?Появляется в',
		'?Обслуживание',
		('userparam=%s'):format(args['дзюцу медиа']),
		'mainlabel=main',
		'limit=200'
	}
	local hasNCderivatives = mw.smw.ask {
		(HF.Link('Concept:%s')):format( 'Дзюцу/НеКанонический' ),
		(HF.Link('Родительское дзюцу::%s')):format( mw.title.getCurrentTitle().prefixedText )
	}
	if type(mq) == 'table' then
		for _, parent in ipairs(mq) do
			local mainlink =
				(
				    parent['Обслуживание'] == 'Название'
				    or (
				        type(parent['Обслуживание']) == 'table'
				        and table.concat(parent['Обслуживание']):match('Название')
		            )
			    )
				and (''%s''):format(
					HF.Link(
						parent['main']:match(stripLinkToTarget),
						parent['main']:match('%[%[:?([^|]*)|?'):match(stripPageTitleToBase)
					)
				)
				or HF.Link(
					parent['main']:match(stripLinkToTarget),
					parent['main']:match('%[%[:?([^|]*)|?'):match(stripPageTitleToBase)
				)
			local dq = mw.smw.ask {
				(HF.Link('Concept:%s')):format( mtypes[args['дзюцу медиа']] or 'Дзюцу/Канонический' ),
				(HF.Link('Родительское дзюцу::%s')):format( parent['main']:match(stripLinkToTarget) ),
				('userparam=%s'):format( args['дзюцу медиа'] or 'Аниме, Манга' ),
				'mainlabel=main',
				'named args=yes',
				'limit=20'
			}
			local derivatives = {}
			if type( dq ) == 'table' then
				for _, derived in ipairs(dq) do
					local dlink = (
					    derived['Обслуживание'] == 'Название'
					    or type(derived['Обслуживание']) == 'table'
				        and table.concat(derived['Обслуживание']):match('Название')
					    )
					and ("''%s''"):format(
						HF.Link(
							derived['main']:match(stripLinkToTarget),
							derived['main']:match('%[%[:?([^|]*)|?'):match(stripPageTitleToBase)
						)
					)
					or HF.Link(
						derived['main']:match(stripLinkToTarget),
						derived['main']:match('%[%[:?([^|]*)|?'):match(stripPageTitleToBase)
					)
					table.insert( derivatives, dlink )
				end
				table.insert( out, mainlink .. L.makeList( 'bulleted', derivatives ) )
			else
				table.insert( out, mainlink )
			end
		end
		return L.makeList( 'bulleted', out )
	elseif type(hasNCderivatives) == 'table' then
	    local t = 
	        mw.title.new( 'SearchByProperty', 'Special' ).prefixedText
	    local q = mw.uri.buildQueryString{ 
	        ['property'] = 'Родительское дзюцу',
	        ['value'] = mw.uri.encode(
	            mw.title.getCurrentTitle().prefixedText,
	            'WIKI'
	            )
        }
        local searchlink = HF.ExternalLink(
            tostring(mw.uri.fullUrl(t,q)),
            'Все производные дзюцу'
        )
	    return ('<center class="smwsearch">%s</center>'):format( searchlink )
	end
end

function Infobox.jutsuRelated(frame)
	local args = getArgs(frame)
	return arraymap( args['родственные дзюцу'], ',%s*', HF.Link('%s'), ', ' )
end

function Infobox.jutsuUsers(frame)
	local args = getArgs(frame)
	local out = {}
	-- Valid media types
	local mtypes = {
		['нет'] = true, ['аниме'] = true, ['манга'] = true,
		['роман'] = true, ['игра'] = true, ['фильм'] = true, ['фильм канон'] = true
	}
  -- Divides users into actionable items (even if there's only one)
  local users = args['пользователи'] and mw.text.split( args['пользователи'], ',%s*' )
  -- Checks if any user entries exist, and if they don't, return nil
  if type(users) ~= 'table' then return nil end
  -- For each user
  for _, user in ipairs( users ) do
    -- checks if the entry is real or empty
    if type(user) == 'string' and #user < 1 then break end
    -- separates user name from media
    local prime, media = user:match('([^%~]*)%~?([^%~]*)')
    local link = HF.Link(
      base( prime ):match(stripLinkToTarget),
      base( prime ):match(stripLinkToTarget):match(stripPageTitleToBase)
    )
    link = nameCheck( prime ) == true
      and ("''%s''"):format( link )
      or link

    --- AdditionalInfo
    -- Puppetry handling
    local puppetry = user:match('~~марионетка~(.*)$')
    if puppetry then
      puppetry = (' (Использование марионеток %s)')
        :format(mw.text.listToText(mw.text.split(puppetry, '~')))
    end
    -- "with" handling
    local with = user:match('~~с~([^%~]*)')
      and (' (с %s)'):format(user:match('~~с~([^%~]*)'))
    local AdditionalInfo = puppetry or with or ''

    --- Media
    local Media = ''
    if media
      and mtypes[media:lower()]
      and media:lower() ~= 'фильм канон'
    then
      Media = ('<sup> (%s)</sup>')
        :format( language:ucfirst( media ) )
    elseif media
      and media:lower() == 'фильм канон'
      then
        Media = '<sup> (Фильм)</sup>'
    end

    --- Summons
    local cq = mw.smw.ask {
      (HF.Link('Контракт::%s')):format( prime:match(stripLinkToTarget) ),
      'mainlabel=main'
    }
    local sl = {}
    if type(cq) == 'table' then
      for _, v in ipairs( cq ) do
        table.insert( sl, v['main'] )
      end
    end
    local Summons = ((#sl > 0)
        and ( pageTitle == 'Техника Призыва' or pageTitle == 'Destruction Bug Host Technique' ))
      and ( ' (%s)' ):format( table.concat( sl, ", " ) )
      or ''

    -- SMW set
    local setmtype = ( media and mtypes[ media:lower() ] )
      and language:ucfirst( media:lower() )
      or 'null'
    mw.smw.set {
      ['Пользователи техники'] = prime .. ';' .. setmtype
    }

    table.insert( out, link .. AdditionalInfo .. Summons .. Media )
  end
  return L.makeList( 'bulleted', out )
end
---------------------------------------------------------
-- Exported functions (used in this and other Modules) --
---------------------------------------------------------
-- None.
-------------------------------------------------
-- Output (send it back to whatever called it) --
-------------------------------------------------
return Infobox