Module:Sprite: Difference between revisions
Jump to navigation
Jump to search
Improve speed by only lowercasing each name once |
mw.html seems to use a lot of memory. Converting elements to wikitext string where possible before inserting them into an existing HtmlBuilder significantly reduces that memory usage for some reason, even though that just happens later anyway on output. |
||
Line 104: | Line 104: | ||
end | end | ||
return root | return tostring( root ) | ||
end | end | ||
Line 221: | Line 221: | ||
local box = section.boxes:tag( 'li' ):addClass( 'spritedoc-box' ):attr( 'data-pos', pos ) | local box = section.boxes:tag( 'li' ):addClass( 'spritedoc-box' ):attr( 'data-pos', pos ) | ||
box:tag( 'div' ):addClass( 'spritedoc-image' ) | box:tag( 'div' ):addClass( 'spritedoc-image' ) | ||
: | :wikitext( p.base{ pos = pos, settings = settingsPage } ) | ||
names = box:tag( 'ul' ):addClass( 'spritedoc-names' ) | names = box:tag( 'ul' ):addClass( 'spritedoc-names' ) | ||
section[pos] = names | section[pos] = names | ||
end | end | ||
local | local nameElem = mw.html.create( 'li' ):addClass( 'spritedoc-name' ) | ||
local codeElem = nameElem:tag( 'code' ):wikitext( data.name ) | |||
if idData.deprecated then | if idData.deprecated then | ||
codeElem:addClass( 'spritedoc-deprecated' ) | codeElem:addClass( 'spritedoc-deprecated' ) | ||
end | end | ||
names:wikitext( tostring( nameElem ) ) | |||
end | end | ||
Line 238: | Line 238: | ||
return tostring( body ) | return tostring( body ) | ||
end | end | ||
return f:callParserFunction( '#widget:Stylesheet', { page = 'SpriteDoc' } ) | return f:callParserFunction( '#widget:Stylesheet', { page = 'SpriteDoc' } ), tostring( body ) | ||
end | end | ||
return p | return p |
Revision as of 06:17, 17 August 2015
Documentation for this module may be created at Module:Sprite/doc
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' )
if setting( 'stylesheet' ) then
sprite:addClass(
setting( 'classname' ) or
mw.ustring.lower( setting( 'name' ):gsub( ' ', '-' ) ) .. '-sprite'
)
else
sprite:css(
'background-image',
'{{FileUrl|' .. ( setting( 'image' ) or setting( 'name' ) .. 'Sprite.png' ) .. '}}'
)
end
if setting( 'class' ) then
sprite:addClass( setting( 'class' ) )
end
local size = setting( 'size' )
local pos = math.abs( setting( 'pos' ) ) - 1
local tiles = setting( 'sheetsize' ) / size
local left = pos % tiles * size
local top = math.floor( pos / tiles ) * size
local scale = setting( 'scale' )
if left > 0 or top > 0 then
sprite:css( 'background-position', '-' .. left * scale .. 'px -' .. top * scale .. 'px' )
end
if not setting( 'autoscale' ) and scale ~= defaultStyle.scale then
sprite:css( 'background-size', setting( 'sheetsize' ) * scale .. 'px auto' )
end
if size ~= defaultStyle.size or ( not setting( 'autoscale' ) and scale ~= defaultStyle.scale ) then
sprite:css( 'height', size * scale .. 'px;width:' .. size * scale .. 'px' )
end
if setting( 'align' ) ~= defaultStyle.align then
sprite:css( 'vertical-align', setting( 'align' ) )
end
if css then
sprite:cssText( css )
end
local root
local spriteText
if setting( 'text' ) then
root = mw.html.create( 'span' ):addClass( 'nowrap' )
spriteText = mw.html.create( 'span' ):addClass( 'sprite-text' ):wikitext( setting( 'text' ) )
end
if setting( 'title' ) then
( root or sprite ):attr( 'title', setting( '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' )
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 )
end
local categories = {}
if tonumber( args[1] ) then
args.pos = args[1]
table.insert( categories, '[[Category:Pages using sprite positions]]' )
else
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
local id = mw.text.trim( args[1] or '' )
idData = ids[id] or ids[mw.ustring.lower( id ):gsub( '[%s%+]', '-' )]
end
local allowCats = not mw.title.getCurrentTitle().isSubpage
if not idData and allowCats then
table.insert( categories, '[[Category:Pages with missing sprites]]' )
else
if idData.deprecated and allowCats then
table.insert( categories, '[[Category:Pages using deprecated sprite names]]' )
end
args.pos = idData.pos
end
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 body
if args.refresh then
body = mw.html.create()
else
local spriteSheet = settings.image or settings.name .. 'Sprite.png'
body = mw.html.create( 'div' ):attr( {
id = 'spritedoc',
['data-idspage'] = '{{PAGEID:' .. idsPage .. '}}',
['data-idstimestamp'] = '{{REVISIONTIMESTAMP:' .. idsPage .. '}}',
['data-spritesheet'] = spriteSheet,
['data-pos'] = settings.pos or 1,
['data-refreshtext'] = mw.text.nowiki( '{{#invoke:sprite2|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