WARFRAME Wiki
WARFRAME Wiki
m (documentation)
mNo edit summary
 
(158 intermediate revisions by 4 users not shown)
Line 1: Line 1:
--- '''Tooltips''' builds tooltip links and icons.<br />
+
--- '''Tooltips''' builds tooltip links and icons. It can be used as a static or
  +
-- instantiated class.<br />
 
--
 
--
  +
-- Stylesheet for tooltips and tooltip text can be found on [[MediaWiki:Tooltips.css]].
-- @module tooltips
 
  +
-- The JS script that enables tooltips is sourced from https://dev.fandom.com/wiki/Tooltips
-- @author [[User:Gigamicro|Gigamicro]]
 
  +
--
-- @image TooltipPic.PNG
 
  +
-- @module tooltips
-- @require [[Module:Tooltips/data]]
 
  +
-- @author [[User:Gigamicro|Gigamicro]]
-- @require [[Module:Tooltips/tip]]
 
  +
-- @image TooltipPic.PNG
-- @require [[Module:Shared]]
 
  +
-- @require [[w:c:dev:MediaWiki:Tooltips.js|MediaWiki:Tooltips.js]]
-- @release stable
 
  +
-- @require [[Module:Tooltips/icon]]
-- <nowiki>
 
  +
-- @require [[Module:Tooltips/tip]]
  +
-- @release stable
  +
-- <nowiki>
  +
  +
local p = {}
  +
local dataPrep;
  +
dataPrep = setmetatable({}, { __index = function(self, index)
  +
dataPrep = require[[Module:Tooltips/icon]]
  +
return dataPrep[index]
  +
end })
  +
  +
-- TODO: Update index table to be just a map instead of a mixed map and array.
  +
