Module:Sprite
This module implements {{sprite}}. It should generally be invoked directly on template pages, rather than using the sprite template.
Parent arguments are automatically merged with directly passed arguments (the latter overwriting the former) and all arguments are normalised to trim whitespace and set empty arguments to nil
.
Dependencies
See also
- {{Sprite}}
- {{BiomeSprite}}
- {{BlockSprite}}
- {{CommentSprite}}
- {{EffectSprite}}
- {{EntitySprite}}
- {{EnvSprite}}
- {{ItemSprite}}
- {{SchematicSprite}}
- Module:Sprite
The above documentation is transcluded from Module:Sprite/doc. (edit | history)
local p = {}
function p.base( f )
local args = f
if f == mw.getCurrentFrame() then
args = require( 'Module:ProcessArgs' ).merge( true )
else
f = mw.getCurrentFrame()
end
-- Default settings
local default = {
scale = 1,
sheetsize = 256,
size = 16,
pos = 1,
align = 'text-top'
}
local defaultStyle = default
if args.settings then
local settings = mw.loadData( 'Module:' .. args.settings )
if not settings.stylesheet then
-- Make a separate clone of the current default settings
defaultStyle = mw.clone( default )
end
for k, v in pairs( settings ) do
default[k] = v
end
end
local setting = function( arg )
return args[arg] or default[arg]
end
local sprite = mw.html.create( 'span' ):addClass( 'sprite' )
sprite:tag( 'br' )
-- mw.html's css method performs very slow escaping, which doubles the time it takes
-- to run, so we'll construct the styles manually, and put them in the cssText
-- method, which only does html escaping (which isn't slow)
local styles = {}
if setting( 'stylesheet' ) then
sprite:addClass(
setting( 'classname' ) or
mw.ustring.lower( setting( 'name' ):gsub( ' ', '-' ) ) .. '-sprite'
)
else
table.insert( styles, 'background-image:{{FileUrl|' .. (
setting( 'image' ) or setting( 'name' ) .. 'Sprite.png'
) .. '}}' )
end
local class = setting( 'class' )
if class then
sprite:addClass( class )
end
local size = setting( 'size' )
local pos = math.abs( setting( 'pos' ) ) - 1
local sheetWidth = setting( 'sheetsize' )
local tiles = sheetWidth / size
local left = pos % tiles * size
local top = math.floor( pos / tiles ) * size
local scale = setting( 'scale' )
local autoScale = setting( 'autoscale' )
if left > 0 or top > 0 then
table.insert( styles, 'background-position:-' .. left * scale .. 'px -' .. top * scale .. 'px' )
end
if not autoScale and scale ~= defaultStyle.scale then
table.insert( styles, 'background-size:' .. sheetWidth * scale .. 'px auto' )
end
if size ~= defaultStyle.size or ( not autoScale and scale ~= defaultStyle.scale ) then
table.insert( styles, 'height:' .. size * scale .. 'px' )
table.insert( styles, 'width:' .. size * scale .. 'px' )
end
local align = setting( 'align' )
if align ~= defaultStyle.align then
table.insert( styles, 'vertical-align:' .. align )
end
table.insert( styles, setting( 'css' ) )
sprite:cssText( table.concat( styles, ';' ) )
local text = setting( 'text' )
local root
local spriteText
if text then
root = mw.html.create( 'span' ):addClass( 'nowrap' )
spriteText = mw.html.create( 'span' ):addClass( 'sprite-text' ):wikitext( text )
end
local title = setting( 'title' )
if title then
( root or sprite ):attr( 'title', title )
end
if not root then
root = mw.html.create( '' )
end
root:node( sprite )
if spriteText then
root:node( spriteText )
end
local link = setting( 'link' ) or ''
if link ~= '' and mw.ustring.lower( link ) ~= 'none' then
-- External link
if link:find( '//' ) then
return '[' .. link .. ' ' .. tostring( root ) .. ']'
end
-- Internal link
local linkPrefix = setting( 'linkprefix' ) or ''
return '[[' .. linkPrefix .. link .. '|' .. tostring( root ) .. ']]'
end
return tostring( root )
end
function p.sprite( f )
local args = f
if f == mw.getCurrentFrame() then
args = require( 'Module:ProcessArgs' ).merge( true )
else
f = mw.getCurrentFrame()
end
local categories = {}
local idData = args.iddata
if not idData then
local default = {}
if args.settings then
default = mw.loadData( 'Module:' .. args.settings )
end
local name = args.name or default.name
local ids = mw.loadData( 'Module:' .. ( args.ids or default.ids or name .. '/IDs' ) )
ids = ids.ids or ids
local id = mw.text.trim( tostring( args[1] or '' ) )
idData = ids[id] or ids[mw.ustring.lower( id ):gsub( '[%s%+]', '-' )]
end
local title = mw.title.getCurrentTitle()
-- Remove categories on language pages, talk pages, and in User/UserWiki/UserProfile namespaces
local disallowCats = args.nocat or title.isTalkPage or title.nsText:find( '^User' )
if idData then
if type( idData ) == 'table' then
if idData.deprecated and not disallowCats then
table.insert( categories, f:expandTemplate{ title = 'Translation category', args = { 'Pages using deprecated sprite names', project = 0 } } )
end
args.pos = idData.pos
else
args.pos = idData
end
elseif not disallowCats then
table.insert( categories, f:expandTemplate{ title = 'Translation category', args = { 'Pages with missing sprites', project = 0 } } )
end
return p.base( args ), table.concat( categories, '' )
end
function p.link( f )
local args = f
if f == mw.getCurrentFrame() then
args = require( 'Module:ProcessArgs' ).merge( true )
end
local link = args[1]
if args[1] and not args.id then
link = args[1]:match( '^(.-)%+' ) or args[1]
end
local text = args.text or args[2] or link
args[1] = args.id or args[1]
args.link = args.link or link
args.text = text
return p.sprite( args )
end
function p.doc( f )
local args = f
if f == mw.getCurrentFrame() then
args = f.args
else
f = mw.getCurrentFrame()
end
local settingsPage = mw.text.trim( args[1] )
local settings = mw.loadData( 'Module:' .. settingsPage )
local idsPage = 'Module:' .. ( settings.ids or settings.name .. '/IDs' )
local getProtection = function( title, action, extra )
local protections = { 'edit' }
if extra then
table.insert( protections, extra )
end
local addProtection = function( protection )
if protection == 'autoconfirmed' then
protection = 'editsemiprotected'
elseif protection == 'sysop' then
protection = 'editprotected'
end
table.insert( protections, protection )
end
local direct = title.protectionLevels[action]
for _, protection in ipairs( direct ) do
addProtection( protection )
end
local cascading = title.cascadingProtection.restrictions[action] or {}
if #cascading > 0 then
table.insert( protections, 'protect' )
end
for _, protection in ipairs( cascading ) do
addProtection( protection )
end
return table.concat( protections, ',' )
end
local body
if args.refresh then
body = mw.html.create( '' )
else
local idsTitle = mw.title.new( idsPage )
local spritesheet = settings.image or settings.name .. 'Sprite.png'
local spriteTitle = mw.title.new( 'File:' .. spritesheet )
local idsProtection = getProtection( idsTitle, 'edit' )
local spriteProtection = getProtection( spriteTitle, 'upload', 'upload,reupload' )
body = mw.html.create( 'div' ):attr( {
id = 'spritedoc',
['data-idspage'] = idsTitle.id,
['data-idsprotection'] = idsProtection,
['data-idstimestamp'] = f:callParserFunction( 'REVISIONTIMESTAMP', idsPage ),
['data-spritesheet'] = spritesheet,
['data-spriteprotection'] = spriteProtection,
['data-pos'] = settings.pos or 1,
['data-refreshtext'] = mw.text.nowiki( '{{#invoke:sprite|doc|' .. settingsPage .. '|refresh=1}}' )
} )
end
local data = mw.loadData( idsPage )
local sections = {}
for _, sectionData in ipairs( data.sections or { 'Uncategorized' } ) do
local sectionTag = body:tag( 'div' ):addClass( 'spritedoc-section' ):attr( 'data-section-id', sectionData.id )
-- https://phabricator.wikimedia.org/T73594
sectionTag:wikitext( '<h3>', sectionData[1], '</h3>' )
sections[sectionData.id] = { boxes = sectionTag:tag( 'ul' ):addClass( 'spritedoc-boxes' ) }
end
local keyedData = {}
for name, idData in pairs( data.ids ) do
table.insert( keyedData, {
sortKey = mw.ustring.lower( name ),
name = name,
data = idData
} )
end
table.sort( keyedData, function( a, b )
return a.sortKey < b.sortKey
end )
for _, data in ipairs( keyedData ) do
local idData = data.data
local pos = idData.pos
local section = sections[idData.section]
local names = section[pos]
if not names then
local box = section.boxes:tag( 'li' ):addClass( 'spritedoc-box' ):attr( 'data-pos', pos )
box:tag( 'div' ):addClass( 'spritedoc-image' )
:wikitext( p.base{ pos = pos, settings = settingsPage } )
names = box:tag( 'ul' ):addClass( 'spritedoc-names' )
section[pos] = names
end
local nameElem = mw.html.create( 'li' ):addClass( 'spritedoc-name' )
local codeElem = nameElem:tag( 'code' ):wikitext( data.name )
if idData.deprecated then
codeElem:addClass( 'spritedoc-deprecated' )
end
names:wikitext( tostring( nameElem ) )
end
if args.refresh then
return '', tostring( body )
end
return f:callParserFunction( '#widget:Stylesheet', { page = 'SpriteDoc' } ), tostring( body )
end
return p