Module:Animation
Appearance
This documentation is transcluded from Module:Animation/doc.
Implements Template:Animation.
require( 'strict' )
--- @class AnimationProps
--- @field images string[]
--- @field size string|nil
--- @field width string|nil
--- @field height string|nil
--- @field fps number|nil
--- @field offset table|nil
--- @field offset.top string|nil
--- @field offset.right string|nil
--- @field offset.bottom string|nil
--- @field offset.left string|nil
local p = {}
--- @param props AnimationProps
local function normalizeProps( props )
props.size = props.size or '80px'
props.width = props.width or props.size
props.height = props.height or 'auto'
props.fps = tonumber( props.fps ) or 12
props.offset = props.offset or {}
end
--- Process the wikitext args
---
--- @param args table
--- @return table
local function processArgs( args )
local images = {}
for k, v in pairs( args ) do
if k ~= 'size' and k ~= 'fps' then
images[k] = v
end
end
return {
images = images,
size = args.size,
width = args.width,
height = args.height,
offset = {
top = args.offsetTop,
right = args.offsetRight,
bottom = args.offsetBottom,
left = args.offsetLeft,
},
fps = args.fps,
}
end
--- Determine the frame count based on the images
--- We start from the end because mw.title.file.exists is expensive
---
--- @param images string[]
--- @return number
local function determineFrameCount( images )
for i = #images, 1, -1 do
local title = mw.title.new( images[i], 'File' )
if title and title.file.exists then
return i
end
end
return 0
end
--- @param file string
--- @param size string
--- @return string
local function getFileWikitext( file, size )
-- `link=` is needed make sure the image is not clickable.
return string.format( '[[File:%s|%s|link=]]', file, size )
end
--- @param props AnimationProps
--- @param frameCount number
--- @return mw.html
local function getFramesHtml( props, frameCount )
local html = mw.html.create( 'div' ):addClass( 't-animation-frames' )
for i = 1, frameCount do
local image = props.images[i]
html:tag( 'div' ):addClass( 't-animation-frame' )
:css( '--t-animation-frame-index', tostring( i - 1 ) )
:wikitext( getFileWikitext( image, props.size ) )
:done()
end
return html
end
--- @param props AnimationProps
--- @return string
function p.render( props )
normalizeProps( props )
local frameCount = determineFrameCount( props.images )
local root = mw.html.create( 'div' ):addClass( 't-animation' )
root
:css( '--t-animation-width', props.width )
:css( '--t-animation-height', props.height )
:css( '--t-animation-fps', tostring( props.fps ) )
:css( '--t-animation-frame-count', frameCount )
:css( '--t-animation-offset-top', props.offset.top )
:css( '--t-animation-offset-right', props.offset.right )
:css( '--t-animation-offset-bottom', props.offset.bottom )
:css( '--t-animation-offset-left', props.offset.left )
:node( getFramesHtml( props, frameCount ) )
return mw.getCurrentFrame():extensionTag {
name = 'templatestyles', args = { src = 'Module:Animation/styles.css' }
} .. tostring( root )
end
--- Wikitext entry point for the module
---
--- @param frame mw.frame
--- @return string
function p.main( frame )
local getArgs = require( 'Module:Arguments' ).getArgs
return p.render( processArgs( getArgs( frame ) ) )
end
return p