Terraria Wiki
无编辑摘要
(同步。 sync :: en revid:1130586::)
(未显示同一用户的28个中间版本)
第1行: 第1行:
  +
---Holds the tables with the l10n information for the different languages, taken from the l10n submodule.
-- l10n text, need to be translated.
 
  +
local l10n_info = mw.loadData('Module:Item/l10n')
local l10n = {
 
['en'] = {
 
['id_text_item'] = 'Internal [[Item IDs|Item ID]]: ',
 
['id_text_tile'] = 'Internal [[Tile IDs|Tile ID]]: ',
 
['id_text_wall'] = 'Internal [[Wall IDs|Wall ID]]: ',
 
['id_text_npc'] = 'Internal [[NPC IDs|NPC ID]]: ',
 
['id_text_mount'] = 'Internal [[Mount IDs|Mount ID]]: ',
 
['id_text_buff'] = 'Internal [[Buff IDs|Buff ID]]: ',
 
['id_text_projectile'] = 'Internal [[Projectile IDs|Projectile ID]]: ',
 
['id_text_armor'] = 'Internal [[Armor IDs|Armor ID]]: ',
 
},
 
['zh'] = {
 
['id_text_item'] = '内部[[物品 ID]]:',
 
['id_text_tile'] = '内部[[图格 ID]]:',
 
['id_text_wall'] = '内部[[墙 ID]]:',
 
['id_text_npc'] = '内部 [[NPC ID]]:',
 
['id_text_mount'] = '内部[[坐骑 ID]]:',
 
['id_text_buff'] = '内部[[增益 ID]]:',
 
['id_text_projectile'] = '内部[[射弹 ID]]:',
 
['id_text_armor'] = '内部[[盔甲 ID]]:',
 
},
 
}
 
   
  +
---Holds the l10n information for the current language, as key-value pairs.
-- l10n function to get plural form, it may be different for each language. If function for target language does not exist, the EN version is used.
 
  +
local l10n_table
-- about the function itself:
 
-- return plural form, nil if no pluralism processing occurs.
 
-- _arg1 is the original text(after auto translation), _arg2 is custom text or plural postfix, may be s/es/ies/ves (for english).
 
local plural = {
 
-- for English (en)
 
['en'] = function(_arg1, _arg2)
 
-- intuitive pluralism
 
-- The comparisons are performed in order, so putting the more common ones in front gives the best performance.
 
if _arg2 == 's' then
 
local suffix1 = _arg1:sub(-1) -- cache for better performance.
 
local suffix2 = _arg1:sub(-2) -- cache for better performance.
 
if suffix1 == 'y' then
 
if suffix2 == 'ay' or suffix2 == 'ey' or suffix2 == 'iy' or suffix2 == 'oy' or suffix2 == 'uy' then
 
return _arg1 .. 's' -- eg. ray->rays
 
else
 
return _arg1:sub(1, -2) .. 'ies' -- eg. firefly->fireflies
 
end
 
end
 
if suffix2 == 'fe' and string.lower(_arg1) ~= 'safe' then
 
return _arg1:sub(1, -3) .. 'ves' -- eg. knife->knives
 
end
 
if suffix1 == 'f' and suffix2 ~= 'ff' then
 
return _arg1:sub(1, -2) .. 'ves' -- eg. wolf->wolves, leaf->leaves, but buff->buffs
 
else
 
return _arg1 .. 's'
 
end
 
end
 
   
  +
---The current language. Determines which l10n table to use.
if _arg2 == 'es' then
 
  +
local lang
return _arg1 .. 'es'
 
end
 
   
  +
local trim = mw.text.trim
if _arg2 == 'ies' then
 
  +
local cargo = mw.ext.cargo
return _arg1:sub(1, -2) .. 'ies'
 
  +
local eicons = require('Module:Exclusive').simpleEicons
end
 
  +
local cache = require 'mw.ext.LuaCache'
   
  +
local should_cache = true
if _arg2 == 'ves' then
 
if _arg1:sub(-2) == 'fe' then
 
return _arg1:sub(1, -3) .. 'ves' --replace last 2 letters, e.g. knife->knives
 
end
 
if _arg1:sub(-1) == 'f' or _arg1:sub(-2) ~= 'ff' then
 
return _arg1:sub(1, -2) .. 'ves' --replace last letter, e.g. wolf-wolves, leaf->leaves, but buff->buffs
 
end
 
end
 
end,
 
   
  +
---A cached version of the current frame, the interface to the parser.
-- for Chinese (zh)
 
  +
local currentFrame
['zh'] = function(_arg1, _arg2)
 
  +
---Holds the arguments from the template call.
-- there is no plural form in chinese
 
  +
local args_table
if _arg2 == 's' or _arg2 == 'es' or _arg2 == 'ies' or _arg2 == 'ves' then
 
return _arg1
 
end
 
return nil
 
end,
 
}
 
   
   
  +
---Return the l10n string associated with the `key`.
  +
---@param key string
  +
---@return string
  +
local function l10n(key)
  +
return l10n_table[key] or l10n_info['en'][key]
  +
end
   
  +
---Return a trimmed version of the value of the template parameter with the specified `key`.
  +
---Return `nil` if the parameter is empty or unset.
  +
---@param key string|number
  +
---@return string|nil
  +
local function getArg(key)
  +
local value = args_table[key]
  +
if not value then
  +
return nil
  +
end
  +
value = trim(value)
  +
if value == '' then
  +
return nil
  +
end
  +
return value
  +
end
   
  +
---Convert a string of parameters in a `@param1:value^@param2:value^` format to a table.
------- The following is not related to l10n. --------------
 
  +
---Change the `name` and `text` parameters to `1` and `2`, respectively.
 
  +
---@param paramstr string
local trim = mw.text.trim
 
  +
---@return table
local cargo = mw.ext.cargo
 
  +
local function parse(paramstr)
 
local currentFrame -- cache
+
local args = {}
  +
for s in string.gmatch(paramstr, '%b@^') do
  +
local k,v = string.match(s, '^@(.-):(.*)^$')
  +
