Minecraft Wiki
Registrarse
m (Se ha deshecho la revisión 102125 de Magiczocker (disc.))
Etiqueta: Deshacer
Sawyerar (discusión | contribs.)
Sin resumen de edición
Línea 3: Línea 3:
 
local args = f
 
local args = f
 
if f == mw.getCurrentFrame() then
 
if f == mw.getCurrentFrame() then
args = require( 'Módulo: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 settings = data.settings
 
 
 
-- Default settings
 
-- Default settings
Línea 12: Línea 17:
 
size = 16,
 
size = 16,
 
pos = 1,
 
pos = 1,
link = '',
+
align = 'text-top'
align = 'text-top',
 
class = '',
 
text = '',
 
title = ''
 
 
}
 
}
 
 
local defaultStyle = mw.clone( default )
+
local defaultStyle = default
if args.settings then
+
if settings then
  +
if not settings.stylesheet then
local settings = mw.loadData( 'Módulo:' .. args.settings )
 
  +
-- Make a separate clone of the current default settings
  +
defaultStyle = mw.clone( default )
  +
end
 
for k, v in pairs( settings ) do
 
for k, v in pairs( settings ) do
 
default[k] = v
 
default[k] = v
if settings.stylesheet then
 
defaultStyle[k] = v
 
end
 
 
end
 
end
 
end
 
end
 
 
local name = args.name or default.name
+
local setting = function( arg )
local scale = args.scale or default.scale
+
return args[arg] or default[arg]
  +
end
local autoScale = args.autoscale or default.autoscale
 
local sheetWidth = args.sheetsize or default.sheetsize
 
local size = args.size or default.size
 
local pos = math.abs( args.pos or default.pos ) - 1
 
local link = args.link or default.link
 
local align = args.align or default.align
 
local class = args.class or default.class
 
local text = args.text or default.text
 
local title = args.title or default.title
 
local css = args.css or default.css
 
local className = args.classname or default.classname
 
 
local tiles = sheetWidth / size
 
local left = pos % tiles * size
 
local top = math.floor( pos / tiles ) * size
 
 
 
  +
local sprite = mw.html.create( 'span' ):addClass( 'sprite' )
  +
  +
-- 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 = {}
 
local styles = {}
  +
if args.stylesheet or default.stylesheet then
 
  +
if not setting( 'nourl' ) and setting( 'url' ) then
class = ( className or mw.ustring.lower( name:gsub( ' ', '-' ) ) .. '-sprite ' ) .. class
 
  +
