Module:Item link
This module implements {{item link}} and facilitates the creation of item links.
The above documentation is transcluded from Module:Item link/doc.
Editors can experiment in this module's sandbox and testcases pages.
Subpages of this module.
Editors can experiment in this module's sandbox and testcases pages.
Subpages of this module.
-- Item link module
--
-- This is separate from the main item module for small speed ups.
--
-- Those speed ups are only sigificant if the module is called a lot of times (100+), in tests this amounted to only a ~10% difference in page load times at best.
-- It should be noted those tests are difficult because of the large variance in page load times
-- ----------------------------------------------------------------------------
-- Imports
-- ----------------------------------------------------------------------------
local m_util = require('Module:Util')
local getArgs = require('Module:Arguments').getArgs
local m_cargo = require('Module:Cargo')
-- ----------------------------------------------------------------------------
-- Strings
-- ----------------------------------------------------------------------------
-- This section contains strings used by this module.
-- Add new strings here instead of in-code directly, this will help other
-- people to correct spelling mistakes easier and help with translation to
-- other PoE wikis.
--
-- TODO: Maybe move this out to a separate sub-page module
local i18n = {
categories = {
-- maintenance cats
broken_item_links = 'Pages with broken item links',
},
errors = {
invalid_args = 'Item link: metadata_id, page, item_name or item_name_exact must be specified',
no_results = 'Item link: No results found for search parameter "%s".',
too_many_results = 'Item link: Too many results for search parameter "%s". Consider using page parameter instead.',
alt_art_undefined = 'Item link: Image parameter was specified, but there is no alternate art defined on page "%s"',
alt_art_invalid_index = 'Item Link: Alternate art with index/name "%s" not found on page "%s"',
},
}
-- ----------------------------------------------------------------------------
-- Constants & Data
-- ----------------------------------------------------------------------------
local c = {}
c.image_size = 39
c.image_size_full = c.image_size * 2
c.parameters = {
name = 'items.name',
inventory_icon = 'items.inventory_icon',
html = 'items.html',
width = 'items.size_x',
height = 'items.size_y',
}
c.selectors = {'metadata_id', 'page', 'item_name', 'item_name_exact'}
-- ----------------------------------------------------------------------------
-- Invokable code
-- ----------------------------------------------------------------------------
--
-- Template:Item link
--
local p = {}
function p.item_link (frame)
--[[
Creates a link to the item and displays the item info box on hover
on the link.
Examples
--------
= p.item_link{'Multistrike'}
= p.item_link{'Multistrike Support'}
]]
-- Get arguments:
local tpl_args = getArgs(frame, {
parentFirst = true,
removeBlanks = false,
})
frame = m_util.misc.get_frame(frame)
-- Backwards compability
tpl_args.item_name = tpl_args.item_name or tpl_args[1]
tpl_args.name = tpl_args.name or tpl_args[2]
if m_util.table.has_all_value(tpl_args, c.selectors) and tpl_args.skip_query == nil then
error(i18n.errors.invalid_args)
end
tpl_args.large = m_util.cast.boolean(tpl_args.large)
local img
local result
if m_util.table.has_one_value(tpl_args, c.selectors, nil) and tpl_args.skip_query == nil then
local query = {
groupBy='items._pageID',
}
if tpl_args.metadata_id ~= nil then
query.where = string.format(
'items.metadata_id="%s"',
tpl_args.metadata_id
)
elseif tpl_args.page ~= nil then
-- TODO returns the result even if the + format is specified.
query.where = string.format(
'items._pageName="%s"',
tpl_args.page
)
else
if tpl_args.item_name ~= nil then
-- HOLDS is unreliable, using __FULL and REGEXP instead:
query.where = string.format(
'items.name_list__FULL REGEXP "(�|^)%s(�|$)"',
tpl_args.item_name
)
elseif tpl_args.item_name_exact ~= nil then
query.where = string.format(
'items.name = "%s"',
tpl_args.item_name_exact
)
end
end
if tpl_args.link_type == 'skill' then
query.where = string.format(
'%s AND (items.class = "Active Skill Gems" OR items.class = "Support Skill Gems")',
query.where
)
end
result = m_cargo.query(
{
'items'
},
{
'items._pageName',
'items.name',
'items.inventory_icon',
'items.html',
'items.alternate_art_inventory_icons',
'items.size_x',
'items.size_y',
'items.drop_enabled',
'items.class_id',
},
query
)
local err
local j = 1
if #result == 0 then
err = m_util.misc.raise_error_or_return{
raise_required=true,
args=tpl_args,
msg=string.format(
i18n.errors.no_results,
tpl_args.page or tpl_args.item_name or tpl_args.item_name_exact
)
}
elseif #result > 1 then
-- If only one of the results is drop enabled then use that one:
local n = 0
for i,v in ipairs(result) do
if m_util.cast.boolean(v['items.drop_enabled']) then
j = i
n = n+1
end
end
if n ~= 1 then
err = m_util.misc.raise_error_or_return{
raise_required=true,
args=tpl_args,
msg=string.format(
i18n.errors.too_many_results,
tpl_args.page or tpl_args.item_name or tpl_args.item_name_exact
)
}
end
end
if err ~= nil then
return err .. m_util.misc.add_category({i18n.categories.broken_item_links})
end
result = result[j]
else
result = {
['items._pageName'] = tpl_args.page or tpl_args.name
}
end
for k, prop in pairs(c.parameters) do
if tpl_args[k] ~= nil then
result[prop] = tpl_args[k]
end
end
if tpl_args.image ~= nil then
if result['items.alternate_art_inventory_icons'] == nil then
return m_util.misc.raise_error_or_return{
raise_required=true,
args=tpl_args,
msg=string.format(
i18n.errors.alt_art_undefined,
result['items._pageName']
) .. m_util.misc.add_category({i18n.categories.broken_item_links})
}
end
result['items.alternate_art_inventory_icons'] = m_util.string.split(
result['items.alternate_art_inventory_icons'],
',%s*'
)
local index = tonumber(tpl_args.image)
if index ~= nil then
img = result['items.alternate_art_inventory_icons'][index]
else
-- offset 1 is needed
local suffix = string.len(' inventory icon.png') + 1
-- add an extra offset by 1 to account for the space
local prefix = string.len(string.sub(result['items.inventory_icon'], 1, -suffix)) + 2
for _, filename in ipairs(result['items.alternate_art_inventory_icons']) do
if string.sub(filename, prefix, -suffix) == tpl_args.image then
img = filename
break
end
end
end
if img == nil then
return m_util.misc.raise_error_or_return{
raise_required=true,
args=tpl_args,
msg=string.format(
i18n.errors.alt_art_invalid_index,
tpl_args.image, result['items._pageName']
) .. m_util.misc.add_category({i18n.categories.broken_item_links})
}
end
elseif result['items.inventory_icon'] ~= nil then
img = result['items.inventory_icon']
end
--
-- output
--
-- Maps have their main page on the item name now, link there instead.
-- Hopefully there are no maps with identical names besides the series.
local linked_page
if result['items.class_id'] == 'Map' and tpl_args.page == nil then
linked_page = tpl_args.link or tpl_args.item_name
else
linked_page = tpl_args.link or result['items._pageName']
end
local container = mw.html.create('span')
container:addClass('c-item-hoverbox')
if tpl_args.large then
container:addClass('c-item-hoverbox--large')
end
local activator = mw.html.create('span')
activator:addClass('c-item-hoverbox__activator')
if img and not tpl_args.large then
activator:wikitext(string.format('[[%s|16x16px|link=|alt=]]', img))
end
if #result['items.name'] > 0 then
activator:wikitext(string.format(
'[[%s|%s]]',
linked_page,
result['items.name'] or result['items._pageName']
)
)
end
local display = mw.html.create('span')
display:attr('class', 'c-item-hoverbox__display')
if result['items.html'] ~= nil then
display:wikitext(result['items.html'])
if img then
display:wikitext(string.format('[[%s|link=|alt=]]', img))
end
end
if img and tpl_args.large then
local width = tonumber(result['items.size_x']) or tonumber(tpl_args.width)
local height = tonumber(result['items.size_y']) or tonumber(tpl_args.height)
if width and height then
img = string.format(
'[[%s|%sx%spx|link=%s|alt=]]',
img,
width*c.image_size,
height*c.image_size,
linked_page
)
elseif width then
img = string.format(
'[[%s|%spx|link=%s|alt=]]',
img,
width*c.image_size,
linked_page
)
elseif height then
img = string.format(
'[[%s|x%spx|link=%s|alt=]]',
img,
height*c.image_size,
linked_page
)
else
img = string.format(
'[[%s|link=%s|alt=]]',
img,
linked_page
)
end
activator:wikitext(img)
end
container
:node(activator)
:node(display)
:done()
return tostring(container)
end
return p