Minecraft Wiki
Registrarse
Sawyerar (discusión | contribs.)
Sin resumen de edición
Sawyerar (discusión | contribs.)
(Se ha deshecho la revisión 104185 de Sawyerar (disc.))
Etiqueta: Deshacer
Línea 3: Línea 3:
 
local args = f
 
local args = f
 
if f == mw.getCurrentFrame() then
 
if f == mw.getCurrentFrame() then
args = require( 'Module:ProcessArgs' ).merge( true )
+
args = require( 'Módulo: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 17: Línea 12:
 
size = 16,
 
size = 16,
 
pos = 1,
 
pos = 1,
align = 'text-top'
+
link = '',
  +
align = 'text-top',
  +
class = '',
  +
text = '',
  +
title = ''
 
}
 
}
 
 
local defaultStyle = default
+
local defaultStyle = mw.clone( default )
if settings then
+
if args.settings then
  +
local settings = mw.loadData( 'Módulo:' .. 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
 
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 setting = function( arg )
+
local name = args.name or default.name
return args[arg] or default[arg]
+
local scale = args.scale or default.scale
  +
local autoScale = args.autoscale or default.autoscale
end
 
  +
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
 
  +
class = ( className or mw.ustring.lower( name:gsub( ' ', '-' ) ) .. '-sprite ' ) .. class
if not setting( 'nourl' ) and setting( 'url' ) then
 
  +
else
styles[#styles + 1] = 'background-image:' .. ( setting( 'url' ).url or setting( 'url' ) )
 
  +
table.insert( styles, 'background-image:{{FileUrl|' .. ( args.image or default.image or name .. 'Sprite.png' ) .. '}}' )
 
end
 
end
if setting( 'stylesheet' ) then
+
if left > 0 or top > 0 then
  +
table.insert( styles, 'background-position:-' .. left * scale .. 'px -' .. top * scale .. 'px' )
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
 
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
styles[#styles + 1] = 'background-size:' .. sheetWidth * scale .. 'px auto'
+
table.insert( styles, '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
styles[#styles + 1] = 'height:' .. size * scale .. 'px'
+
table.insert( styles, 'height:' .. size * scale .. 'px;width:' .. 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
styles[#styles + 1] = 'vertical-align:' .. align
+
table.insert( styles, 'vertical-align:' .. align )
 
end
 
end
  +
if css then
styles[#styles + 1] = setting( 'css' )
 
  +
table.insert( styles, css )
 
  +
end
sprite:cssText( table.concat( styles, ';' ) )
 
  +
if title ~= '' then
 
  +
title = ' title="' .. title .. '"'
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
 
end
 
 
local title = setting( 'title' )
+
local sprite = table.concat( {
  +
'<span',
if title then
 
  +
'class="sprite ' .. class .. '"',
( root or sprite ):attr( 'title', title )
 
  +
'style="' .. table.concat( styles, ';' ) .. '"',
end
 
  +
title,
  +
'><br></span>'
  +
}, ' ' )
  +
sprite = sprite:gsub( '%s+([">])', '%1' )
 
 
if not root then
+
if text ~= '' then
  +
text = '<span class="sprite-text nowrap"' .. title .. '>' .. text .. '</span>'
root = mw.html.create( '' )
 
end
 
root:node( sprite )
 
if spriteText then
 
root:node( spriteText )
 
 
end
 
end
 
 
local link = setting( 'link' ) or ''
+
if link ~= '' then
if link ~= '' and mw.ustring.lower( link ) ~= 'none' then
 
-- External link
 
 
if link:find( '//' ) then
 
if link:find( '//' ) then
  +
-- External link
return '[' .. link .. ' ' .. tostring( root ) .. ']'
 
  +
return '[' .. link .. ' ' .. sprite .. text .. ']'
  +
else
  +
-- Internal link
  +
local linkPrefix = args.linkprefix or default.linkprefix or ''
  +
return '[[' .. linkPrefix .. link .. '|' .. sprite .. text .. ']]'
 
end
 
end
  +
else
 
  +
return sprite .. text
-- Internal link
 
local linkPrefix = setting( 'linkprefix' ) or ''
 
return '[[' .. linkPrefix .. link .. '|' .. tostring( root ) .. ']]'
 
 
end
 
end
 
return tostring( root )
 
 
end
 
end
   
Línea 128: Línea 103:
 
local args = f
 
local args = f
 
if f == mw.getCurrentFrame() then
 
if f == mw.getCurrentFrame() then
args = require( 'Module:ProcessArgs' ).merge( true )
+
args = require( 'Módulo:ProcessArgs' ).merge( true )
else
 
f = mw.getCurrentFrame()
 
 
end
 
end
 
 
  +
local category = ''
local data = args.data and mw.loadData( 'Module:' .. args.data ) or {}
 
  +
if tonumber( args[1] ) then
local categories = {}
 
local idData = args.iddata
+
args.pos = args[1]
  +
else
if not idData then
 
local name = args.name or data.settings.name
+
local default = {}
  +
if args.settings then
local id = mw.text.trim( tostring( args[1] or '' ) )
 
  +
default = mw.loadData( 'Módulo:' .. args.settings )
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
 
end
 
 
args.pos = idData.pos
+
local name = args.name or default.name
  +
local ids = mw.loadData( 'Módulo:' .. ( args.ids or default.ids or 'Sprite/' .. name ) )
elseif not disallowCats then
 
  +
local id = mw.text.trim( args[1] or '' )
categories[#categories + 1] = f:expandTemplate{ title = 'Translation category', args = { 'Pages with missing sprites', project = 0 } }
 
  +
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 ), table.concat( categories )
+
return p.base( args ) .. category
 
end
 
end
   
Línea 164: Línea 131:
 
local args = f
 
local args = f
 
if f == mw.getCurrentFrame() then
 
if f == mw.getCurrentFrame() then
args = require( 'Module:ProcessArgs' ).merge( true )
+
args = require( 'Módulo:ProcessArgs' ).merge( true )
 
end
 
end
 
 
Línea 171: Línea 138:
 
link = args[1]:match( '^(.-)%+' ) or args[1]
 
link = args[1]:match( '^(.-)%+' ) or args[1]
 
end
 
end
local text
+
local text = args.text or args[2] or link
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 = args.link or link
+
args.link = 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 settings = mw.loadData( 'Módulo:' .. f.args[1] )
local args = f
 
  +
local idTable = mw.title.new( 'Módulo:' .. ( settings.ids or 'Sprite/' .. settings.name ) ):getContent()
if f == mw.getCurrentFrame() then
 
  +
idTable = idTable:gsub( '(\n%s*%-%-%s*.-%s*%-%-%s*\n)', '%1,' ):gsub( '^return {', '' ):gsub( '}$', '' )
args = f.args
 
else
 
f = mw.getCurrentFrame()
 
end
 
local dataPage = mw.text.trim( args[1] )
 
local data = mw.loadData( 'Module:' .. dataPage )
 
 
 
  +
local html = {}
local getProtection = function( title, action, extra )
 
local protections = { 'edit' }
+
local ids = {}
  +
local posKeys = {}
if extra then
 
  +
local section = ''
protections[#protections + 1] = extra
 
  +
for line in mw.text.gsplit( idTable, ',' ) do
end
 
  +
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
 
 
  +
if id ~= '' and pos ~= '' then
local addProtection = function( protection )
 
if protection == 'autoconfirmed' then
+
if ids[pos] then
  +
if type( ids[pos].id ) == 'table' then
protection = 'editsemiprotected'
 
  +
table.insert( ids[pos].id, id )
elseif protection == 'sysop' then
 
  +
else
protection = 'editprotected'
 
  +
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 direct = title.protectionLevels[action] or {}
+
local list = {}
  +
local listHead = '<ul class="spritedoc-multicolumn">'
for _, protection in ipairs( direct ) do
 
  +
local listFoot = '</ul>'
addProtection( protection )
 
  +
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
  +
table.insert( list, '<li><table><tr><td data-pos="' .. pos .. '">' )
local cascading = title.cascadingProtection.restrictions[action] or {}
 
if #cascading > 0 then
+
if type( id ) == 'table' then
  +
for i, id2 in ipairs( id ) do
protections[#protections + 1] = 'protect'
 
  +
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
  +
table.insert( list, '</td></tr></table></li>' )
for _, protection in ipairs( cascading ) do
 
  +
addProtection( protection )
 
  +
if i == #posKeys then
  +
table.insert( list, listFoot )
 
end
 
end
 
return table.concat( protections, ',' )
 
 
end
 
end
 
 
local spriteStyle = ''
+
local out = table.concat( list )
if data.settings.url and data.settings.url.style then
+
if not f.args.refresh then
  +
out = f:preprocess( '{{#widget:stylesheet|page=Sprite doc}}' ) .. '<div id="sprite-doc" data-settings="' .. f.args[1] .. '">' .. out .. '</div>'
spriteStyle = data.settings.url.style
 
 
end
 
end
 
 
  +
return out
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
 
end
 
return p
 
return p

Revisión del 23:32 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( 'Módulo:ProcessArgs' ).merge( true )
	end
	
	-- Default settings
	local default = {
		scale = 1,
		sheetsize = 256,
		size = 16,
		pos = 1,
		link = '',
		align = 'text-top',
		class = '',
		text = '',
		title = ''
	}
	
	local defaultStyle = mw.clone( default )
	if args.settings then
		local settings = mw.loadData( 'Módulo:' .. args.settings )
		for k, v in pairs( settings ) do
			default[k] = v
			if settings.stylesheet then
				defaultStyle[k] = v
			end
		end
	end
	
	local name = args.name or default.name
	local scale = args.scale or default.scale
	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 styles = {}
	if args.stylesheet or default.stylesheet then
		class = ( className or mw.ustring.lower( name:gsub( ' ', '-' ) ) .. '-sprite ' ) .. class
	else
		table.insert( styles, 'background-image:{{FileUrl|' .. ( args.image or default.image or name .. 'Sprite.png' ) .. '}}' )
	end
	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;width:' .. size * scale .. 'px' )
	end
	if align ~= defaultStyle.align then
		table.insert( styles, 'vertical-align:' .. align )
	end
	if css then
		table.insert( styles, css )
	end
	if title ~= '' then
		title = ' title="' .. title .. '"'
	end
	
	local sprite = table.concat( {
		'<span',
			'class="sprite ' .. class .. '"',
			'style="' .. table.concat( styles, ';' ) .. '"',
			title,
		'><br></span>'
	}, ' ' )
	sprite = sprite:gsub( '%s+([">])', '%1' )
	
	if text ~= '' then
		text = '<span class="sprite-text nowrap"' .. title .. '>' .. text .. '</span>'
	end
	
	if link ~= '' then
		if link:find( '//' ) then
			-- External link
			return '[' .. link .. ' ' .. sprite .. text .. ']'
		else
			-- Internal link
			local linkPrefix = args.linkprefix or default.linkprefix or ''
			return '[[' .. linkPrefix .. link .. '|' .. sprite .. text .. ']]'
		end
	else
		return sprite .. text
	end
end

function p.sprite( f )
	local args = f
	if f == mw.getCurrentFrame() then
		args = require( 'Módulo:ProcessArgs' ).merge( true )
	end
	
	local category = ''
	if tonumber( args[1] ) then
		args.pos = args[1]
	else
		local default = {}
		if args.settings then
			default = mw.loadData( 'Módulo:' .. args.settings )
		end
		
		local name = args.name or default.name
		local ids = mw.loadData( 'Módulo:' .. ( args.ids or default.ids or 'Sprite/' .. name ) )
		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
	
	return p.base( args ) .. category
end

function p.link( f )
	local args = f
	if f == mw.getCurrentFrame() then
		args = require( 'Módulo: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 = link
	args.text = text
	
	return p.sprite( args )
end

function p.doc( f )
	local settings = mw.loadData( 'Módulo:' .. f.args[1] )
	local idTable = mw.title.new( 'Módulo:' .. ( settings.ids or 'Sprite/' .. settings.name ) ):getContent()
	idTable = idTable:gsub( '(\n%s*%-%-%s*.-%s*%-%-%s*\n)', '%1,' ):gsub( '^return {', '' ):gsub( '}$', '' )
	
	local html = {}
	local ids = {}
	local posKeys = {}
	local section = ''
	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
		
		if id ~= '' and pos ~= '' then
			if ids[pos] then
				if type( ids[pos].id ) == 'table' then
					table.insert( ids[pos].id, id )
				else
					ids[pos].id = { ids[pos].id, id }
				end
			else
				ids[pos] = { id = id, section = section }
				table.insert( posKeys, pos )
			end
		end
	end
		
	local list = {}
	local listHead = '<ul class="spritedoc-multicolumn">'
	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
		table.insert( list, '<li><table><tr><td data-pos="' .. pos .. '">' )
		if type( id ) == 'table' then
			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
		table.insert( list, '</td></tr></table></li>' )
		
		if i == #posKeys then
			table.insert( list, listFoot )
		end
	end
	
	local out = table.concat( list )
	if not f.args.refresh then
		out = f:preprocess( '{{#widget:stylesheet|page=Sprite doc}}' ) .. '<div id="sprite-doc" data-settings="' .. f.args[1] .. '">' .. out .. '</div>'
	end
	
	return out
end
return p