local p = {}
local getArgs = require('Module:Arguments').getArgs
local charData = nil
local function getCharData()
if charData then return charData end
local ok, result = pcall(mw.loadJsonData, 'Template:彩虹社/charbox/data')
charData = ok and result or {}
return charData
end
function p._main(args, frame)
local arg1 = args[1] or ''
local arg2 = args[2] or ''
local l = args.l or ''
local i = args.i or ''
local k = args.k or '#fff'
local text = args.text or ''
-- Text mode if |text= is set to anything
local isText = (text ~= '')
local isTextName = (text == 'name')
-- iw: default 30 in text mode, 40 otherwise
local iw = tonumber(args.iw) or (isText and 30 or 40)
-- Look up JSON data by arg1 then arg2
local data = getCharData()
local charEntry = (arg1 ~= '' and data[arg1])
or (arg2 ~= '' and data[arg2])
or {}
-- Resolve image source and sprite params
-- Priority: explicit args > data entry > defaults
local useFile = false -- true = single file image, false = sprite sheet
if i ~= '' then
-- Explicit custom image
useFile = false -- still a sprite sheet with custom file
elseif charEntry.file then
-- Data entry supplies a standalone file
i = charEntry.file
useFile = true
end
local h, n, c
if useFile then
-- Standalone file: no sprite math needed
h = 1
n = 1
c = tonumber(args.c) or 1
else
-- Sprite sheet (default or custom)
h = tonumber(args.h) or tonumber(charEntry.h) or 1
n = tonumber(args.n) or tonumber(charEntry.n) or 1
-- c default: 1 if custom image supplied, 13 for the default sprite
c = tonumber(args.c) or (i ~= '' and 1 or (charEntry.c or 13))
end
-- Link target: l > arg1 > arg2
local linkTarget
if l ~= '' then
linkTarget = l
elseif arg1 ~= '' then
linkTarget = arg1
else
linkTarget = arg2
end
-- Display name for text=name link
local displayName = arg1 ~= '' and arg1 or arg2
-- Outer span style
local outerStyle = string.format(
'display:inline-block;width:%dpx;height:%dpx;overflow:hidden;',
iw, iw
)
if isText then
outerStyle = outerStyle .. string.format(
'background:%s;border-radius:50%%;vertical-align:middle;',
k
)
end
-- Inner span: margin offsets for sprite positioning
local marginTop = (iw + 2) * (1 - h) - 1
local marginLeft = (iw + 2) * (1 - n) - 1
local innerStyle = string.format(
'display:block;pointer-events:none;margin-top:%dpx;margin-left:%dpx;',
marginTop, marginLeft
)
-- Image width
local imgStyleWidth = (iw + 2) * c
-- Resolve sprite filename
local spriteFile
if i ~= '' and not useFile then
spriteFile = i
elseif useFile then
-- Strip "File:" prefix for filepath
spriteFile = i:gsub('^[Ff]ile:', '')
else
-- Default sprite from template
spriteFile = frame:expandTemplate({ title = '彩虹社/sprite' })
spriteFile = mw.text.trim(spriteFile)
end
local filepath = frame:callParserFunction('filepath', spriteFile)
local imgTag = frame:callParserFunction('#img', {
'',
src = filepath,
style = 'width:' .. imgStyleWidth .. 'px',
})
-- Build the icon wikilink content
local iconContent = string.format(
'<span class="image-clip" style="%s"><span style="%s">%s</span></span>',
outerStyle, innerStyle, imgTag
)
local iconLink = '[[' .. linkTarget .. '|' .. iconContent .. ']]'
-- Optional text link after icon (text=name only)
local textLink = ''
if isTextName then
textLink = ' [[' .. linkTarget .. '|' .. displayName .. ']]'
end
return iconLink
.. textLink
end
function p.main(frame)
local args = getArgs(frame, {
parentFirst = true,
})
return p._main(args, frame)
end
return p