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