Module:Sprite: Difference between revisions

Fix mw.html performance issue (basically doubles performance). Fix the css parameter not actually working.
m 91 revisions imported
 
(35 intermediate revisions by 6 users not shown)
Line 7: Line 7:
f = mw.getCurrentFrame()
f = mw.getCurrentFrame()
end
end
local data = args.data and mw.loadData( 'Module:' .. args.data ) or {}
local settings = data.settings
-- Default settings
-- Default settings
Line 18: Line 21:
local defaultStyle = default
local defaultStyle = default
if args.settings then
if settings then
local settings = mw.loadData( 'Module:' .. args.settings )
if not settings.stylesheet then
if not settings.stylesheet then
-- Make a separate clone of the current default settings
-- Make a separate clone of the current default settings
Line 34: Line 36:
local sprite = mw.html.create( 'span' ):addClass( 'sprite' )
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
-- mw.html's css method performs very slow escaping, which doubles the time it takes
Line 41: Line 42:
local styles = {}
local styles = {}
if setting( 'stylesheet' ) then
-- for tint
sprite:addClass(
local classname = setting( 'classname' ) or mw.ustring.lower( setting( 'name' ):gsub( ' ', '-' ) ) .. '-sprite'
setting( 'classname' ) or
local css_image = "background"
mw.ustring.lower( setting( 'name' ):gsub( ' ', '-' ) ) .. '-sprite'
if setting( 'formask' ) then
)
classname = classname .. '-mask'
else
css_image = "mask"
table.insert( styles, 'background-image:{{FileUrl|' .. (
setting( 'image' ) or setting( 'name' ) .. 'Sprite.png'
) .. '}}' )
end
end
sprite:addClass( classname )
local class = setting( 'class' )
local class = setting( 'class' )
if class then
if class then
Line 56: Line 56:
end
end
local size = setting( 'size' )
local width = setting( 'width' ) or setting( 'size' )
local pos = math.abs( setting( 'pos' ) ) - 1
local height = setting( 'height' ) or setting( 'size' )
local sheetWidth = setting( 'sheetsize' )
local sheetWidth = setting( 'sheetsize' )
local tiles = sheetWidth / size
local tiles = sheetWidth / width
local left = pos % tiles * size
local pos = setting( 'pos' ) - 1
local top = math.floor( pos / tiles ) * size
local scale = setting( 'scale' )
local scale = setting( 'scale' )
local autoScale = setting( 'autoscale' )
local autoScale = setting( 'autoscale' )
if left > 0 or top > 0 then
if pos then
table.insert( styles, 'background-position:-' .. left * scale .. 'px -' .. top * scale .. 'px' )
local left = pos % tiles * width * scale
local top = math.floor( pos / tiles ) * height * scale
if css_image == 'mask' then
styles[#styles + 1] = '-webkit-mask-position:-' .. left .. 'px -' .. top .. 'px'
end
styles[#styles + 1] = css_image .. '-position:-' .. left .. 'px -' .. top .. 'px'
end
end
if not autoScale and scale ~= defaultStyle.scale then
if not autoScale and scale ~= defaultStyle.scale then
table.insert( styles, 'background-size:' .. sheetWidth * scale .. 'px auto' )
if css_image == 'mask' then
styles[#styles + 1] = '-webkit-mask-size:' .. sheetWidth * scale .. 'px auto'
end
styles[#styles + 1] = css_image .. '-size:' .. sheetWidth * scale .. 'px auto'
end
end
if size ~= defaultStyle.size or ( not autoScale and scale ~= defaultStyle.scale ) then
if height ~= defaultStyle.size or width ~= defaultStyle.size or ( not autoScale and scale ~= defaultStyle.scale ) then
table.insert( styles, 'height:' .. size * scale .. 'px' )
styles[#styles + 1] = 'height:' .. height * scale .. 'px'
table.insert( styles, 'width:' .. size * scale .. 'px' )
styles[#styles + 1] = 'width:' .. width * scale .. 'px'
end
end
local align = setting( 'align' )
local align = setting( 'align' )
if align ~= defaultStyle.align then
if align ~= defaultStyle.align then
table.insert( styles, 'vertical-align:' .. align )
styles[#styles + 1] = 'vertical-align:' .. align
end
end
table.insert( styles, setting( 'css' ) )
styles[#styles + 1] = setting( 'css' )
sprite:cssText( table.concat( styles, ';' ) )
sprite:cssText( table.concat( styles, ';' ) )
Line 86: Line 96:
local spriteText
local spriteText
if text then
if text then
root = mw.html.create( 'span' ):addClass( 'nowrap' )
if not args['wrap'] then
root = mw.html.create( 'span' ):addClass( 'nowrap' )
end
spriteText = mw.html.create( 'span' ):addClass( 'sprite-text' ):wikitext( text )
spriteText = mw.html.create( 'span' ):addClass( 'sprite-text' ):wikitext( text )
end
end
Line 122: Line 134:
if f == mw.getCurrentFrame() then
if f == mw.getCurrentFrame() then
args = require( 'Module:ProcessArgs' ).merge( true )
args = require( 'Module:ProcessArgs' ).merge( true )
else
f = mw.getCurrentFrame()
end
end
local data = args.data and mw.loadData( 'Module:' .. args.data ) or {}
local categories = {}
local categories = {}
if tonumber( args[1] ) then
local idData = args.iddata
args.pos = args[1]
if not idData then
table.insert( categories, '[[Category:Pages using sprite positions]]' )
local name = args.name or data.settings.name
else
local id = mw.text.trim( tostring( args[1] or '' ) )
local idData = args.iddata
idData = data.ids[id] or data.ids[mw.ustring.lower( id ):gsub( '[%s%+]', '-' )]
if not idData then
end
local default = {}
if args.settings then
local title = mw.title.getCurrentTitle()
default = mw.loadData( 'Module:' .. args.settings )
-- 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 idData.deprecated then
args.class = ( args.class or '' ) .. ' sprite-deprecated'
if not disallowCats then
categories[#categories + 1] = f:expandTemplate{ title = 'Translation category', args = { 'Pages using deprecated sprite names', project = 0 } }
end
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
end
local allowCats = not mw.title.getCurrentTitle().isSubpage
args.pos = idData.pos
if idData then
elseif not disallowCats then
if idData.deprecated and allowCats then
categories[#categories + 1] = f:expandTemplate{ title = 'Translation category', args = { 'Pages with missing sprites', project = 0 } }
table.insert( categories, '[[Category:Pages using deprecated sprite names]]' )
end
args.pos = idData.pos
elseif allowCats then
table.insert( categories, '[[Category:Pages with missing sprites]]' )
end
end
end
return p.base( args ), table.concat( categories, '' )
return p.base( args ), table.concat( categories )
end
end


Line 167: Line 176:
link = args[1]:match( '^(.-)%+' ) or args[1]
link = args[1]:match( '^(.-)%+' ) or args[1]
end
end
local text = args.text or args[2] or link
local text
if not args.notext then
text = args.text or args[2] or link
end
args[1] = args.id or args[1]
args[1] = args.id or args[1]
Line 183: Line 195:
f = mw.getCurrentFrame()
f = mw.getCurrentFrame()
end
end
local settingsPage = mw.text.trim( args[1] )
local dataPage = mw.text.trim( args[1] )
local settings = mw.loadData( 'Module:' .. settingsPage )
local data = mw.loadData( 'Module:' .. dataPage )
local idsPage = 'Module:' .. ( settings.ids or settings.name .. '/IDs' )
local body
local getProtection = function( title, action, extra )
if args.refresh then
local protections = { 'edit' }
body = mw.html.create()
if extra then
else
protections[#protections + 1] = extra
local spriteSheet = settings.image or settings.name .. 'Sprite.png'
end
body = mw.html.create( 'div' ):attr( {
id = 'spritedoc',
local addProtection = function( protection )
['data-idspage'] = '{{PAGEID:' .. idsPage .. '}}',
if protection == 'autoconfirmed' then
['data-idstimestamp'] = '{{REVISIONTIMESTAMP:' .. idsPage .. '}}',
protection = 'editsemiprotected'
['data-spritesheet'] = spriteSheet,
elseif protection == 'sysop' then
['data-pos'] = settings.pos or 1,
protection = 'editprotected'
['data-refreshtext'] = mw.text.nowiki( '{{#invoke:sprite2|doc|' .. settingsPage .. '|refresh=1}}' )
end
} )
protections[#protections + 1] = protection
end
local direct = title.protectionLevels[action] or {}
for _, protection in ipairs( direct ) do
addProtection( protection )
end
local cascading = title.cascadingProtection.restrictions[action] or {}
if #cascading > 0 then
protections[#protections + 1] = 'protect'
end
for _, protection in ipairs( cascading ) do
addProtection( protection )
end
return table.concat( protections, ',' )
end
local spriteStyle = ''
if data.settings.url and data.settings.url.style then
spriteStyle = data.settings.url.style
end
end
local data = mw.loadData( idsPage )
local dataTitle = mw.title.new( 'Module:' .. dataPage )
-- Temporary until this is updated
local spritesheet = data.settings.image or data.settings.name .. 'Sprite.png'
local spriteTitle = mw.title.new( 'File:' .. spritesheet )
local dataProtection = getProtection( dataTitle, 'edit' )
local spriteProtection = getProtection( spriteTitle, 'upload', 'upload,reupload' )
local body = mw.html.create( 'div' ):attr( {
id = 'spritedoc',
['data-dataprotection'] = dataProtection,
['data-datatimestamp'] = f:callParserFunction( 'REVISIONTIMESTAMP', 'Module:' .. dataPage ),
['data-datapage'] = 'Module:' .. dataPage,
['data-spritesheet'] = spritesheet,
['data-spriteprotection'] = spriteProtection,
['data-refreshtext'] = mw.text.nowiki( '{{#invoke:sprite|doc|' .. dataPage .. '|refresh=1}}' ),
['data-settings'] = mw.text.jsonEncode( data.settings ),
} )
local sections = {}
local sections = {}
for _, sectionData in ipairs( data.sections or { 'Uncategorized' } ) do
for _, sectionData in ipairs( data.sections or { name = 'Uncategorized' } ) do
local sectionTag = body:tag( 'div' ):addClass( 'spritedoc-section' ):attr( 'data-section-id', sectionData.id )
local sectionTag = body:tag( 'div' ):addClass( 'spritedoc-section' ):attr( 'data-section-id', sectionData.id )
-- https://phabricator.wikimedia.org/T73594
sectionTag:tag( 'h3' ):wikitext( sectionData.name )
sectionTag:wikitext( '<h3>', sectionData[1], '</h3>' )
sections[sectionData.id] = { boxes = sectionTag:tag( 'ul' ):addClass( 'spritedoc-boxes' ) }
sections[sectionData.id] = { boxes = sectionTag:tag( 'ul' ):addClass( 'spritedoc-boxes' ) }
end
end
local keyedData = {}
local keyedData = {}
local i = 1
for name, idData in pairs( data.ids ) do
for name, idData in pairs( data.ids ) do
table.insert( keyedData, {
keyedData[i] = {
sortKey = mw.ustring.lower( name ),
sortKey = mw.ustring.lower( name ),
name = name,
name = name,
data = idData
data = idData
} )
}
i = i + 1
end
end
table.sort( keyedData, function( a, b )
table.sort( keyedData, function( a, b )
Line 232: Line 280:
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 } )
:wikitext( p.base{ pos = pos, data = dataPage, nourl = spriteStyle ~= '' } )
names = box:tag( 'ul' ):addClass( 'spritedoc-names' )
names = box:tag( 'ul' ):addClass( 'spritedoc-names' )
Line 247: Line 295:
if args.refresh then
if args.refresh then
return '', tostring( body )
return '', '', tostring( body )
end
end
return f:callParserFunction( '#widget:Stylesheet', { page = 'SpriteDoc' } ), tostring( body )
local styles = f:extensionTag( 'templatestyles', '', { src = 'Sprite/doc.css' } )
return styles, spriteStyle, tostring( body )
end
end
return p
return p