-- Instead of index[3] (don't know what this contains at first glance), store the link in index['link'] or index['Link']
  +
  +
--- Returns formatted tooltip link text.
  +
-- @function p._getText
  +
-- @param {string} name Name of object entry to make a tooltip of
  +
-- @param {table} index Tooltip index table
  +
-- @param {table} rep Replacement args
  +
-- @return {string} Wikitext link
  +
function p._getText(name, index, rep)
  +
return ('[[%s|<span style="border-bottom:2px dotted; color:%s;">%s</span>]]')
  +
:format(
  +
index[3] or name,
  +
rep.color ~= '' and rep.color or index.color or '',
  +
-- index.name is the Name key of object entries
  +
-- name is the index key to object entry (typically the same as Name key but not always)
  +
(rep.r ~= '' and rep.r or index.name or name or ' '):gsub('%s+', ' ')
  +
)
  +
end
  +
  +
--- Returns tooltip icon.
  +
-- @function p._getIcon
  +
-- @param {string} _ Ignore; unused variable
  +
-- @param {table} index Tooltip index table
  +
-- @return {string} Image wikilink or nil
  +
function p._getIcon(_, index)
  +
return index.icon ~= '' and index.icon or nil
  +
end
  +
  +
--- Creates a tooltip index table for passing parameters to the tooltip builder.
  +
-- @function makeData
  +
-- @param {string} source Name of module containing object entry
  +
-- @param {table} frame Frame object
  +
-- @return {table} Tooltip index table or nil
  +
local function makeData(source, frame)
  +
return (source and frame and type(frame) == 'table' and type(frame.args) == 'table' and frame.args.i) and {
  +
source,
  +
frame.args.i,
  +
frame.args.l,
  +
name = frame.args.n,
  +
icon = ('[[File:%s|x19px|link=%s|class=icon]]'):format(frame.args.icon, frame.args.l or ''),
  +
color = frame.args.color,
  +
overridden = true,
  +
} or nil
  +
end
   
  +
--- Function preprocessor.
return {
 
  +
-- @function pp
--- Get the tooltip icon. (frame.args.i, frame.args.l are index, link; frame.args.r is display of link)
 
-- @function p.getIcon
+
-- @param {function} func
  +
-- @return {function} tooltip span applied to return value of func
-- @param {string} name
 
  +
local function pp(func)
-- @param {string, table} source Name of module containing object entry (can pass table instead)
 
  +
return function(...)
-- @param {boolean} skipData Skip loading data? (will also remove icon) (nil,'' -> load)
 
  +
--standardise input to frame object equivalent
-- @param {string} frame.args.i index for data replacement (will also prevent data from loading)
 
  +
--(nt,b,c) ->(nt,b,c)
-- @param {string} frame.args.l link for data replacement
 
  +
--({args={a,b,c}}) -> (a,b,c)
-- @param {boolean} frame.args.noIcon Remove icon? (nil,'' -> keep)
 
  +
--({a,b,c}) -> (a,b,c)
-- @param {string} frame.args.r Displayed link text (nil, '' -> <name>)
 
  +
--(a,b,c) -> (a,b,c)
-- @return {string} Tooltip </span>, icon, & link in wikitext
 
getIcon = function(frame, b, c, d)
+
local frame = nil
  +
or type(...)~='table' and {args={...}}
local name, source, skipData, nextvar = (function(t)return t[1],t[2],t[3],t[4] end)(frame.args or {frame, b, c, d})
 
  +
or (...).args and (...)
assert(name and name~='', 'No name provided')
 
  +
or not select(2,...) and {args=(...)}
pcall(function()source=(source+0)end) -- number?
 
  +
or true and true and {args={...}}
name = mw.text.decode(name) -- Replacing HTML codes in text with their ASCII character equivalent
 
  +
local name, source, index = (function(t) return t[1], t[2], t[3] end)(frame.args)--unpack doesn't work on the frame object
-- [==[
 
  +
if type(name) == 'table' then
local index = mw.loadData('Module:Tooltips/data/'..source)[name] or error('p.getIcon(frame, b, c, d): icon not found in [[Module:Tooltips/data/'..source..']] for "'..name..'" (Are you using the wrong tooltip template or made a typo? If not, you likely have to edit [[Module:'..source..'/data]]. If content in question is outdated, please replace tooltip template call with a normal wikitext link.)')
 
  +
--({}) -> ({}.name/2,{}.1,{})
--local index = {require('Module:Tooltips/icon')[source](name) or mw.log(name..' unfound')}
 
  +
index = name
--[=[]==]
 
  +
source = index[1]
local index = -- get data table entry
 
  +
name = index.name or index[2]
not (skipData or type(b) == 'table' or frame.args and frame.args.i) -- load the data in the first place?
 
  +
end
and mw.loadData('Module:Tooltips/data')[name]
 
  +
if type(index) ~= 'table' then
or {}--]=]
 
  +
local error = '<strong class="error scribunto-error" title="%s">%s</strong>[[Category:Pages with script errors]]'
index = nil--looking for {source,index,link}
 
  +
if source == '' or not source then
or type(b)=='table' and b -- passed in (unused so far)
 
  +
return error:format(debug.traceback('pp(func): source is '..type(source)..'. ', 2):gsub('[<>]', ''),
or index[source] -- find in data by number
 
  +
'Where is '..(name and '"[['..name..']]"' or '<nil>')..'?')
or (function(index,source)
 
  +
elseif name == '' or not name then
for i,v in ipairs(index) do
 
  +
return error:format(debug.traceback('pp(func): name is '..type(name)..'. ', 2):gsub('[<>]', ''),
if v[1] == source then
 
  +
'What did you want in '..(source and '[[Module:'..source..'/data]]' or '<nil>')..'?')
return v
 
  +
elseif not dataPrep[source] then
end
 
  +
return error:format(debug.traceback('pp(func): source is '..type(source)..'. ', 2):gsub('[<>]', ''),
end
 
  +
'Invalid source "'..source..'"')
end)(index,source) -- find in data by name
 
  +
end
or index[1] -- default from data
 
  +
--get the data from the source module + formatted
or { source, frame.args and frame.args.i, frame.args and frame.args.l } -- cobbled together from input
 
  +
--(a,b,nt) -> (dca,b,fdat)
  +
name = mw.text.decode(name)
  +
index = makeData(source, frame) or dataPrep[source](name)
  +
  +
if not index then
  +
return error:format(debug.traceback('pp(func)', 1):gsub('[<>]', ''),
  +
(name and '"[['..name..']]"' or '<nil>')..' wasn\'t found in [[Module:'..source..'/data]]')
  +
end
  +
elseif not index[2] then
  +
--index is a data entry, get it formatted properly
  +
--(a,b,dat) -> (a,b,fdat)
  +
if not dataPrep[source] then
  +
error('M:Tooltips.pp()(): Missing tooltip gen script for source "'..(source or '<nil>')..'"')
  +
end
  +
index = dataPrep[source](index,name)
  +
end
  +
source = index[1]
  +
-- Damage tooltips are unique in that they both need invert and hue-rotate filters for colored damage icons and text
  +
return ('<span class="tooltip tooltip-full %s" data-param="%s" data-param2="%s">%s</span>')
  +
:format(source == 'DamageTypes' and 'damage-type-tooltip' or '',
  +
index[2] or mw.log('pp(func): no index[2]:', name, index[1]) or name or index[3], source or error('no sauce :('..mw.dumpObject(index)) or 'nil',
  +
func(name, index, frame.args)
  +
)
  +
end
  +
end
   
  +
--- Get the tooltip text and icon.
local icon = (frame.args and frame.args["noicon"] or '') == '' and (type(index.icon)=='table' and index.icon[1] or index.icon) or ''
 
  +
-- @function p.full
return string.format('<span class="tooltip" data-param="%s" data-param2="%s">%s%s[[%s|<span style="border-bottom:1px dotted;%s">%s</span>]]</span>',
 
  +
-- @param {string} name Name of object entry to make a tooltip of (can also be used as index)
index[2] or name, index[1] or '',--param1 (item name), param2 (item type/source)
 
  +
-- @param {string} source Name of module containing object entry (nil to check if a manual index is working)
icon, icon == '' and '' or '&nbsp;',-- icon, spacing
 
  +
-- @param {table} index Index entry from m:tt/icon, or data point from (source) if source is set
index[3] ~= name and index[3] or name,-- link destination
 
  +
-- @param {string} frame.args.r Replacement for displayed link text (nil, '' -> <name>)
index.color and (' color:%s;'):format(index.color) or '',-- coloring
 
  +
-- @param {string} frame.args.color Color replacement for displayed link text (e.g. '#ffffff')
(frame.args and frame.args.r ~= '' and frame.args.r or name):gsub(' ','&nbsp;') -- displayed name
 
  +
-- @param {string} frame.args.i Index for data replacement (will also prevent data from loading)
)
 
  +
-- @param {string} frame.args.l Link for data replacement
end,
 
  +
-- @param {string} frame.args.n Name for data replacement
  +
-- @param {string} frame.args.icon Icon image name for data replacement (e.g. 'Ash.png')
  +
-- @example `p.full('Serration', 'Mods')` for mod tooltip for Serration
  +
-- @example `p.full( { 'Serration', 'Mods', r = 'Replacement Display Link Name' } ) for mod tooltip for serration with replacement link text
  +
-- @return {string} Tooltip <span> tags, icon, & link in wikitext
  +
p.full = pp(function(...)
  +
local icon = p._getIcon(...)
  +
return icon
  +
and icon..' '..p._getText(...) --&nbsp;
  +
or p._getText(...)
  +
end)
  +
p.icontext = p.full
   
--- Get the tooltip icon with no text.
+
--- Get the tooltip text with no icon.
-- @function p.getIcon
+
-- @function p.text
-- @param {string} name
+
-- @param {string} name Name of object entry to make a tooltip of
  +
-- @param {string} ... see p.full
-- @param {string} source Name of module containing object entry (can pass table instead)
 
  +
-- @return {string} Tooltip text in wikitext
-- @param {boolean} doTip Whether to add tooltip span (nil, '' -> tooltip)
 
  +
p.text = pp(p._getText)
-- @return {string} Tooltip </span> (if enabled) & icon in wikitext
 
getImage = function(frame, b, c)
 
local name, source, doTip = (function(t)return t[1],t[2],t[3] end)(frame.args or {frame, b, c})
 
assert(name and name~='', 'No name provided')
 
pcall(function()source=(source+0)end) -- number?
 
   
  +
--- Get the tooltip icon with no text.
local index = -- get data table entry
 
  +
-- @function p.icon
not (type(b) == 'table' or frame.args and frame.args.i) -- load the data in the first place?
 
  +
-- @param {string} name Name of object entry to make a tooltip of
and mw.loadData('Module:Tooltips/data')[name]
 
  +
-- @param {string} ... see p.full
or {}
 
  +
-- @return {string} Tooltip icon in wikitext
index = nil--looking for {source,index,link}
 
  +
p.icon = pp(p._getIcon)
or type(b)=='table' and b -- passed in (unused so far)
 
  +
p.image = p.icon
or index[source] -- find in data by number
 
or (function(index,source)
 
for i,v in ipairs(index) do
 
if v[1] == source then
 
return v
 
end
 
end
 
end)(index,source) -- find in data by name
 
or index[1] -- default from data
 
or { source } -- cobbled together from input
 
   
  +
--- Get the data index.
return doTip and doTip~='' and string.format('<span class="tooltip" data-param="%s" data-param2="%s">%s</span>',
 
  +
-- @function p._getIndex
index[2] or name, index[1] or '',--param1 (item name), param2 (item type/source)
 
  +
-- @param {string} name Item name
(type(index.icon)=='table' and index.icon[1] or index.icon) or ''-- icon
 
  +
-- @param {string} source Name of source module containing object entry
) or (type(index.icon)=='table' and index.icon[1] or index.icon) or ''
 
  +
-- @return {table} index table
end,
 
  +
p._getIndex = function(name, source)
  +
if name == '' or not name or source == '' or not source then
  +
return
  +
end
  +
-- name = mw.text.decode(name)
  +
  +
local success, index = pcall(dataPrep[source], name)
  +
return success and index or nil
  +
end
   
--- Get the tooltip. (uses frame:preprocess if no tooltip function is found)
+
--- Get the tooltip.
-- @function p.getTip
+
-- @function p.getTip
-- @param {string} name
+
-- @param {string} name Name of object entry to make a tooltip of
  +
-- @param {string} source Name of source module containing object entry
-- @param {string} b source
 
  +
-- @param {string} slot Name of submodule
-- @return {string} Tooltip
 
  +
-- @return {string} Tooltip
getTip = function(frame,b)
 
  +
p.getTip = function(frame, ...)
local name, source = (function(t)return t[1],t[2] end)(frame.args or {frame, b})
 
  +
local name, source, slot = (function(t) return t[1], t[2], t[3] end)(frame.args or {frame, ...})
assert(name, 'No name provided')
 
  +
assert(name and name ~= '', 'p.getTip(): No name provided')
  +
return (require('Module:Tooltips/tip')[source] or
  +
error('M:Tooltips.getTip(): Missing tooltip gen script for source "'..(source or '<nil>')..'"'))(name, slot)
  +
end
   
  +
--- Returns a function that serves as a interface to tooltip builders.
return (require('Module:Tooltips/tip')[source] or function(name)
 
  +
-- Another way of thinking about this function is to treat the entire module as a class.
--default tooltip
 
  +
-- When you require(), the module, you are 'instantiating' a new instance of this class
local s = frame:preprocess('{'..'{#lst:'..name..'|intro}}')-- or frame:preprocess('{'..'{#lsth:'..frame.args[1]..'}}')
 
  +
-- and pass in the name of the database to pull data from. Then you call a
return s~='' and
 
  +
-- tooltip function and pass in a database entry name for the desired tooltip.
('<div style="display:inline-block;">\n{| class="Tooltip Main"\n|-\n|style="padding:0px;"|<div style="position:relative;">\n'
 
  +
-- @function p._source
..'{| class="Sub"\n|-\n| class="Data" style="width:100px;white-space:inherit;padding:2px;line-height:normal;" |%s'
 
  +
-- @param {string} source Name of source module containing object entry
..'\n|}\n</div>\n|}\n</div>'):format(s)
 
  +
-- @return {function} Wrapper function
or ''
 
  +
p._source = function(source)
end)(name)
 
  +
return function(func)
end,
 
  +
return function(name, ...)
  +
return p[func](name, source, ...)
  +
-- E.g. require('Module:Tooltips')('Warframes')('full')('Ivara') === require('Module:Tooltips').full('Ivara', 'Warframes')
  +
end
  +
end
  +
end
   
  +
-- For calling export module directly: require('Module:Tooltips')()
--- Read out the data table.
 
  +
setmetatable(p, { __call = function(self, ...) return p._source(...) end })
-- @require [[Module:Shared]]
 
-- @function p.__readout
 
-- @param {table} frame input
 
-- @return {string} the data table, sanitised for Lua (not for wikitext)
 
__readout = function(frame)
 
-- TODO: Move Shared.upk() to M:Lua and use require('Module:Lua').upk() instead
 
local data = mw.loadData('Module:Tooltips/data')
 
return({require('Module:Shared').upk(
 
(function(data,l) for i,v in ipairs(l) do data=data[v] end return data end)(data,frame.args),
 
(frame.args.depth or 1) + 0
 
):gsub('\n','\n\n')})[1]
 
end,
 
   
  +
return p
--- Loops over every entry in the table, concatenating its key between the arguments.
 
-- @require [[Module:Shared]]
 
-- @function p.__all
 
-- @param {table} frame input (2 params), also uses frame:preprocess
 
-- @return {string} The preprocessed result
 
__all = function(frame)
 
-- TODO: Move Shared.skpairs() to M:Table and use require('Module:Table').skpairs() instead
 
local t,a,b={},frame.args[1],frame.args[2]--unpack(frame.args)
 
for k in require('Module:Shared').skpairs(mw.loadData('Module:Tooltips/data')) do
 
table.insert(t,k)
 
end
 
return frame:preprocess(a..table.concat(t,b..a)..b)
 
end,
 
}
 

Latest revision as of 02:53, 29 November 2023


Tooltips builds tooltip links and icons. It can be used as a static or instantiated class.

Stylesheet for tooltips and tooltip text can be found on MediaWiki:Tooltips.css. The JS script that enables tooltips is sourced from https://dev.fandom.com/wiki/Tooltips

On this Wiki, Tooltips is used in:

Usage

Direct Invocation

{{#invoke:Tooltip|function|input1|input2|...}}

Examples

Note that these only work on pages with the wikitext content model such as here. In addition, tooltips will not work if a page is added via <tabview> tags.

How it works

  1. When you call a tooltip builder function (e.g. Tooltips.full(itemName, moduleName, ...)), it uses Module:Tooltips/icon to get the item image and page link from a module's /data subpage and builds the basic HTML tooltip tags to put on wiki articles (<span class="tooltip tooltip-text" data-param="..." data-param2="..."></span>).
  2. The JS script https://dev.fandom.com/wiki/Tooltips (imported in MediaWiki:ImportJS, configured in MediaWiki:Tooltips.js) does the fetching of data based on data-param (containing item name) and data-param2 (containing name of module which has a /data database containing the item's data) attributes in tooltip tags to build the actual tooltip defined by wikitext in Module:Tooltips/tip and css in MediaWiki:Tooltips.css.
    • For example, <span class="tooltip tooltip-full tooltips-init-complete" data-param="Artemis Bow" data-param2="Weapons">...</span> will display a Template:Weapon tooltip of Artemis Bow (Weapon) while <span class="tooltip tooltip-full tooltips-init-complete" data-param="Artemis Bow" data-param2="Ability">...</span> will display a Template:A ("A" is a shorthand for abilities) tooltip of Artemis Bow.
    • The processed wikitext for tooltips will be located in a div container on the bottom of articles with an id of tooltip-storage.
    • Data fetching uses MediaWiki's Action API.
    • Note that tooltips do not work properly on module pages because they do not have the same HTML structure as article pages.

Directory

  • Module:Tooltips - main module for invoking tooltip function on articles; tooltip builder
    • Module:Tooltips/tip - submodule for defining styling of tooltip box that appears on hover over
    • Module:Tooltips/icon - submodule for defining where to fetch data for the contents of tooltip box as well as the styling of the icon next to tooltip element

Documentation

Package items

tooltips._getText(name, index, rep) (function)
Returns formatted tooltip link text.
Parameters:
  • name Name of object entry to make a tooltip of (string)
  • index Tooltip index table (table)
  • rep Replacement args (table)
Returns: Wikitext link (string)
tooltips._getIcon(_, index) (function)
Returns tooltip icon.
Parameters:
  • _ Ignore; unused variable (string)
  • index Tooltip index table (table)
Returns: Image wikilink or nil (string)
tooltips.full(name, source, index) (function)
Get the tooltip text and icon.
Parameters:
  • name Name of object entry to make a tooltip of (can also be used as index) (string)
  • source Name of module containing object entry (nil to check if a manual index is working) (string)
  • index Index entry from m:tt/icon, or data point from (source) if source is set (table)
      • frame.args.r Replacement for displayed link text (nil, -> <name>) (string)
      • frame.args.color Color replacement for displayed link text (e.g. '#ffffff') (string)
      • frame.args.i Index for data replacement (will also prevent data from loading) (string)
      • frame.args.l Link for data replacement (string)
      • frame.args.n Name for data replacement (string)
      • frame.args.icon Icon image name for data replacement (e.g. 'Ash.png') (string)
Returns: Tooltip tags, icon, & link in wikitext (string)
tooltips.text(name, ...) (function)
Get the tooltip text with no icon.
Parameters:
  • name Name of object entry to make a tooltip of (string)
  • ... see p.full (string)
Returns: Tooltip text in wikitext (string)
tooltips.icon(name, ...) (function)
Get the tooltip icon with no text.
Parameters:
  • name Name of object entry to make a tooltip of (string)
  • ... see p.full (string)
Returns: Tooltip icon in wikitext (string)
tooltips._getIndex(name, source) (function)
Get the data index.
Parameters:
  • name Item name (string)
  • source Name of source module containing object entry (string)
Returns: index table (table)
tooltips.getTip(name, source, slot) (function)
Get the tooltip.
Parameters:
  • name Name of object entry to make a tooltip of (string)
  • source Name of source module containing object entry (string)
  • slot Name of submodule (string)
Returns: Tooltip (string)
tooltips._source(source) (function)
Returns a function that serves as a interface to tooltip builders. Another way of thinking about this function is to treat the entire module as a class. When you require(), the module, you are 'instantiating' a new instance of this class and pass in the name of the database to pull data from. Then you call a tooltip function and pass in a database entry name for the desired tooltip.
Parameter: source Name of source module containing object entry (string)
Returns: Wrapper function (function)

Created with Docbunto

See Also

Code


---	'''Tooltips''' builds tooltip links and icons. It can be used as a static or 
--	instantiated class.<br />
--	
--	Stylesheet for tooltips and tooltip text can be found on [[MediaWiki:Tooltips.css]].
--	The JS script that enables tooltips is sourced from https://dev.fandom.com/wiki/Tooltips
--	
--	@module		tooltips
--	@author		[[User:Gigamicro|Gigamicro]]
--	@image		TooltipPic.PNG
--	@require	[[w:c:dev:MediaWiki:Tooltips.js|MediaWiki:Tooltips.js]]
--	@require	[[Module:Tooltips/icon]]
--	@require	[[Module:Tooltips/tip]]
--	@release	stable
--	<nowiki>

local p = {}
local dataPrep;
dataPrep = setmetatable({}, { __index = function(self, index)
	dataPrep = require[[Module:Tooltips/icon]]
	return dataPrep[index]
end })

-- TODO: Update index table to be just a map instead of a mixed map and array.
-- Instead of index[3] (don't know what this contains at first glance), store the link in index['link'] or index['Link']

---	Returns formatted tooltip link text.
--	@function		p._getText
--	@param			{string} name Name of object entry to make a tooltip of
--	@param			{table} index Tooltip index table
--	@param			{table} rep Replacement args
--	@return			{string} Wikitext link
function p._getText(name, index, rep)
	return ('[[%s|<span style="border-bottom:2px dotted; color:%s;">%s</span>]]')
		:format(
			index[3] or name,
			rep.color ~= '' and rep.color or index.color or '',
			-- index.name is the Name key of object entries
			-- name is the index key to object entry (typically the same as Name key but not always)
			(rep.r ~= '' and rep.r or index.name or name or ' '):gsub('%s+', ' ')
		)
end

---	Returns tooltip icon.
--	@function		p._getIcon
--	@param			{string} _ Ignore; unused variable
--	@param			{table} index Tooltip index table
--	@return			{string} Image wikilink or nil
function p._getIcon(_, index)
	return index.icon ~= '' and index.icon or nil
end

---	Creates a tooltip index table for passing parameters to the tooltip builder.
--	@function		makeData
--	@param			{string} source Name of module containing object entry
--	@param			{table} frame Frame object
--	@return			{table} Tooltip index table or nil
local function makeData(source, frame)
	return (source and frame and type(frame) == 'table' and type(frame.args) == 'table' and frame.args.i) and {
		source,
		frame.args.i,
		frame.args.l,
		name = frame.args.n,
		icon = ('[[File:%s|x19px|link=%s|class=icon]]'):format(frame.args.icon, frame.args.l or ''),
		color = frame.args.color,
		overridden = true,
	} or nil
end

---	Function preprocessor.
--	@function		pp
--	@param			{function} func
--	@return			{function} tooltip span applied to return value of func
local function pp(func)
	return function(...)
		--standardise input to frame object equivalent
		--(nt,b,c)         ->(nt,b,c)
		--({args={a,b,c}}) -> (a,b,c)
		--({a,b,c})        -> (a,b,c)
		--(a,b,c)          -> (a,b,c)
		local frame = nil
			or type(...)~='table' and {args={...}}
			or (...).args         and       (...)
			or not select(2,...)  and {args=(...)}
			or true and true      and {args={...}}
		local name, source, index = (function(t) return t[1], t[2], t[3] end)(frame.args)--unpack doesn't work on the frame object
		if type(name) == 'table' then
			--({}) -> ({}.name/2,{}.1,{})
			index = name
			source = index[1]
			name = index.name or index[2]
		end
		if type(index) ~= 'table' then
			local error = '<strong class="error scribunto-error" title="%s">%s</strong>[[Category:Pages with script errors]]'
			if source == '' or not source then
				return error:format(debug.traceback('pp(func): source is '..type(source)..'. ', 2):gsub('[<>]', ''),
					'Where is '..(name and '"[['..name..']]"' or '<nil>')..'?')
			elseif name == '' or not name then
				return error:format(debug.traceback('pp(func): name is '..type(name)..'. ', 2):gsub('[<>]', ''),
					'What did you want in '..(source and '[[Module:'..source..'/data]]' or '<nil>')..'?')
			elseif not dataPrep[source] then
				return error:format(debug.traceback('pp(func): source is '..type(source)..'. ', 2):gsub('[<>]', ''),
					'Invalid source "'..source..'"')
			end
			--get the data from the source module + formatted
			--(a,b,nt) -> (dca,b,fdat)
			name = mw.text.decode(name)
			index = makeData(source, frame) or dataPrep[source](name)
			
			if not index then
				return error:format(debug.traceback('pp(func)', 1):gsub('[<>]', ''),
					(name and '"[['..name..']]"' or '<nil>')..' wasn\'t found in [[Module:'..source..'/data]]')
			end
		elseif not index[2] then
			--index is a data entry, get it formatted properly
			--(a,b,dat) -> (a,b,fdat)
			if not dataPrep[source] then
				error('M:Tooltips.pp()(): Missing tooltip gen script for source "'..(source or '<nil>')..'"')
			end
			index = dataPrep[source](index,name)
		end
		source = index[1]
		-- Damage tooltips are unique in that they both need invert and hue-rotate filters for colored damage icons and text
		return ('<span class="tooltip tooltip-full %s" data-param="%s" data-param2="%s">%s</span>')
			:format(source == 'DamageTypes' and 'damage-type-tooltip' or '', 
				index[2] or mw.log('pp(func): no index[2]:', name, index[1]) or name or index[3], source or error('no sauce :('..mw.dumpObject(index)) or 'nil', 
				func(name, index, frame.args)
			)
	end
end

---	Get the tooltip text and icon.
--	@function		p.full
--	@param			{string} name Name of object entry to make a tooltip of (can also be used as index)
--	@param			{string} source Name of module containing object entry (nil to check if a manual index is working)
--	@param			{table} index Index entry from m:tt/icon, or data point from (source) if source is set
--	@param			{string} frame.args.r Replacement for displayed link text (nil, '' -> <name>)
--	@param			{string} frame.args.color Color replacement for displayed link text (e.g. '#ffffff')
--	@param			{string} frame.args.i Index for data replacement (will also prevent data from loading)
--	@param			{string} frame.args.l Link for data replacement
--	@param			{string} frame.args.n Name for data replacement
--	@param			{string} frame.args.icon Icon image name for data replacement (e.g. 'Ash.png')
--	@example		`p.full('Serration', 'Mods')` for mod tooltip for Serration
--	@example		`p.full( { 'Serration', 'Mods', r = 'Replacement Display Link Name' } ) for mod tooltip for serration with replacement link text
--	@return			{string} Tooltip <span> tags, icon, & link in wikitext
p.full = pp(function(...)
	local icon = p._getIcon(...)
	return icon 
		and icon..' '..p._getText(...) --&nbsp;
		or p._getText(...)
end)
p.icontext = p.full

---	Get the tooltip text with no icon.
--	@function		p.text
--	@param			{string} name Name of object entry to make a tooltip of
--	@param			{string} ... see p.full
--	@return			{string} Tooltip text in wikitext
p.text = pp(p._getText)

---	Get the tooltip icon with no text.
--	@function		p.icon
--	@param			{string} name Name of object entry to make a tooltip of
--	@param			{string} ... see p.full
--	@return			{string} Tooltip icon in wikitext
p.icon = pp(p._getIcon)
p.image = p.icon

---	Get the data index.
--	@function		p._getIndex
--	@param			{string} name Item name
--	@param			{string} source Name of source module containing object entry
--	@return			{table} index table
p._getIndex = function(name, source)
	if name == '' or not name or source == '' or not source then
		return
	end
	-- name = mw.text.decode(name)
	
	local success, index = pcall(dataPrep[source], name)
	return success and index or nil
end

---	Get the tooltip.
--	@function		p.getTip
--	@param			{string} name Name of object entry to make a tooltip of
--	@param			{string} source Name of source module containing object entry
--	@param			{string} slot Name of submodule
--	@return			{string} Tooltip
p.getTip = function(frame, ...)
	local name, source, slot = (function(t) return t[1], t[2], t[3] end)(frame.args or {frame, ...})
	assert(name and name ~= '', 'p.getTip(): No name provided')
	return (require('Module:Tooltips/tip')[source] or 
		error('M:Tooltips.getTip(): Missing tooltip gen script for source "'..(source or '<nil>')..'"'))(name, slot)
end

---	Returns a function that serves as a interface to tooltip builders.
--	Another way of thinking about this function is to treat the entire module as a class.
--	When you require(), the module, you are 'instantiating' a new instance of this class
--	and pass in the name of the database to pull data from. Then you call a 
--	tooltip function and pass in a database entry name for the desired tooltip.
--	@function		p._source
--	@param			{string} source Name of source module containing object entry
--	@return			{function} Wrapper function
p._source = function(source)
	return function(func)
		return function(name, ...)
			return p[func](name, source, ...)
			-- E.g. require('Module:Tooltips')('Warframes')('full')('Ivara') === require('Module:Tooltips').full('Ivara', 'Warframes')
		end
	end
end

-- For calling export module directly: require('Module:Tooltips')()
setmetatable(p, { __call = function(self, ...) return p._source(...) end })

return p