args[k] = v
  +
end
  +
args[1] = args['name']
  +
args[2] = args['text']
  +
return args
  +
end
   
  +
---Split the `str` on each `div` in it and return the result as a table.
-- credit: http://richard.warburton.it
 
  +
---Original version credit: http://richard.warburton.it. This version trims each substring.
-- this version is with trim.
 
  +
---@param div string
local function explode(div,str)
 
  +
---@param str string
  +
---@return table|boolean
  +
local function explode(div,str)
 
if (div=='') then return false end
 
if (div=='') then return false end
 
local pos,arr = 0,{}
 
local pos,arr = 0,{}
 
-- for each divider found
 
-- for each divider found
 
for st,sp in function() return string.find(str,div,pos,true) end do
 
for st,sp in function() return string.find(str,div,pos,true) end do
table.insert(arr,trim(string.sub(str,pos,st-1))) -- Attach chars left of current divider
+
arr[#arr + 1] = trim(string.sub(str,pos,st-1)) -- Attach chars left of current divider
 
pos = sp + 1 -- Jump past current divider
 
pos = sp + 1 -- Jump past current divider
 
end
 
end
table.insert(arr, trim(string.sub(str,pos))) -- Attach chars right of last divider
+
arr[#arr + 1] = trim(string.sub(str,pos)) -- Attach chars right of last divider
 
return arr
 
return arr
 
end
 
end
   
  +
---Extract scale, width, and height from an input string. Up to two of the three can be empty in the input.
local escape = function(str)
 
  +
---Example: `5x7px*0.75` → `0.75`, `5`, `7`
return str:gsub("'", "\\'"):gsub("'", "\\'")
 
  +
---@param size string
end
 
  +
---@return string basescale
local enclose = function(str)
 
return "'" .. escape(str) .. "'"
+
---@return number width
  +
---@return number height
end
 
 
local function getText(_arg1, _arg2, lang, frame)
 
_arg1 = frame:expandTemplate{ title = 'tr', args = {_arg1, lang=lang} } -- auto translate
 
if not _arg2 then
 
return _arg1
 
end
 
local plural_function = plural[lang] or plural['en'] or function() end
 
return plural_function(_arg1, _arg2) or _arg2
 
end
 
 
 
local function parseSize(size)
 
local function parseSize(size)
  +
if not size then return end
 
local basescale, width, height
 
local basescale, width, height
  +
size, basescale = unpack(explode('*', size))
if size then
 
size, basescale = unpack(explode('*', size))
+
if size ~= '' then
  +
width, height = unpack(explode('x', string.gsub(size, 'px', '')))
if size ~= '' then
 
width, height = unpack(explode('x', string.gsub(size, 'px', '')))
+
width, height = tonumber(width), tonumber(height)
width, height = tonumber(width), tonumber(height)
+
if width == 0 then width = nil end
if width == 0 then width = nil end
+
if height == 0 then height = nil end
if height == 0 then height = nil end
 
end
 
 
end
 
end
 
return basescale, width, height
 
return basescale, width, height
 
end
 
end
   
  +
---Return width, height, and caching date for the specified `imagename` from the Imageinfo cargo table.
local function getInfoFromCargo(image)
 
  +
---@param imagename string
  +
---@return number width
  +
---@return number height
  +
---@return string cached
  +
local function getInfoFromCargo(imagename)
 
-- try to get from cargo cache
 
-- try to get from cargo cache
 
local result = mw.ext.cargo.query('Imageinfo', 'width, height, cached', {
 
local result = mw.ext.cargo.query('Imageinfo', 'width, height, cached', {
  +
-- escape apostrophes in the imagename input
where = 'image='..enclose(image),
 
  +
where = 'image='.. "'"..imagename:gsub("'", "\\'"):gsub("'", "\\'").."'",
 
orderBy = "cached DESC",
 
orderBy = "cached DESC",
 
limit = 1,
 
limit = 1,
第144行: 第111行:
 
return tonumber(row['width']), tonumber(row['height']), row['cached']
 
return tonumber(row['width']), tonumber(row['height']), row['cached']
 
end
 
end
return nil, nil, nil
 
 
end
 
end
   
  +
---Store width and height of the specified `imagename` to the Imageinfo cargo table and return them.
local function storeInfoToCargo(image)
 
  +
---Width and height are computed via the `#imgw:` and `#imgh:` parser functions, respectively.
local width, height
 
  +
---@param imagename string
width = tonumber(currentFrame:callParserFunction( '#imgw', image))
 
  +
---@return number width
if width and width ~= 0 then -- save one expensive call when the file is not a valid image.
 
  +
---@return number height
height = tonumber(currentFrame:callParserFunction( '#imgh', image))
 
  +
local function storeInfoToCargo(imagename)
end
 
  +
-- don't cache {{item}}'s result when parsing imagesize fails.
  +
should_cache = false
  +
local imageTitle = mw.title.new("File:" .. imagename)
  +
local width, height = imageTitle.file.width, imageTitle.file.height
 
if width and width ~= 0 and height and height ~= 0 then
 
if width and width ~= 0 and height and height ~= 0 then
  +
should_cache = true -- ok, cache it.
 
currentFrame:callParserFunction('#cargo_store:_table=Imageinfo',{
 
currentFrame:callParserFunction('#cargo_store:_table=Imageinfo',{
image = image,
+
image = imagename,
 
width = width,
 
width = width,
 
height = height,
 
height = height,
第164行: 第135行:
 
end
 
end
   
  +
---Retrieve the dimensions of the specified `image` from the Imageinfo cargo table.
local function getSizeInfo(image)
 
  +
---If it doesn't have any data for the image yet, store it.
local width, height, cached = getInfoFromCargo(image)
 
  +
---@param imagename string
  +
---@return number width
  +
---@return number height
  +
local function getSizeInfo(imagename)
  +
local width, height, cached = getInfoFromCargo(imagename)
 
-- cache missed, init cache
 
-- cache missed, init cache
 
if not cached then
 
if not cached then
width, height = storeInfoToCargo(image)
+
width, height = storeInfoToCargo(imagename)
 
end
 
end
  +
if width == 0 then width = nil end
  +
if height == 0 then height = nil end
 
return width, height
 
return width, height
 
end
 
end
   
local function getImageSize(image, width, height, scale, maxwidth, maxheight)
+
---Compute the final width and height of the image.
  +
---If necessary, retrieve data from or store data to the Imageinfo cargo table.
  +
---@param imagename string
  +
---@param width number
  +
---@param height number
  +
---@param scale number
  +
---@param maxwidth number
  +
---@param maxheight number
  +
---@return number width
  +
---@return number height
  +
local function getImageSize(imagename, width, height, scale, maxwidth, maxheight)
 
-- get size info from image file itself (may be expensive)
 
-- get size info from image file itself (may be expensive)
local w, h = getSizeInfo(image) -- store data to cache
+
local w, h = getSizeInfo(imagename) -- store data to cache
   
  +
-- if width and height are not given as input, but scale/maxwidth/maxheight are, then
  +
-- set width and height to the original dimensions of the image
 
if not width and not height and (scale or maxwidth or maxheight) then
 
if not width and not height and (scale or maxwidth or maxheight) then
 
width, height = w, h
 
width, height = w, h
第187行: 第177行:
 
end
 
end
   
-- apply maxwidth/maxheight.
+
-- apply maxwidth/maxheight
 
if maxwidth then
 
if maxwidth then
 
if width then
 
if width then
第203行: 第193行:
 
end
 
end
   
  +
-- round to natural numbers
-- rounding
 
 
if width then width = math.ceil(width) end
 
if width then width = math.ceil(width) end
 
if height then height = math.ceil(height) end
 
if height then height = math.ceil(height) end
第210行: 第200行:
 
end
 
end
   
  +
---Extract width and height from an input string.
  +
---Example: `6x9px` → `6`, `9`
  +
---@param maxsize string
  +
---@return number maxwidth
  +
---@return number maxheight
 
local function parseMaxSize(maxsize)
 
local function parseMaxSize(maxsize)
if not maxsize then
+
if not maxsize then return end
return nil,nil
 
end
 
 
local maxwidth, maxheight = unpack(explode('x', string.gsub(maxsize, 'px', '')))
 
local maxwidth, maxheight = unpack(explode('x', string.gsub(maxsize, 'px', '')))
 
maxwidth, maxheight = tonumber(maxwidth), tonumber(maxheight)
 
maxwidth, maxheight = tonumber(maxwidth), tonumber(maxheight)
第221行: 第214行:
 
end
 
end
   
  +
---Assemble the final wikicode for an image.
local function getScale(scale, basescale)
 
  +
---@param imagename string
scale = (tonumber(scale) or 1) * (tonumber(basescale) or 1)
 
  +
---@param link string
if scale == 0 or scale == 1 then
 
  +
---@param text string
scale = nil
 
  +
---@param size string As accepted by the `[[File:` syntax, e.g. `5x7px*0.75`.
end
 
  +
---@param scale number This will be multiplied by the scale in `size`, if necessary.
return scale
 
  +
---@param maxsize string
end
 
  +
---@return string
 
local function imagecode(image, link, text, size, scale, maxsize)
+
local function imagecode(imagename, link, text, size, scale, maxsize)
local image_output = '[[File:' .. image .. '|link='.. link .. '|' .. text
+
local image_output = '[[File:' .. imagename .. '|link='.. link .. '|' .. text
 
if size or scale or maxsize then
 
if size or scale or maxsize then
local basescale, width, height = parseSize(size) -- width,height: number or nil
+
local basescale, width, height = parseSize(size) -- width, height: number or nil (basescale is string!)
scale = getScale(scale, basescale) -- number or nil
+
scale = (tonumber(scale) or 1) * (tonumber(basescale) or 1) -- combine the scale parameter and scale from the size parameter
  +
if scale == 0 or scale == 1 then
  +
scale = nil
  +
end
 
local maxwidth, maxheight = parseMaxSize(maxsize)
 
local maxwidth, maxheight = parseMaxSize(maxsize)
width, height = getImageSize(image, width, height, scale, maxwidth, maxheight) -- can be 0
+
width, height = getImageSize(imagename, width, height, scale, maxwidth, maxheight) -- can be 0
 
if width or height then
 
if width or height then
return image_output .. '|' .. (width or '') .. 'x' .. (height or '') .. 'px]]'
+
image_output = image_output .. '|' .. (width or '') .. 'x' .. (height or '') .. 'px'
else
 
return image_output .. ']]'
 
 
end
 
end
else
 
return image_output .. ']]'
 
 
end
 
end
  +
return image_output .. ']]'
 
end
 
end
   
  +
---Return the full `[[File:` wikicode for each image in the input (multiple are separated with `/`).
local image_for_cargo
 
  +
---@param image string
  +
---@param link string
  +
---@param text string
  +
---@param size string
  +
---@param scale string
  +
---@param maxsize string
  +
---@return string
 
local function images(image, link, text, size, scale, maxsize)
 
local function images(image, link, text, size, scale, maxsize)
  +
 
 
if not image:find('/') then
 
if not image:find('/') then
  +
-- there is only one image in the input
image_for_cargo = image
 
 
return imagecode(image, link, text, size, scale, maxsize)
 
return imagecode(image, link, text, size, scale, maxsize)
 
end
 
end
   
  +
-- there are multiple images in the input, separated with a slash
 
image = explode('/', image)
 
image = explode('/', image)
 
local result = ''
 
local result = ''
 
if size and size:find('/') then
 
if size and size:find('/') then
  +
-- there are multiple sizes in the size parameter
size = explode('/', size)
 
  +
size = explode('/', size) -- so turn it into a table
for i, v in ipairs(image) do
 
  +
for i, v in ipairs(image) do -- iterate over the images
result = result .. imagecode(v, link, text, size[i], scale, maxsize)
 
  +
result = result .. imagecode(v, link, text, size[i], scale, maxsize) -- create the wikicode (using the respective size)
 
end
 
end
 
else
 
else
for i, v in ipairs(image) do
+
for i, v in ipairs(image) do -- iterate over the images
result = result .. imagecode(v, link, text, size, scale, maxsize)
+
result = result .. imagecode(v, link, text, size, scale, maxsize) -- create the wikicode
 
end
 
end
 
end
 
end
第269行: 第271行:
 
end
 
end
   
  +
---Return a string like `Internal Item ID: `, depending on the `_type`.
local getIdText = function(_type, lang)
 
  +
---@param _type '"item"'|'"tile"'|'"wall"'|'"npc"'|'"mount"'|'"buff"'|'"projectile"'|'"armor"'
_type = _type:lower()
 
  +
---@return string
local id_text, needcargo
 
  +
local function getIdText(_type)
  +
local id_text
 
if _type == 'item' then -- a shortcut for faster
 
if _type == 'item' then -- a shortcut for faster
id_text = l10n[lang]['id_text_item'] or l10n['en']['id_text_item']
+
id_text = l10n('id_text_item')
needcargo = true
 
 
elseif _type == 'tile' then
 
elseif _type == 'tile' then
id_text = l10n[lang]['id_text_tile'] or l10n['en']['id_text_tile']
+
id_text = l10n('id_text_tile')
 
elseif _type == 'wall' then
 
elseif _type == 'wall' then
id_text = l10n[lang]['id_text_wall'] or l10n['en']['id_text_wall']
+
id_text = l10n('id_text_wall')
 
elseif _type == 'npc' then
 
elseif _type == 'npc' then
id_text = l10n[lang]['id_text_npc'] or l10n['en']['id_text_npc']
+
id_text = l10n('id_text_npc')
 
elseif _type == 'mount' then
 
elseif _type == 'mount' then
id_text = l10n[lang]['id_text_mount'] or l10n['en']['id_text_mount']
+
id_text = l10n('id_text_mount')
 
elseif _type == 'buff' or _type == 'debuff' then
 
elseif _type == 'buff' or _type == 'debuff' then
id_text = l10n[lang]['id_text_buff'] or l10n['en']['id_text_buff']
+
id_text = l10n('id_text_buff')
 
elseif _type == 'projectile' then
 
elseif _type == 'projectile' then
id_text = l10n[lang]['id_text_projectile'] or l10n['en']['id_text_projectile']
+
id_text = l10n('id_text_projectile')
 
elseif _type == 'armor' then
 
elseif _type == 'armor' then
id_text = l10n[lang]['id_text_armor'] or l10n['en']['id_text_armor']
+
id_text = l10n('id_text_armor')
 
else
 
else
id_text = l10n[lang]['id_text_item'] or l10n['en']['id_text_item']
+
id_text = l10n('id_text_item')
needcargo = true
 
 
end
 
end
return id_text, needcargo
+
return id_text
 
end
 
end
   
第299行: 第301行:
 
-- main return object
 
-- main return object
 
return {
 
return {
  +
 
  +
parse = parse,
 
go = function(frame, args)
 
go = function(frame, args)
currentFrame = frame -- cache
+
-- cache?
if args then
+
if not args then
  +
local cached = cache.get(':_item:' .. frame.args[1])
for k, v in pairs(args) do
 
if v == '' then
+
if cached then
args[k] = nil
+
return cached
end
 
end
 
if args['nolink'] then
 
args['link'] = ''
 
else
 
if not args['link'] then
 
args['link'] = args[1]
 
end
 
 
end
 
end
 
end
 
end
   
  +
-- init var cache
local getArg = function(key)
 
  +
currentFrame = frame
if args then
 
  +
args_table = args or parse(frame.args[1])
return args[key]
 
  +
lang = getArg('lang') or 'en'
else
 
  +
l10n_table = l10n_info[lang] or l10n_info['en']
local value = frame.args[key]
 
if not value then
 
return nil
 
end
 
value = trim(value)
 
if value == '' then
 
return nil
 
else
 
return value
 
end
 
end
 
end
 
   
local lang = getArg('lang') or 'en' -- cache lang setting.
+
local _arg1 = getArg(1) or ''
  +
local _nolink = getArg('nolink')
  +
local _link = _nolink and '' or getArg('link') or frame:expandTemplate{ title = 'tr', args = {_arg1, link='y', lang=lang} } -- now: _link == '' means nolink
   
local _arg1 = getArg(1) or ''
+
local text = getArg(2) or ''
  +
local _rawlink = trim(frame.args['link'] or args['link'] or '') -- keep '' input
 
  +
-- hovertext: {{tr|_arg1}} or text or _link (in that order)
local _link
 
  +
local hovertext
if _rawlink == '' then
 
_link = ''
+
if _arg1 ~= '' then
  +
hovertext = frame:expandTemplate{ title = 'tr', args = {_arg1, lang=lang} }
  +
elseif text ~= '' then
  +
hovertext = text
 
else
 
else
  +
hovertext = _link
_link = frame:expandTemplate{ title = 'tr', args = {_rawlink, link = 'y', lang=lang} } -- auto translate
 
 
end
 
end
   
  +
-- set output flags
local _arg2 = getArg(2)
 
local text = getText(_arg1, _arg2, lang, frame) -- text will be auto translated.
 
 
local class = 'item-link'
 
 
 
local output_image, output_text, output_table = true, true, false
 
local output_image, output_text, output_table = true, true, false
 
local _mode = getArg('mode')
 
local _mode = getArg('mode')
第362行: 第347行:
 
end
 
end
   
local image_output = ''
+
local class = 'i'
  +
  +
local image_output, text_output
  +
-- get wikicode for the image(s)
 
if output_image then
 
if output_image then
  +
local image_arg = getArg('image')
image_output = images(getArg('image') or (_arg1 .. '.' .. (getArg('ext') or 'png')), _link, text, getArg('size'), getArg('scale'), getArg('maxsize'))
 
  +
if not image_arg then
  +
if _arg1 == '1/2 Second Timer' then
  +
image_arg = '1 2 Second Timer'
  +
elseif _arg1 == '1/4 Second Timer' then
  +
image_arg = '1 4 Second Timer'
  +
else
  +
image_arg = string.gsub(_arg1, ":%s*", " ")
  +
end
  +
image_arg = image_arg .. '.' .. (getArg('ext') or 'png')
  +
end
  +
if string.find(image_arg, '%[%[[fF]ile:') then
  +
image_output = '<span class="img">' .. image_arg .. '</span>'
  +
else
  +
image_output = images(image_arg, _link, hovertext, getArg('size'), getArg('scale'), getArg('maxsize'))
  +
end
  +
else
  +
image_output = ''
 
end
 
end
  +
-- get wikicode for the text
 
local text_output = ''
 
 
if output_text then
 
if output_text then
  +
local _note, _note2, _showid, _id, _icon = getArg('note'), getArg('note2'), getArg('showid'), getArg('id'), getArg('icons') -- get info from arguments
local _note = getArg('note')
 
local _note2 = getArg('note2')
 
local _id = getArg('id')
 
   
  +
-- prepare: display ID?
  +
if _id and not _showid then
  +
_showid = true
  +
end
  +
if _showid and (_showid == 'n' or _showid == 'no') then
  +
_showid = false
  +
end
  +
  +
-- prepare: wrap?
 
local _wrap
 
local _wrap
if _id or _note2 then
+
if _showid or _note2 then
 
_wrap = false
 
_wrap = false
 
else
 
else
第380行: 第391行:
 
end
 
end
   
  +
-- prepare: link and display text
 
if _link ~= '' then
 
if _link ~= '' then
 
if text == _link then
 
if text == _link then
text = '[['..text..']]'
+
text = '<span>[['..text..']]</span>'
 
else
 
else
text = '[['.._link..'|'..text..']]'
+
text = '<span>[['.._link..'|'..text..']]</span>'
 
end
 
end
  +
else
  +
text = '<span title="'..hovertext..'">'..text..'</span>'
 
end
 
end
   
  +
-- prepare: eicons
local _icon = getArg('icons')
 
local icon = ''
+
local icon = nil
if not (_icon == 'n' or _icon == 'no' or _icon == 'off') then
+
if _icon == 'n' or _icon == 'no' or _icon == 'off' then
  +
icon = ''
-- eicons should base on link first.
 
  +
else
local t
 
  +
icon = eicons(getArg('epage') or _arg1, lang, (_showid or _note2 or _wrap or getArg('small')) and 'y')
if _link ~= '' then
 
t = _rawlink -- untranslated
 
else
 
t = _arg1
 
end
 
local args = {t}
 
if _id or _note2 or _wrap or getArg('small') then
 
args['small'] = 'y'
 
end
 
icon = frame:expandTemplate{ title = 'eicons', args = args } -- eicons will do auto translate.
 
 
end
 
end
   
  +
-- assemble HTML code
local content = mw.text.tag('span', nil, text)
 
  +
local content = text -- item name link text first.
 
-- '-w' class means 'wrapmode', optimized for multiple lines of text. But it should be disabled for single line text.
 
-- '-w' class means 'wrapmode', optimized for multiple lines of text. But it should be disabled for single line text.
 
if _wrap then
 
if _wrap then
  +
-- eicons in the same line
 
if icon ~= '' then
 
if icon ~= '' then
 
class = class .. ' -w'
 
class = class .. ' -w'
 
content = content .. icon
 
content = content .. icon
 
end
 
end
  +
-- note in a new line
 
if _note then
 
if _note then
 
class = class .. ' -w'
 
class = class .. ' -w'
content = content .. mw.text.tag('span',{class='note'}, _note)
+
content = content .. '<span class="note">' .. _note .. '</span>'
 
end
 
end
 
else
 
else
  +
-- note in the same line
 
if _note then
 
if _note then
content = content .. mw.text.tag('span',{class='note'}, _note)
+
content = content .. '<span class="note">' .. _note .. '</span>'
 
end
 
end
  +
-- eicons in the same line
 
if icon ~= '' then
 
if icon ~= '' then
 
content = content .. icon
 
content = content .. icon
 
end
 
end
  +
-- note2 in a new line
 
if _note2 then
 
if _note2 then
 
class = class .. ' -w'
 
class = class .. ' -w'
content = content .. mw.text.tag('div',{class='note'}, _note2)
+
content = content .. '<div class="note">' .. _note2 .. '</div>'
 
end
 
end
if _id then
+
-- id in a new line
  +
if _showid then
 
class = class .. ' -w'
 
class = class .. ' -w'
local id_text, needcargo = getIdText(getArg('type') or 'item', lang)
+
local idtype = (getArg('type') or 'item'):lower()
if needcargo and output_image and image_for_cargo then
+
if not _id then
  +
-- get ID automatically via {{itemIdFromName}} or the like
frame:expandTemplate{ title = 'Item/cargo', args = {name=_arg1, image=image_for_cargo, id=_id} }
 
  +
_id = frame:expandTemplate{ title = idtype .. 'IdFromName', args = {_arg1} }
 
end
 
end
  +
local id_text = getIdText(idtype)
content = content .. mw.text.tag('div', {class='id'}, id_text .. _id)
 
  +
content = content .. '<div class="id">' .. id_text .. _id .. '</div>'
 
end
 
end
 
end
 
end
text_output = mw.text.tag{name='span', content=content}
+
text_output = '<span>' .. content .. '</span>'
  +
else
  +
text_output = ''
 
end
 
end
   
  +
-- handle custom CSS
local _class = getArg('class')
 
local _css = getArg('css')
+
local _class, _css = getArg('class'), getArg('css')
 
 
if _class then
 
if _class then
class = class .. ' ' .. _class
+
class = class .. ' ' .. _class -- add to existing classes
 
end
 
end
 
 
local attr = {class = class}
 
local attr = {class = class}
 
if _css then
 
if _css then
attr.style = _css
+
attr.style = _css -- set the style attribute to parameter value
end
 
 
local anchor = ''
 
if getArg('anchor') then
 
anchor = mw.text.tag('div', {id=frame:callParserFunction('anchorencode', _arg1), class='anchor'}, '')
 
 
end
 
end
  +
  +
local return_string
 
if output_table then
 
if output_table then
  +
-- table output
attr.class = class .. ' block aligncenter'
 
  +
attr.class = class
local result = mw.text.tag('span', attr, image_output) .. '||'
 
  +
local _rowspan = getArg('rowspan')
attr.class = class .. ' block alignleft'
 
  +
local rowspan_text = (_rowspan and (' rowspan=' .. _rowspan) or '')
return result .. mw.text.tag('span', attr, text_output .. anchor)
 
  +
-- prepare the two cells
  +
local first_cell_pre = rowspan_text .. ' class="il1c"'
  +
local first_cell_content = mw.text.tag('span', attr, image_output)
  +
local second_cell_pre = rowspan_text .. ' class="il2c"'
  +
local second_cell_content = mw.text.tag('span', attr, text_output)
  +
-- combine
  +
return_string = first_cell_pre .. " | " .. first_cell_content .. " || " .. second_cell_pre .. " | " .. second_cell_content
  +
else
  +
-- non-table output (text/image)
  +
return_string = mw.text.tag('span', attr, image_output .. text_output)
  +
end
  +
  +
-- cache output for later reuse
  +
if not args and should_cache then
  +
cache.set(':_item:' .. frame.args[1], return_string, 3600*24) -- cache for 24 hours
  +
end
  +
  +
-- output
  +
return return_string
  +
  +
end,
  +
  +
purge = function(frame)
  +
cache.delete(':_item:' .. frame.args[1]) -- delete that cache key.
  +
end,
  +
  +
storeImageInfo = function(frame)
  +
currentFrame = frame
  +
local width, height = storeInfoToCargo(frame.args[1])
  +
if not width or width == 0 or not height or height == 0 then
  +
return
 
else
 
else
  +
return frame:callParserFunction{name = "#dplvar:set", args = {
return mw.text.tag('span', attr, image_output .. text_output .. anchor)
 
  +
"_image_exist", "1",
  +
"_image_width", width,
  +
"_image_height", height,
  +
}}
 
end
 
end
 
end,
 
end,
 
getText = getText,
 
   
 
}
 
}

2021年8月29日 (日) 14:56的版本

This module is intended to provide functionality to the {{item}} template.



---Holds the tables with the l10n information for the different languages, taken from the l10n submodule.
local l10n_info = mw.loadData('Module:Item/l10n')

---Holds the l10n information for the current language, as key-value pairs.
local l10n_table

---The current language. Determines which l10n table to use.
local lang

local trim = mw.text.trim
local cargo = mw.ext.cargo
local eicons = require('Module:Exclusive').simpleEicons
local cache = require 'mw.ext.LuaCache'

local should_cache = true

---A cached version of the current frame, the interface to the parser.
local currentFrame
---Holds the arguments from the template call.
local args_table


---Return the l10n string associated with the `key`.
---@param key string
---@return string
local function l10n(key)
	return l10n_table[key] or l10n_info['en'][key]
end

---Return a trimmed version of the value of the template parameter with the specified `key`.
---Return `nil` if the parameter is empty or unset.
---@param key string|number
---@return string|nil
local function getArg(key)
	local value = args_table[key]
	if not value then
		return nil
	end
	value = trim(value)
	if value == '' then
		return nil
	end
	return value
end

---Convert a string of parameters in a `@param1:value^@param2:value^` format to a table.
---Change the `name` and `text` parameters to `1` and `2`, respectively.
---@param paramstr string
---@return table
local function parse(paramstr)
	local args = {}
	for s in string.gmatch(paramstr, '%b@^') do
		local k,v = string.match(s, '^@(.-):(.*)^$')
		args[k] = v
	end
	args[1] = args['name']
	args[2] = args['text']
	return args
end

---Split the `str` on each `div` in it and return the result as a table.
---Original version credit: http://richard.warburton.it. This version trims each substring.
---@param div string
---@param str string
---@return table|boolean
local function explode(div,str)
	if (div=='') then return false end
	local pos,arr = 0,{}
	-- for each divider found
	for st,sp in function() return string.find(str,div,pos,true) end do
		arr[#arr + 1] = trim(string.sub(str,pos,st-1)) -- Attach chars left of current divider
		pos = sp + 1 -- Jump past current divider
	end
	arr[#arr + 1] = trim(string.sub(str,pos)) -- Attach chars right of last divider
	return arr
end

---Extract scale, width, and height from an input string. Up to two of the three can be empty in the input.
---Example: `5x7px*0.75` → `0.75`, `5`, `7`
---@param size string
---@return string basescale
---@return number width
---@return number height
local function parseSize(size)
	if not size then return end
	local basescale, width, height
	size, basescale = unpack(explode('*', size))
	if size ~= '' then
		width, height = unpack(explode('x', string.gsub(size, 'px', '')))
		width, height = tonumber(width), tonumber(height)
		if width == 0 then width = nil end
		if height == 0 then height = nil end
	end
	return basescale, width, height
end

---Return width, height, and caching date for the specified `imagename` from the Imageinfo cargo table.
---@param imagename string
---@return number width
---@return number height
---@return string cached
local function getInfoFromCargo(imagename)
	-- try to get from cargo cache
	local result = mw.ext.cargo.query('Imageinfo', 'width, height, cached', {
		-- escape apostrophes in the imagename input
		where = 'image='.. "'"..imagename:gsub("'", "\\'"):gsub("&#39;", "\\'").."'",
		orderBy = "cached DESC",
		limit = 1,
	})
	for _, row in ipairs(result) do
		return tonumber(row['width']), tonumber(row['height']), row['cached']
	end
end

---Store width and height of the specified `imagename` to the Imageinfo cargo table and return them.
---Width and height are computed via the `#imgw:` and `#imgh:` parser functions, respectively.
---@param imagename string
---@return number width
---@return number height
local function storeInfoToCargo(imagename)
	-- don't cache {{item}}'s result when parsing imagesize fails.
	should_cache = false
	local imageTitle = mw.title.new("File:" .. imagename)
	local width, height = imageTitle.file.width, imageTitle.file.height
	if width and width ~= 0 and height and height ~= 0 then
		should_cache = true -- ok, cache it.
		currentFrame:callParserFunction('#cargo_store:_table=Imageinfo',{
			image = imagename,
			width = width,
			height = height,
			cached = os.time(),
		})
	end
	return width, height
end

---Retrieve the dimensions of the specified `image` from the Imageinfo cargo table.
---If it doesn't have any data for the image yet, store it.
---@param imagename string
---@return number width
---@return number height
local function getSizeInfo(imagename)
	local width, height, cached = getInfoFromCargo(imagename)
	-- cache missed, init cache
	if not cached then
		width, height = storeInfoToCargo(imagename)
	end
	if width == 0 then width = nil end
	if height == 0 then height = nil end
	return width, height
end

---Compute the final width and height of the image.
---If necessary, retrieve data from or store data to the Imageinfo cargo table.
---@param imagename string
---@param width number
---@param height number
---@param scale number
---@param maxwidth number
---@param maxheight number
---@return number width
---@return number height
local function getImageSize(imagename, width, height, scale, maxwidth, maxheight)
	-- get size info from image file itself (may be expensive)
	local w, h = getSizeInfo(imagename) -- store data to cache

	-- if width and height are not given as input, but scale/maxwidth/maxheight are, then
	-- set width and height to the original dimensions of the image
	if not width and not height and (scale or maxwidth or maxheight) then
		width, height = w, h
	end

	-- apply scale to width/height if needed
	if scale then
		if width then width = width * scale end
		if height then height = height * scale end
	end

	-- apply maxwidth/maxheight
	if maxwidth then
		if width then
			if width > maxwidth then width = maxwidth end
		else
			if height then width = maxwidth end
		end
	end
	if maxheight then
		if height then
			if height > maxheight then height = maxheight end
		else
			if width then height = maxheight end
		end
	end

	-- round to natural numbers
	if width then width = math.ceil(width) end
	if height then height = math.ceil(height) end

	return width, height
end

---Extract width and height from an input string.
---Example: `6x9px` → `6`, `9`
---@param maxsize string
---@return number maxwidth
---@return number maxheight
local function parseMaxSize(maxsize)
	if not maxsize then return end
	local maxwidth, maxheight = unpack(explode('x', string.gsub(maxsize, 'px', '')))
	maxwidth, maxheight = tonumber(maxwidth), tonumber(maxheight)
	if maxwidth == 0 then maxwidth = nil end
	if maxheight == 0 then maxheight = nil end
	return maxwidth, maxheight
end

---Assemble the final wikicode for an image.
---@param imagename string
---@param link string
---@param text string
---@param size string As accepted by the `[[File:` syntax, e.g. `5x7px*0.75`.
---@param scale number This will be multiplied by the scale in `size`, if necessary.
---@param maxsize string
---@return string
local function imagecode(imagename, link, text, size, scale, maxsize)
	local image_output = '[[File:' .. imagename .. '|link='.. link .. '|' .. text
	if size or scale or maxsize then
		local basescale, width, height = parseSize(size) -- width, height: number or nil (basescale is string!)
		scale = (tonumber(scale) or 1) * (tonumber(basescale) or 1) -- combine the scale parameter and scale from the size parameter
		if scale == 0 or scale == 1 then
			scale = nil
		end
		local maxwidth, maxheight = parseMaxSize(maxsize)
		width, height = getImageSize(imagename, width, height, scale, maxwidth, maxheight) -- can be 0
		if width or height then
			image_output = image_output .. '|' .. (width or '') .. 'x' .. (height or '') .. 'px'
		end
	end
	return image_output .. ']]'
end

---Return the full `[[File:` wikicode for each image in the input (multiple are separated with `/`).
---@param image string
---@param link string
---@param text string
---@param size string
---@param scale string
---@param maxsize string
---@return string
local function images(image, link, text, size, scale, maxsize)

	if not image:find('/') then
		-- there is only one image in the input
		return imagecode(image, link, text, size, scale, maxsize)
	end

	-- there are multiple images in the input, separated with a slash
	image = explode('/', image)
	local result = ''
	if size and size:find('/') then
		-- there are multiple sizes in the size parameter
		size = explode('/', size) -- so turn it into a table
		for i, v in ipairs(image) do -- iterate over the images
			result = result .. imagecode(v, link, text, size[i], scale, maxsize) -- create the wikicode (using the respective size)
		end
	else
		for i, v in ipairs(image) do -- iterate over the images
			result = result .. imagecode(v, link, text, size, scale, maxsize) -- create the wikicode
		end
	end
	return result
end

---Return a string like `Internal Item ID: `, depending on the `_type`.
---@param _type '"item"'|'"tile"'|'"wall"'|'"npc"'|'"mount"'|'"buff"'|'"projectile"'|'"armor"'
---@return string
local function getIdText(_type)
	local id_text
	if _type == 'item' then -- a shortcut for faster
		id_text = l10n('id_text_item')
	elseif _type == 'tile' then
		id_text = l10n('id_text_tile')
	elseif _type == 'wall' then
		id_text = l10n('id_text_wall')
	elseif _type == 'npc' then
		id_text = l10n('id_text_npc')
	elseif _type == 'mount' then
		id_text = l10n('id_text_mount')
	elseif _type == 'buff' or _type == 'debuff' then
		id_text = l10n('id_text_buff')
	elseif _type == 'projectile' then
		id_text = l10n('id_text_projectile')
	elseif _type == 'armor' then
		id_text = l10n('id_text_armor')
	else
		id_text = l10n('id_text_item')
	end
	return id_text
end

-----------------------------------------------------------------
-- main return object
return {

parse = parse,
go = function(frame, args)
	-- cache?
	if not args then
		local cached = cache.get(':_item:' .. frame.args[1])
		if cached then
			return cached
		end
	end

	-- init var cache
	currentFrame = frame
	args_table = args or parse(frame.args[1])
	lang = getArg('lang') or 'en'
	l10n_table = l10n_info[lang] or l10n_info['en']

	local _arg1 = getArg(1) or ''
	local _nolink = getArg('nolink')
	local _link = _nolink and '' or getArg('link') or frame:expandTemplate{ title = 'tr', args = {_arg1, link='y', lang=lang} } -- now: _link == '' means nolink

	local text = getArg(2) or ''

	-- hovertext: {{tr|_arg1}} or text or _link (in that order)
	local hovertext
	if _arg1 ~= '' then
		hovertext = frame:expandTemplate{ title = 'tr', args = {_arg1, lang=lang} }
	elseif text ~= '' then
		hovertext = text
	else
		hovertext = _link
	end

	-- set output flags
	local output_image, output_text, output_table = true, true, false
	local _mode = getArg('mode')
	if _mode then
		if _mode == 'image' or _mode == 'imageonly' or _mode =='onlyimage' then
			output_text = false
		elseif _mode == 'text' or _mode == 'noimage' then
			output_image = false
		elseif _mode == 'table' or _mode == '2-cell' then
			output_table = true
		end
	end

	local class = 'i'

	local image_output, text_output
	-- get wikicode for the image(s)
	if output_image then
		local image_arg = getArg('image')
		if not image_arg then
			if _arg1 == '1/2 Second Timer' then
				image_arg = '1 2 Second Timer'
			elseif _arg1 == '1/4 Second Timer' then
				image_arg = '1 4 Second Timer'
			else
				image_arg = string.gsub(_arg1, ":%s*", " ")
			end
			image_arg = image_arg .. '.' .. (getArg('ext') or 'png')
		end
		if string.find(image_arg, '%[%[[fF]ile:') then
			image_output = '<span class="img">' .. image_arg .. '</span>'
		else
			image_output = images(image_arg, _link, hovertext, getArg('size'), getArg('scale'), getArg('maxsize'))
		end
	else
		image_output = ''
	end
	-- get wikicode for the text
	if output_text then
		local _note, _note2, _showid, _id, _icon = getArg('note'), getArg('note2'), getArg('showid'), getArg('id'), getArg('icons') -- get info from arguments

		-- prepare: display ID?
		if _id and not _showid then
			_showid = true
		end
		if _showid and (_showid == 'n' or _showid == 'no') then
			_showid = false
		end

		-- prepare: wrap?
		local _wrap
		if _showid or _note2 then
			_wrap = false
		else
			_wrap = getArg('wrap')
		end

		-- prepare: link and display text
		if _link ~= '' then
			if text == _link then
				text = '<span>[['..text..']]</span>'
			else
				text = '<span>[['.._link..'|'..text..']]</span>'
			end
		else
			text = '<span title="'..hovertext..'">'..text..'</span>'
		end

		-- prepare: eicons
		local icon = nil
		if _icon == 'n' or _icon == 'no' or _icon == 'off' then
			icon = ''
		else
			icon = eicons(getArg('epage') or _arg1, lang, (_showid or _note2 or _wrap or getArg('small')) and 'y')
		end

		-- assemble HTML code
		local content = text -- item name link text first.
		-- '-w' class means 'wrapmode', optimized for multiple lines of text. But it should be disabled for single line text.
		if _wrap then
			-- eicons in the same line
			if icon ~= '' then
				class = class .. ' -w'
				content = content .. icon
			end
			-- note in a new line
			if _note then
				class = class .. ' -w'
				content = content .. '<span class="note">' .. _note .. '</span>'
			end
		else
			-- note in the same line
			if _note then
				content = content .. '<span class="note">' .. _note .. '</span>'
			end
			-- eicons in the same line
			if icon ~= '' then
				content = content .. icon
			end
			-- note2 in a new line
			if _note2 then
				class = class .. ' -w'
				content = content .. '<div class="note">' .. _note2 .. '</div>'
			end
			-- id in a new line
			if _showid then
				class = class .. ' -w'
				local idtype = (getArg('type') or 'item'):lower()
				if not _id then
					-- get ID automatically via {{itemIdFromName}} or the like
					_id = frame:expandTemplate{ title = idtype .. 'IdFromName', args = {_arg1} }
				end
				local id_text = getIdText(idtype)
				content = content .. '<div class="id">' .. id_text .. _id .. '</div>'
			end
		end
		text_output = '<span>' .. content .. '</span>'
	else
		text_output = ''
	end

	-- handle custom CSS
	local _class, _css = getArg('class'), getArg('css')
	if _class then
		class = class .. ' ' .. _class -- add to existing classes
	end
	local attr = {class = class}
	if _css then
		attr.style = _css -- set the style attribute to parameter value
	end

	local return_string
	if output_table then
		-- table output
		attr.class = class
		local _rowspan = getArg('rowspan')
		local rowspan_text = (_rowspan and (' rowspan=' .. _rowspan) or '')
		-- prepare the two cells
		local first_cell_pre = rowspan_text .. ' class="il1c"'
		local first_cell_content = mw.text.tag('span', attr, image_output)
		local second_cell_pre = rowspan_text .. ' class="il2c"'
		local second_cell_content = mw.text.tag('span', attr, text_output)
		-- combine
		return_string = first_cell_pre .. " | " .. first_cell_content .. " || " .. second_cell_pre .. " | " .. second_cell_content
	else
		-- non-table output (text/image)
		return_string = mw.text.tag('span', attr, image_output .. text_output)
	end

	-- cache output for later reuse
	if not args and should_cache then
		cache.set(':_item:' .. frame.args[1], return_string, 3600*24) -- cache for 24 hours
	end

	-- output
	return return_string

end,

purge = function(frame)
	cache.delete(':_item:' .. frame.args[1]) -- delete that cache key.
end,

storeImageInfo = function(frame)
	currentFrame = frame
	local width, height = storeInfoToCargo(frame.args[1])
	if not width or width == 0 or not height or height == 0 then
		return
	else
		return frame:callParserFunction{name = "#dplvar:set", args = { 
			"_image_exist", "1",
			"_image_width", width,
			"_image_height", height,
		}}
	end
end,

}