styles[#styles + 1] = 'background-image:' .. ( setting( 'url' ).url or setting( 'url' ) )
else
 
table.insert( styles, 'background-image:{{FileUrl|' .. ( args.image or default.image or name .. 'Sprite.png' ) .. '}}' )
 
 
end
 
end
if left > 0 or top > 0 then
+
if setting( 'stylesheet' ) then
  +
sprite:addClass(
table.insert( styles, 'background-position:-' .. left * scale .. 'px -' .. top * scale .. 'px' )
 
  +
setting( 'classname' ) or
  +
mw.ustring.lower( setting( 'name' ):gsub( ' ', '-' ) ) .. '-sprite'
  +
)
  +
elseif not setting( 'url' ) then
  +
styles[#styles + 1] = 'background-image:' .. p.getUrl(
  +
setting( 'image' ) or setting( 'name' ) .. 'Sprite.png'
  +
).url
 
end
 
end
  +
local class = setting( 'class' )
  +
if class then
  +
sprite:addClass( class )
  +
end
  +
  +
local size = setting( 'size' )
  +
local sheetWidth = setting( 'sheetsize' )
  +
local tiles = sheetWidth / size
  +
local pos = setting( 'pos' ) - 1
  +
local scale = setting( 'scale' )
  +
local autoScale = setting( 'autoscale' )
  +
  +
if pos then
  +
local left = pos % tiles * size * scale
  +
local top = math.floor( pos / tiles ) * size * scale
  +
styles[#styles + 1] = 'background-position:-' .. left .. 'px -' .. top .. 'px'
  +
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' )
+
styles[#styles + 1] = 'background-size:' .. sheetWidth * scale .. 'px auto'
 
end
 
end
 
if size ~= defaultStyle.size or ( not autoScale and scale ~= defaultStyle.scale ) then
 
if size ~= defaultStyle.size or ( not autoScale and scale ~= defaultStyle.scale ) then
table.insert( styles, 'height:' .. size * scale .. 'px;width:' .. size * scale .. 'px' )
+
styles[#styles + 1] = 'height:' .. size * scale .. 'px'
  +
styles[#styles + 1] = 'width:' .. size * scale .. 'px'
 
end
 
end
  +
  +
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
  +
styles[#styles + 1] = setting( 'css' )
if css then
 
  +
table.insert( styles, css )
 
  +
sprite:cssText( table.concat( styles, ';' ) )
end
 
  +
if title ~= '' then
 
  +
local text = setting( 'text' )
title = ' title="' .. title .. '"'
 
  +
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
 
end
 
 
local sprite = table.concat( {
+
local title = setting( 'title' )
  +
if title then
'<span',
 
  +
( root or sprite ):attr( 'title', title )
'class="sprite ' .. class .. '"',
 
  +
end
'style="' .. table.concat( styles, ';' ) .. '"',
 
title,
 
'><br></span>'
 
}, ' ' )
 
sprite = sprite:gsub( '%s+([">])', '%1' )
 
 
 
if text ~= '' then
+
if not root then
  +
root = mw.html.create( '' )
text = '<span class="sprite-text nowrap"' .. title .. '>' .. text .. '</span>'
 
  +
end
  +
root:node( sprite )
  +
if spriteText then
  +
root:node( spriteText )
 
end
 
end
 
 
if link ~= '' then
+
local link = setting( 'link' ) or ''
  +
if link ~= '' and mw.ustring.lower( link ) ~= 'none' then
  +
-- External link
 
if link:find( '//' ) then
 
if link:find( '//' ) then
  +
return '[' .. link .. ' ' .. tostring( root ) .. ']'
-- External link
 
return '[' .. link .. ' ' .. sprite .. text .. ']'
 
else
 
-- Internal link
 
local linkPrefix = args.linkprefix or default.linkprefix or ''
 
return '[[' .. linkPrefix .. link .. '|' .. sprite .. text .. ']]'
 
 
end
 
end
  +
else
 
  +
-- Internal link
return sprite .. text
 
  +
local linkPrefix = setting( 'linkprefix' ) or ''
  +
return '[[' .. linkPrefix .. link .. '|' .. tostring( root ) .. ']]'
 
end
 
end
  +
  +
return tostring( root )
 
end
 
end
   
Línea 103: Línea 128:
 
local args = f
 
local args = f
 
if f == mw.getCurrentFrame() then
 
if f == mw.getCurrentFrame() then
args = require( 'Módulo: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 category = ''
 
  +
local categories = {}
if tonumber( args[1] ) then
 
args.pos = args[1]
+
local idData = args.iddata
  +
if not idData then
else
 
local default = {}
+
local name = args.name or data.settings.name
  +
local id = mw.text.trim( tostring( args[1] or '' ) )
if args.settings then
 
  +
idData = data.ids[id] or data.ids[mw.ustring.lower( id ):gsub( '[%s%+]', '-' )]
default = mw.loadData( 'Módulo:' .. args.settings )
 
  +
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 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
 
end
 
 
local name = args.name or default.name
+
args.pos = idData.pos
  +
elseif not disallowCats then
local ids = mw.loadData( 'Módulo:' .. ( args.ids or default.ids or 'Sprite/' .. name ) )
 
  +
categories[#categories + 1] = f:expandTemplate{ title = 'Translation category', args = { 'Pages with missing sprites', project = 0 } }
local id = mw.text.trim( args[1] or '' )
 
local pos = ids[id] or ids[mw.ustring.lower( id ):gsub( '[%s%+]', '-' )]
 
if not pos and not mw.title.getCurrentTitle().isSubpage then
 
category = '[[Categoría:Páginas con sprite ausente]]'
 
end
 
args.pos = pos
 
 
end
 
end
 
 
return p.base( args ) .. category
+
return p.base( args ), table.concat( categories )
 
end
 
end
   
Línea 131: Línea 164:
 
local args = f
 
local args = f
 
if f == mw.getCurrentFrame() then
 
if f == mw.getCurrentFrame() then
args = require( 'Módulo:ProcessArgs' ).merge( true )
+
args = require( 'Module:ProcessArgs' ).merge( true )
 
end
 
end
 
 
Línea 138: Línea 171:
 
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]
args.link = link
+
args.link = args.link or link
 
args.text = text
 
args.text = text
 
 
 
return p.sprite( args )
 
return p.sprite( args )
  +
end
  +
  +
function p.getUrl( image, query, classname )
  +
local f = mw.getCurrentFrame()
  +
local t = {
  +
url = f:expandTemplate{
  +
title = 'FileUrl',
  +
args = { image, query = query }
  +
},
  +
}
  +
if classname and classname ~= '' then
  +
t.style = f:expandTemplate{
  +
title = 'FileUrlStyle',
  +
args = { classname, image, query = query }
  +
}
  +
end
  +
return t
  +
end
  +
  +
function p.getParsedUrlStyle( f )
  +
local args = f:getParent().args
  +
local module = args[1]
  +
return require( 'Module:' .. module ).settings.url.style
 
end
 
end
   
 
function p.doc( f )
 
function p.doc( f )
  +
local args = f
local settings = mw.loadData( 'Módulo:' .. f.args[1] )
 
  +
if f == mw.getCurrentFrame() then
local idTable = mw.title.new( 'Módulo:' .. ( settings.ids or 'Sprite/' .. settings.name ) ):getContent()
 
  +
args = f.args
idTable = idTable:gsub( '(\n%s*%-%-%s*.-%s*%-%-%s*\n)', '%1,' ):gsub( '^return {', '' ):gsub( '}$', '' )
 
  +
else
  +
f = mw.getCurrentFrame()
  +
end
  +
local dataPage = mw.text.trim( args[1] )
  +
local data = mw.loadData( 'Module:' .. dataPage )
 
 
  +
local getProtection = function( title, action, extra )
local html = {}
 
local ids = {}
+
local protections = { 'edit' }
  +
if extra then
local posKeys = {}
 
  +
protections[#protections + 1] = extra
local section = ''
 
  +
end
for line in mw.text.gsplit( idTable, ',' ) do
 
line = mw.text.trim( line )
 
id = line:match( '^%[[\'"](.+)[\'"]%]' ) or line:match( '^%w+' ) or ''
 
pos = line:match( '=%s*(%d+)%s*,?$' ) or ''
 
section = line:match( '^%-%-%s*(.+)%s*%-%-$' ) or section
 
 
 
  +
local addProtection = function( protection )
if id ~= '' and pos ~= '' then
 
if ids[pos] then
+
if protection == 'autoconfirmed' then
  +
protection = 'editsemiprotected'
if type( ids[pos].id ) == 'table' then
 
  +
elseif protection == 'sysop' then
table.insert( ids[pos].id, id )
 
  +
protection = 'editprotected'
else
 
ids[pos].id = { ids[pos].id, id }
 
end
 
else
 
ids[pos] = { id = id, section = section }
 
table.insert( posKeys, pos )
 
 
end
 
end
  +
  +
protections[#protections + 1] = protection
 
end
 
end
end
 
 
 
local list = {}
+
local direct = title.protectionLevels[action] or {}
  +
for _, protection in ipairs( direct ) do
local listHead = '<ul class="spritedoc-multicolumn">'
 
  +
addProtection( protection )
local listFoot = '</ul>'
 
local lastSection = ''
 
for i, pos in ipairs( posKeys ) do
 
local id = ids[pos].id
 
local newSection = mw.text.trim( ids[pos].section )
 
 
if newSection ~= lastSection or i == 1 then
 
if newSection ~= lastSection then
 
if lastSection ~= '' then
 
table.insert( list, listFoot )
 
end
 
 
table.insert( list, '\n===' .. newSection .. '===\n' )
 
lastSection = newSection
 
end
 
table.insert( list, listHead )
 
 
end
 
end
  +
local cascading = title.cascadingProtection.restrictions[action] or {}
table.insert( list, '<li><table><tr><td data-pos="' .. pos .. '">' )
 
if type( id ) == 'table' then
+
if #cascading > 0 then
  +
protections[#protections + 1] = 'protect'
for i, id2 in ipairs( id ) do
 
if i == 1 then
 
table.insert( list, p.sprite{ id2, settings = f.args[1] } .. '</td><td><div class="sprite-id"><code>' .. id2 .. '</code></div>' )
 
else
 
table.insert( list, '<div class="sprite-id"><code>' .. id2 .. '</code></div>' )
 
end
 
end
 
else
 
table.insert( list, p.sprite{ id, settings = f.args[1] } .. '</td><td><div class="sprite-id"><code>' .. id .. '</code></div>' )
 
 
end
 
end
  +
for _, protection in ipairs( cascading ) do
table.insert( list, '</td></tr></table></li>' )
 
  +
addProtection( protection )
 
if i == #posKeys then
 
table.insert( list, listFoot )
 
 
end
 
end
  +
  +
return table.concat( protections, ',' )
 
end
 
end
 
 
local out = table.concat( list )
+
local spriteStyle = ''
if not f.args.refresh then
+
if data.settings.url and data.settings.url.style then
  +
spriteStyle = data.settings.url.style
out = f:preprocess( '{{#widget:stylesheet|page=Sprite doc}}' ) .. '<div id="sprite-doc" data-settings="' .. f.args[1] .. '">' .. out .. '</div>'
 
 
end
 
end
 
 
  +
local dataTitle = mw.title.new( 'Module:' .. dataPage )
return out
 
  +
-- Temporary until this is updated
  +
local classname = ''
  +
if data.settings.stylesheet then
  +
classname = data.settings.classname or
  +
mw.ustring.lower( data.settings.name:gsub( ' ', '-' ) ) .. '-sprite'
  +
end
  +
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-urlfunc'] = "require( [[Module:Sprite]] ).getUrl( '" .. spritesheet .. "', '$1', '" .. classname .. "' )",
  +
['data-refreshtext'] = mw.text.nowiki( '{{#invoke:sprite|doc|' .. dataPage .. '|refresh=1}}' ),
  +
['data-settings'] = mw.text.jsonEncode( data.settings ),
  +
} )
  +
  +
local sections = {}
  +
for _, sectionData in ipairs( data.sections or { name = 'Uncategorized' } ) do
  +
local sectionTag = body:tag( 'div' ):addClass( 'spritedoc-section' ):attr( 'data-section-id', sectionData.id )
  +
sectionTag:tag( 'h3' ):wikitext( sectionData.name )
  +
sections[sectionData.id] = { boxes = sectionTag:tag( 'ul' ):addClass( 'spritedoc-boxes' ) }
  +
end
  +
  +
local keyedData = {}
  +
local i = 1
  +
for name, idData in pairs( data.ids ) do
  +
keyedData[i] = {
  +
sortKey = mw.ustring.lower( name ),
  +
name = name,
  +
data = idData
  +
}
  +
i = i + 1
  +
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, data = dataPage, nourl = spriteStyle ~= '' } )
  +
  +
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
  +
local styles = f:callParserFunction( '#widget:SpriteDoc.css' )
  +
return styles, spriteStyle, tostring( body )
 
end
 
end
 
return p
 
return p

Revisión del 23:20 14 oct 2019

[Ver | Editar | Purgar]DocumentaciónVer código ↴

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

Minecraft
Minecraft (legacy)
Minecraft Dungeons
Otras
[Ver | Editar | Purgar]La documentación arriba es transcluída desde Módulo: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
	
	local data = args.data and mw.loadData( 'Module:' .. args.data ) or {}
	local settings = data.settings
	
	-- Default settings
	local default = {
		scale = 1,
		sheetsize = 256,
		size = 16,
		pos = 1,
		align = 'text-top'
	}
	
	local defaultStyle = default
	if settings then
		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' )
	
	-- 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 not setting( 'nourl' ) and setting( 'url' ) then
		styles[#styles + 1] = 'background-image:' .. ( setting( 'url' ).url or setting( 'url' ) )
	end
	if setting( 'stylesheet' ) then
		sprite:addClass(
			setting( 'classname' ) or
			mw.ustring.lower( setting( 'name' ):gsub( ' ', '-' ) ) .. '-sprite'
		)
	elseif not setting( 'url' ) then
		styles[#styles + 1] = 'background-image:' .. p.getUrl(
			setting( 'image' ) or setting( 'name' ) .. 'Sprite.png'
		).url
	end
	local class = setting( 'class' )
	if class then
		sprite:addClass( class )
	end
	
	local size = setting( 'size' )
	local sheetWidth = setting( 'sheetsize' )
	local tiles = sheetWidth / size
	local pos = setting( 'pos' ) - 1
	local scale = setting( 'scale' )
	local autoScale = setting( 'autoscale' )
	
	if pos then
		local left = pos % tiles * size * scale
		local top = math.floor( pos / tiles ) * size * scale
		styles[#styles + 1] = 'background-position:-' .. left .. 'px -' .. top .. 'px'
	end
	
	if not autoScale and scale ~= defaultStyle.scale then
		styles[#styles + 1] = 'background-size:' .. sheetWidth * scale .. 'px auto'
	end
	if size ~= defaultStyle.size or ( not autoScale and scale ~= defaultStyle.scale ) then
		styles[#styles + 1] = 'height:' .. size * scale .. 'px'
		styles[#styles + 1] = 'width:' .. size * scale .. 'px'
	end
	
	local align = setting( 'align' )
	if align ~= defaultStyle.align then
		styles[#styles + 1] = 'vertical-align:' .. align
	end
	styles[#styles + 1] = 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 data = args.data and mw.loadData( 'Module:' .. args.data ) or {}
	local categories = {}
	local idData = args.iddata
	if not idData then
		local name = args.name or data.settings.name
		local id = mw.text.trim( tostring( args[1] or '' ) )
		idData = data.ids[id] or data.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 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
		
		args.pos = idData.pos
	elseif not disallowCats then
		categories[#categories + 1] = 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
	if not args.notext then
		text = args.text or args[2] or link
	end
	
	args[1] = args.id or args[1]
	args.link = args.link or link
	args.text = text
	
	return p.sprite( args )
end

function p.getUrl( image, query, classname )
	local f = mw.getCurrentFrame()
	local t = {
		url = f:expandTemplate{
			title = 'FileUrl',
			args = { image, query = query }
		},
	}
	if classname and classname ~= '' then
		t.style = f:expandTemplate{
			title = 'FileUrlStyle',
			args = { classname, image, query = query }
		}
	end
	return t
end

function p.getParsedUrlStyle( f )
	local args = f:getParent().args
	local module = args[1]
	return require( 'Module:' .. module ).settings.url.style
end

function p.doc( f )
	local args = f
	if f == mw.getCurrentFrame() then
		args = f.args
	else
		f = mw.getCurrentFrame()
	end
	local dataPage = mw.text.trim( args[1] )
	local data = mw.loadData( 'Module:' .. dataPage )
	
	local getProtection = function( title, action, extra )
		local protections = { 'edit' }
		if extra then
			protections[#protections + 1] = extra
		end
		
		local addProtection = function( protection )
			if protection == 'autoconfirmed' then
				protection = 'editsemiprotected'
			elseif protection == 'sysop' then
				protection = 'editprotected'
			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
	
	local dataTitle = mw.title.new( 'Module:' .. dataPage )
	-- Temporary until this is updated
	local classname = ''
	if data.settings.stylesheet then
		classname = data.settings.classname or
			mw.ustring.lower( data.settings.name:gsub( ' ', '-' ) ) .. '-sprite'
	end
	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-urlfunc'] = "require( [[Module:Sprite]] ).getUrl( '" .. spritesheet .. "', '$1', '" .. classname .. "' )",
		['data-refreshtext'] = mw.text.nowiki( '{{#invoke:sprite|doc|' .. dataPage .. '|refresh=1}}' ),
		['data-settings'] = mw.text.jsonEncode( data.settings ),
	} )
	
	local sections = {}
	for _, sectionData in ipairs( data.sections or { name = 'Uncategorized' } ) do
		local sectionTag = body:tag( 'div' ):addClass( 'spritedoc-section' ):attr( 'data-section-id', sectionData.id )
		sectionTag:tag( 'h3' ):wikitext( sectionData.name )
		sections[sectionData.id] = { boxes = sectionTag:tag( 'ul' ):addClass( 'spritedoc-boxes' ) }
	end
	
	local keyedData = {}
	local i = 1
	for name, idData in pairs( data.ids ) do
		keyedData[i] = {
			sortKey = mw.ustring.lower( name ),
			name = name,
			data = idData
		}
		i = i + 1
	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, data = dataPage, nourl = spriteStyle ~= '' } )
			
			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
	local styles = f:callParserFunction( '#widget:SpriteDoc.css' )
	return styles, spriteStyle, tostring( body )
end
return p