Module:Inventory slot: Difference between revisions

From Parallel Wiki
Jump to navigation Jump to search
No edit summary
Tag: Reverted
No edit summary
 
(One intermediate revision by the same user not shown)
Line 3: Line 3:
local i18n = {
local i18n = {
filename = 'Invicon $1',
filename = 'Invicon $1',
legacyFilename = 'Grid $1.png',
-- legacyFilename = 'Grid $1.png',
modLink = 'Mods/$1/$2',
legacyFilename = '$1Invicon $2.png',
-- modLink = 'Mods/$1/$2',
modLink = '$1:$2',
moduleAliases = [[Module:Inventory slot/Aliases]],
moduleAliases = [[Module:Inventory slot/Aliases]],
moduleParallelAliases = [[Module:ParallelAliases]],
moduleRandom = [[Module:Random]],
moduleRandom = [[Module:Random]],
-- List of special prefixes which should be handled by
-- List of special prefixes which should be handled by
Line 13: Line 16:
matching = 'Matching',
matching = 'Matching',
damaged = 'Damaged',
damaged = 'Damaged',
-- parallel = 'Parallel', -- added
},
},
suffixes = {
suffixes = {
Line 23: Line 27:
local random = require( i18n.moduleRandom ).random
local random = require( i18n.moduleRandom ).random
local aliases = mw.loadData( i18n.moduleAliases )
local aliases = mw.loadData( i18n.moduleAliases )
local parallelAliases = mw.loadData( i18n.moduleParallelAliases )
local pageName = mw.title.getCurrentTitle().text
local pageName = mw.title.getCurrentTitle().text


Line 99: Line 104:
local category
local category
local title = frame.title or mw.text.trim( args.title or '' )
local title = frame.title or mw.text.trim( args.title or '' )
local mod = frame.mod
-- local mod = frame.mod
local mod = frame.mod  -- <----- THIS IS CHANGED
local name = frame.name or ''
local name = frame.name or ''
local num = frame.num
local num = frame.num
Line 106: Line 112:
local img
local img
if mod then
if mod then
img = i18n.legacyFilename:gsub( '%$1', name .. ' (' .. mod .. ')' )
-- img = i18n.legacyFilename:gsub( '%$1', name .. ' (' .. mod .. ')' )
img = i18n.legacyFilename:gsub( '%$1', mod ):gsub( '%$2', name )  -- <---- this is also different
elseif name:match( '%.gif$' ) or name:match( '%.png$' ) then
elseif name:match( '%.gif$' ) or name:match( '%.png$' ) then
img = i18n.filename:gsub( '%$1', name )
img = i18n.filename:gsub( '%$1', name )
Line 115: Line 122:
img = i18n.filename:gsub( '%$1', name .. '.png' )
img = i18n.filename:gsub( '%$1', name .. '.png' )
end
end
-- local link = args.link or ''
-- if link == '' then
-- if mod then
-- link = i18n.modLink:gsub( '%$1', mod ):gsub( '%$2', name )
-- else
-- link = name:gsub( '^' .. i18n.prefixes.damaged .. ' ', '' )
-- for _, suffix in pairs( i18n.suffixes ) do
-- link = link:gsub( ' ' .. suffix .. '$', '' )
-- end
-- end
-- elseif link:lower() == 'none' then
-- link = nil
-- end
-- if link == pageName then
-- link = nil
-- end
local link = args.link or ''
local link = args.link or ''
if link == '' then
if link == '' then
if mod then
if mod then   -- <----- this if statement is edited too
link = i18n.modLink:gsub( '%$1', mod ):gsub( '%$2', name )
if mod == "parallel" then
link = name
else
link = i18n.modLink:gsub( '%$1', mod ):gsub( '%$2', name )
end
else
else
link = name:gsub( '^' .. i18n.prefixes.damaged .. ' ', '' )
link = name:gsub( '^' .. i18n.prefixes.damaged .. ' ', '' ) .. ' (Vanilla)'
for _, suffix in pairs( i18n.suffixes ) do
for _, suffix in pairs( i18n.suffixes ) do
link = link:gsub( ' ' .. suffix .. '$', '' )
link = link:gsub( ' ' .. suffix .. '$', '' )
Line 222: Line 250:
modData.default = nil
modData.default = nil
end
end
-- if mod == 'parallel' then  -- <------ THIS IS NEW
-- modData.aliases = mw.loadData( 'Module:ParallelAliases' )
-- end
local frames
local frames
Line 304: Line 335:
if aliases or modData.aliases then
if aliases or modData.aliases then
local id = frame.name
local id = frame.name
if frame.mod then
-- if frame.mod then
id = frame.mod .. ':' .. id
-- id = frame.mod .. ':' .. id
end
-- end
if frame.mod then -- <--- THIS IS CHANGED
if frame.mod == 'parallel' then
modData.aliases = parallelAliases
else
id = frame.mod .. ':' .. id
end
end
local alias = modData and modData.aliases and modData.aliases[id] or
local alias = modData and modData.aliases and modData.aliases[id] or
Line 470: Line 508:
   
   
return p
return p
-- local p = {}
-- local i18n = {
-- filename = 'Invicon $1',
-- -- legacyFilename = 'Grid $1.png',
-- legacyFilename = '$1Invicon $2.png',
-- -- modLink = 'Mods/$1/$2',
-- modLink = '$1:$2',
-- moduleAliases = [[Module:Inventory slot/Aliases]],
-- moduleParallelAliases = [[Module:ParallelAliases]],
-- moduleRandom = [[Module:Random]],
-- -- List of special prefixes which should be handled by
-- -- other modules (such as being moved outside links)
-- prefixes = {
-- any = 'Any',
-- matching = 'Matching',
-- damaged = 'Damaged',
-- -- parallel = 'Parallel', -- added
-- },
-- suffixes = {
-- be = 'BE',
-- lce = 'LCE',
-- },
-- }
-- p.i18n = i18n
-- local random = require( i18n.moduleRandom ).random
-- local aliases = mw.loadData( i18n.moduleAliases )
-- local parallelAliases = mw.loadData( i18n.moduleParallelAliases )
-- local pageName = mw.title.getCurrentTitle().text
-- --[[Splits a given text into fragments separated by semicolons that are not
--    inside square brackets. Written by AttemptToCallNil for the Russian wiki
-- --]]
-- local function splitOnUnenclosedSemicolons(text)
-- local semicolon, lbrace, rbrace = (";[]"):byte(1, 3)
-- local nesting = false
-- local splitStart = 1
-- local frameIndex = 1
-- local frames = {}
-- for index = 1, text:len() do
-- local byte = text:byte(index)
-- if byte == semicolon and not nesting then
-- frames[frameIndex] = text:sub(splitStart, index - 1)
-- frameIndex = frameIndex + 1
-- splitStart = index + 1
-- elseif byte == lbrace then
-- assert(not nesting, "Excessive square brackets found")
-- nesting = true
-- elseif byte == rbrace then
-- assert(nesting, "Unbalanced square brackets found")
-- nesting = false
-- end
-- end
-- assert(not nesting, "Unbalanced square brackets found")
-- frames[frameIndex] = text:sub(splitStart, text:len())
-- for index = 1, #frames do
-- frames[index] = (frames[index]:gsub("^%s+", ""):gsub("%s+$", "")) -- faster mw.text.trim
-- end
-- return frames
-- end
-- -- Performs a simple recursive clone of a table's values
-- local function cloneTable( origTable )
-- local newTable = {}
-- for k, v in pairs( origTable ) do
-- if type( v ) == 'table' then
-- v = cloneTable( v )
-- end
-- newTable[k] = v
-- end
-- return newTable
-- end
-- --[[Merges a list, or inserts a string
-- or table into a table
-- --]]
-- local function mergeList( parentTable, content )
-- local i = #parentTable + 1
-- if content[1] then
-- -- Merge list into table
-- for _, v in ipairs( content ) do
-- parentTable[i] = v
-- i = i + 1
-- end
-- else
-- -- Add strings or tables to table
-- parentTable[i] = content
-- end
-- end
-- -- Creates the HTML for an item
-- local function makeItem( frame, i, args )
-- local item = mw.html.create( 'span' ):addClass( 'invslot-item' )
-- if args.imgclass then
-- item:addClass( args.imgclass )
-- end
-- if frame.name == '' then
-- return item
-- end
-- local category
-- local title = frame.title or mw.text.trim( args.title or '' )
-- -- local mod = frame.mod
-- local mod = frame.mod  -- <----- THIS IS CHANGED
-- local name = frame.name or ''
-- local num = frame.num
-- local description = frame.text
-- local img
-- if mod then
-- -- img = i18n.legacyFilename:gsub( '%$1', name .. ' (' .. mod .. ')' )
-- img = i18n.legacyFilename:gsub( '%$1', mod ):gsub( '%$2', name )  -- <---- this is also different
-- elseif name:match( '%.gif$' ) or name:match( '%.png$' ) then
-- img = i18n.filename:gsub( '%$1', name )
-- -- Remove file extension from name
-- name = name:sub( 0, -5 )
-- else
-- -- Fall back to an individual image if the sprite is lacking
-- img = i18n.filename:gsub( '%$1', name .. '.png' )
-- end
-- -- local link = args.link or ''
-- -- if link == '' then
-- -- if mod then
-- -- link = i18n.modLink:gsub( '%$1', mod ):gsub( '%$2', name )
-- -- else
-- -- link = name:gsub( '^' .. i18n.prefixes.damaged .. ' ', '' )
-- -- for _, suffix in pairs( i18n.suffixes ) do
-- -- link = link:gsub( ' ' .. suffix .. '$', '' )
-- -- end
-- -- end
-- -- elseif link:lower() == 'none' then
-- -- link = nil
-- -- end
-- -- if link == pageName then
-- -- link = nil
-- -- end
-- local link = args.link or ''
-- if link == '' then
-- if mod then  -- <----- this if statement is edited too
-- if mod == "parallel" then
-- link = name
-- else
-- link = i18n.modLink:gsub( '%$1', mod ):gsub( '%$2', name )
-- end
-- else
-- link = "Vanilla:" .. name:gsub( '^' .. i18n.prefixes.damaged .. ' ', '' )
-- for _, suffix in pairs( i18n.suffixes ) do
-- link = link:gsub( ' ' .. suffix .. '$', '' )
-- end
-- end
-- elseif link:lower() == 'none' then
-- link = nil
-- end
-- if link == pageName then
-- link = nil
-- end
-- local formattedTitle
-- local plainTitle
-- if title == '' then
-- plainTitle = name
-- elseif title:lower() ~= 'none' then
-- plainTitle = title:gsub( '\\\\', '&#92;' ):gsub( '\\&', '&#38;' )
-- local formatPattern = '&[0-9a-fk-or]'
-- if plainTitle:match( formatPattern ) then
-- formattedTitle = title
-- plainTitle = plainTitle:gsub( formatPattern, '' )
-- end
-- if plainTitle == '' then
-- plainTitle = name
-- else
-- plainTitle = plainTitle:gsub( '&#92;', '\\' ):gsub( '&#38;', '&' )
-- end
-- elseif link then
-- formattedTitle = ''
-- end
-- item:attr{
-- ['data-minetip-title'] = formattedTitle,
-- ['data-minetip-text'] = description
-- }
-- -- & is re-escaped because mw.html treats attributes
-- -- as plain text, but MediaWiki doesn't
-- local escapedTitle = ( plainTitle or '' ):gsub( '&', '&#38;' )
-- local altText = img .. ': Inventory sprite for ' .. name .. ' in Minecraft as shown in-game'
-- if link then
-- altText = altText .. ' linking to ' .. link
-- end
-- if formattedTitle or plainTitle or link then
-- altText = altText .. ' with description: ' .. ( formattedTitle or plainTitle or link )
-- if description then
-- altText = altText .. ' ' .. description:gsub( '/', ' ' )
-- end
-- altText = altText:gsub( '&[0-9a-fk-or]', '' )
-- end
-- item:addClass( 'invslot-item-image' )
-- :wikitext( '[[File:', img, '|32x32px|link=', link or '', '|alt=', altText, '|', escapedTitle, ']]' )
-- if num and num > 1 and num < 1000 then
-- if link then
-- item:wikitext( '[[', link, '|' )
-- end
-- local number = item
-- :tag( 'span' )
-- :addClass( 'invslot-stacksize' )
-- :attr{ title = plainTitle }
-- :wikitext( num )
-- if args.numstyle then
-- number:cssText( args.numstyle )
-- end
-- if link then
-- item:wikitext( ']]' )
-- end
-- end
-- item:wikitext( category )
-- return item
-- end
-- -- Main entry point
-- function p.slot( f )
-- local args = f.args or f
-- if f == mw.getCurrentFrame() and args[1] == nil then
-- args = f:getParent().args
-- end
-- if not args.parsed then
-- args[1] = mw.text.trim( args[1] or '' )
-- end
-- local modData = {
-- aliases = args.modaliases or '',
-- default = args.mod
-- }
-- if modData.aliases ~= '' then
-- modData.aliases = mw.loadData( 'Module:' .. modData.aliases )
-- else
-- modData.aliases = nil
-- end
-- if args.mod == '' then
-- modData.default = nil
-- end
-- -- if mod == 'parallel' then  -- <------ THIS IS NEW
-- -- modData.aliases = mw.loadData( 'Module:ParallelAliases' )
-- -- end
-- local frames
-- if args.parsed then
-- frames = args[1]
-- elseif args[1] ~= '' then
-- local randomise = args.class == 'invslot-large' and 'never' or nil
-- frames = p.parseFrameText( args[1], randomise, false, modData )
-- end
-- local animated = frames and #frames > 1
-- local imgClass = args.imgclass
-- local numStyle = args.numstyle
-- local body = mw.html.create( 'span' ):addClass( 'invslot' ):css{ ['vertical-align'] = args.align }
-- if animated then
-- body:addClass( 'animated' )
-- end
-- if args.class then
-- body:addClass( args.class )
-- end
-- if args.style then
-- body:cssText( args.style )
-- end
-- if ( args.default or '' ) ~= '' then
-- body:addClass( 'invslot-default-' .. string.lower( args.default ):gsub( ' ', '-' ) )
-- end
-- --mw.logObject( frames )
-- if not frames then
-- return tostring( body )
-- end
-- local activeFrame = frames.randomise == true and random( #frames ) or 1
-- for i, frame in ipairs( frames ) do
-- local item
-- -- Table is a list, must contain subframes
-- if frame[1] then
-- item = body:tag( 'span' ):addClass( 'animated-subframe' )
-- local subActiveFrame = frame.randomise and random( #frame ) or 1
-- for sI, sFrame in ipairs( frame ) do
-- local sItem = makeItem( sFrame, sI, args )
-- item:node( sItem )
-- if sI == subActiveFrame then
-- sItem:addClass( 'animated-active' )
-- end
-- end
-- else
-- item = makeItem( frame, i, args )
-- body:node( item )
-- end
-- if i == activeFrame and animated then
-- item:addClass( 'animated-active' )
-- end
-- end
-- return tostring( body )
-- end
-- --[[Parses the frame text into a table of frames and subframes,
-- expanding aliases (and optionally retaining a reference), and
-- deciding if the slot can be randomised
-- --]]
-- function p.parseFrameText( framesText, randomise, aliasReference, modData )
-- local frames = { randomise = randomise }
-- local subframes = {}
-- local subframe
-- local expandedAliases
-- local splitFrames = splitOnUnenclosedSemicolons( framesText )
-- for i, frameText in ipairs( splitFrames ) do
-- frameText = frameText:gsub( '^%s*{%s*', function()
-- subframe = true
-- return ''
-- end )
-- if subframe then
-- frameText = frameText:gsub( '%s*}%s*$', function()
-- subframe = 'last'
-- return ''
-- end )
-- end
-- local frame = p.makeFrame( frameText, modData and modData.default )
-- local newFrame = frame
-- if aliases or modData.aliases then
-- local id = frame.name
-- -- if frame.mod then
-- -- id = frame.mod .. ':' .. id
-- -- end
-- if frame.mod then -- <--- THIS IS CHANGED
-- if frame.mod == 'parallel' then
-- modData.aliases = parallelAliases
-- else
-- id = frame.mod .. ':' .. id
-- end
-- end
-- local alias = modData and modData.aliases and modData.aliases[id] or
-- aliases and aliases[id]
-- if alias then
-- newFrame = p.getAlias( alias, frame )
-- if aliasReference then
-- local curFrame = #frames + 1
-- local aliasData = { frame = frame, length = #newFrame }
-- if subframe then
-- if not subframes.aliasReference then
-- subframes.aliasReference = {}
-- end
-- subframes.aliasReference[#subframes + 1] = aliasData
-- else
-- if not expandedAliases then
-- expandedAliases = {}
-- end
-- expandedAliases[curFrame] = aliasData
-- end
-- end
-- end
-- end
-- if subframe then
-- mergeList( subframes, newFrame )
-- -- Randomise starting frame for "Any *" aliases, as long as the alias is the only subframe
-- if frames.randomise ~= 'never' and subframes.randomise == nil and
-- frame.name:match( '^' .. i18n.prefixes.any .. ' ' ) then
-- subframes.randomise = true
-- else
-- subframes.randomise = false
-- end
-- if frames.randomise ~= 'never' then
-- frames.randomise = false
-- end
-- if subframe == 'last' then
-- -- No point having a subframe containing a single frame,
-- -- or the subframe being the only frame
-- if #subframes == 1 or #splitFrames == i and #frames == 0 then
-- mergeList( frames, subframes )
-- else
-- table.insert( frames, subframes )
-- end
-- subframes = {}
-- subframe = nil
-- end
-- else
-- -- Randomise starting frame for "Any *" aliases, as long as the alias is the only frame
-- if frames.randomise == nil and frame.name:match( '^' .. i18n.prefixes.any .. ' ' ) then
-- frames.randomise = true
-- elseif frames.randomise ~= 'never' then
-- frames.randomise = false
-- end
-- mergeList( frames, newFrame )
-- end
-- end
-- frames.aliasReference = expandedAliases
-- return frames
-- end
-- --[[Returns a new table with the parts of the parent frame
-- added to the alias
-- --]]
-- function p.getAlias( aliasFrames, parentFrame )
-- -- If alias is just a name, return the parent frame with the new name
-- if type( aliasFrames ) == 'string' then
-- local expandedFrame = mw.clone( parentFrame )
-- expandedFrame.name = aliasFrames
-- return { expandedFrame }
-- end
-- -- Single frame alias, put in list
-- if aliasFrames.name then
-- aliasFrames = { aliasFrames }
-- end
-- local expandedFrames = {}
-- for i, aliasFrame in ipairs( aliasFrames ) do
-- local expandedFrame
-- if type( aliasFrame ) == 'string' then
-- expandedFrame = { name = aliasFrame }
-- else
-- expandedFrame = cloneTable( aliasFrame )
-- end
-- expandedFrame.title = parentFrame.title or expandedFrame.title
-- expandedFrame.mod = parentFrame.mod or expandedFrame.mod
-- expandedFrame.num = parentFrame.num or expandedFrame.num
-- expandedFrame.text = parentFrame.text or expandedFrame.text
-- expandedFrames[i] = expandedFrame
-- end
-- return expandedFrames
-- end
-- function p.expandAlias( parentFrame, alias )
-- return p.getAlias( alias, parentFrame )
-- end
-- function p.stringifyFrame( frame )
-- if not frame.name then
-- return ''
-- end
-- return string.format(
-- '[%s]%s:%s,%s[%s]',
-- frame.title or '',
-- frame.mod or 'Minecraft',
-- frame.name,
-- frame.num or '',
-- frame.text or ''
-- )
-- end
-- function p.stringifyFrames( frames )
-- for i, frame in ipairs( frames ) do
-- frames[i] = p.stringifyFrame( frame )
-- end
-- return table.concat( frames, ';' )
-- end
-- -- Splits up the frame text into its parts
-- function p.makeFrame( frameText, mod )
-- -- Simple frame with no parts
-- if not frameText:match( '[%[:,]' ) then
-- return {
-- mod = mod,
-- name = mw.text.trim( frameText ),
-- }
-- end
-- frameText = frameText:gsub( '%s*([%[%]:,;])%s*', '%1' )
-- local frame = {}
-- frame.title = frameText:match( '^%[([^%]]+)%]' )
-- frame.mod = frameText:match( '([^:%]]+):' ) or mod
-- local vanilla = { v = 1, vanilla = 1, mc = 1, minecraft = 1 }
-- if frame.mod and vanilla[mw.ustring.lower( frame.mod )] or frame.mod == '' then
-- frame.mod = nil
-- end
-- local nameStart = ( frameText:find( ':' ) or frameText:find( '%]' ) or 0 ) + 1
-- if nameStart - 1 == #frameText then
-- nameStart = 1
-- end
-- frame.name = frameText:sub( nameStart, ( frameText:find( '[,%[]', nameStart ) or 0 ) - 1 )
-- frame.num = math.floor( frameText:match( ',(%d+)' ) or 0 )
-- if frame.num == 0 then
-- frame.num = nil
-- end
-- frame.text = frameText:match( '%[([^%]]+)%]$' )
-- return frame
-- end
-- function p.getParts( frameText, mod )
-- return p.makeFrame( frameText, mod )
-- end
-- return p

Latest revision as of 09:09, 6 November 2023

local p = {}

local i18n = {
	filename = 'Invicon $1',
	-- legacyFilename = 'Grid $1.png',
	legacyFilename = '$1Invicon $2.png',
	-- modLink = 'Mods/$1/$2',
	modLink = '$1:$2',
	moduleAliases = [[Module:Inventory slot/Aliases]],
	moduleParallelAliases = [[Module:ParallelAliases]],
	moduleRandom = [[Module:Random]],
	-- List of special prefixes which should be handled by
	-- other modules (such as being moved outside links)
	prefixes = {
		any = 'Any',
		matching = 'Matching',
		damaged = 'Damaged',
		-- parallel = 'Parallel', -- added
	},
	suffixes = {
		be = 'BE',
		lce = 'LCE',
	},
}
p.i18n = i18n

local random = require( i18n.moduleRandom ).random
local aliases = mw.loadData( i18n.moduleAliases )
local parallelAliases = mw.loadData( i18n.moduleParallelAliases )
local pageName = mw.title.getCurrentTitle().text

--[[Splits a given text into fragments separated by semicolons that are not
    inside square brackets. Written by AttemptToCallNil for the Russian wiki
--]]
local function splitOnUnenclosedSemicolons(text)
	local semicolon, lbrace, rbrace = (";[]"):byte(1, 3)
	local nesting = false
	local splitStart = 1
	local frameIndex = 1
	local frames = {}
	
	for index = 1, text:len() do
		local byte = text:byte(index)
		if byte == semicolon and not nesting then
			frames[frameIndex] = text:sub(splitStart, index - 1)
			frameIndex = frameIndex + 1
			splitStart = index + 1
		elseif byte == lbrace then
			assert(not nesting, "Excessive square brackets found")
			nesting = true
		elseif byte == rbrace then
			assert(nesting, "Unbalanced square brackets found")
			nesting = false
		end
	end
	assert(not nesting, "Unbalanced square brackets found")
	frames[frameIndex] = text:sub(splitStart, text:len())
	
	for index = 1, #frames do
		frames[index] = (frames[index]:gsub("^%s+", ""):gsub("%s+$", "")) -- faster mw.text.trim
	end
	
	return frames
end

-- Performs a simple recursive clone of a table's values
local function cloneTable( origTable )
	local newTable = {}
	for k, v in pairs( origTable ) do
		if type( v ) == 'table' then
			v = cloneTable( v )
		end
		newTable[k] = v
	end
	return newTable
end

--[[Merges a list, or inserts a string
	or table into a table
--]]
local function mergeList( parentTable, content )
	local i = #parentTable + 1
	if content[1] then
		-- Merge list into table
		for _, v in ipairs( content ) do
			parentTable[i] = v
			i = i + 1
		end
	else
		-- Add strings or tables to table
		parentTable[i] = content
	end
end

-- Creates the HTML for an item
local function makeItem( frame, i, args )
	local item = mw.html.create( 'span' ):addClass( 'invslot-item' )
	if args.imgclass then
		item:addClass( args.imgclass )
	end
	if frame.name == '' then
		return item
	end
	local category
	local title = frame.title or mw.text.trim( args.title or '' )
	-- local mod = frame.mod
	local mod = frame.mod  -- <----- THIS IS CHANGED
	local name = frame.name or ''
	local num = frame.num
	local description = frame.text
	
	local img
	if mod then
		-- img = i18n.legacyFilename:gsub( '%$1', name .. ' (' .. mod .. ')' )
		img = i18n.legacyFilename:gsub( '%$1', mod ):gsub( '%$2', name )  -- <---- this is also different
	elseif name:match( '%.gif$' ) or name:match( '%.png$' ) then
		img = i18n.filename:gsub( '%$1', name )
		-- Remove file extension from name
		name = name:sub( 0, -5 )
	else
		-- Fall back to an individual image if the sprite is lacking
		img = i18n.filename:gsub( '%$1', name .. '.png' )
	end
	
	-- local link = args.link or ''
	-- if link == '' then
	-- 	if mod then
	-- 		link = i18n.modLink:gsub( '%$1', mod ):gsub( '%$2', name )
	-- 	else
	-- 		link = name:gsub( '^' .. i18n.prefixes.damaged .. ' ', '' )
	-- 		for _, suffix in pairs( i18n.suffixes ) do
	-- 			link = link:gsub( ' ' .. suffix .. '$', '' )
	-- 		end
	-- 	end
	-- elseif link:lower() == 'none' then
	-- 	link = nil
	-- end
	-- if link == pageName then
	-- 	link = nil
	-- end	
	
	local link = args.link or ''
	if link == '' then
		if mod then   -- <----- this if statement is edited too
			if mod == "parallel" then
				link = name
			else
				link = i18n.modLink:gsub( '%$1', mod ):gsub( '%$2', name )
			end
		else
			link = name:gsub( '^' .. i18n.prefixes.damaged .. ' ', '' ) .. ' (Vanilla)'
			for _, suffix in pairs( i18n.suffixes ) do
				link = link:gsub( ' ' .. suffix .. '$', '' )
			end
		end
	elseif link:lower() == 'none' then
		link = nil
	end
	if link == pageName then
		link = nil
	end
	
	local formattedTitle
	local plainTitle
	if title == '' then
		plainTitle = name
	elseif title:lower() ~= 'none' then
		plainTitle = title:gsub( '\\\\', '&#92;' ):gsub( '\\&', '&#38;' )
		
		local formatPattern = '&[0-9a-fk-or]'
		if plainTitle:match( formatPattern ) then
			formattedTitle = title
			plainTitle = plainTitle:gsub( formatPattern, '' )
		end
		
		if plainTitle == '' then
			plainTitle = name
		else
			plainTitle = plainTitle:gsub( '&#92;', '\\' ):gsub( '&#38;', '&' )
		end
	elseif link then
		formattedTitle = ''
	end
	
	item:attr{
		['data-minetip-title'] = formattedTitle,
		['data-minetip-text'] = description
	}
	
	-- & is re-escaped because mw.html treats attributes
	-- as plain text, but MediaWiki doesn't
	local escapedTitle = ( plainTitle or '' ):gsub( '&', '&#38;' )
	local altText = img .. ': Inventory sprite for ' .. name .. ' in Minecraft as shown in-game'
	if link then
		altText = altText .. ' linking to ' .. link
	end
	if formattedTitle or plainTitle or link then
		altText = altText .. ' with description: ' .. ( formattedTitle or plainTitle or link )
		if description then
			altText = altText .. ' ' .. description:gsub( '/', ' ' )
		end
		altText = altText:gsub( '&[0-9a-fk-or]', '' )
	end
	item:addClass( 'invslot-item-image' )
		:wikitext( '[[File:', img, '|32x32px|link=', link or '', '|alt=', altText, '|', escapedTitle, ']]' )
	
	if num and num > 1 and num < 1000 then
		if link then
			item:wikitext( '[[', link, '|' )
		end
		local number = item
			:tag( 'span' )
				:addClass( 'invslot-stacksize' )
				:attr{ title = plainTitle }
				:wikitext( num )
		if args.numstyle then
			number:cssText( args.numstyle )
		end
		if link then
			item:wikitext( ']]' )
		end
	end
	
	item:wikitext( category )
	
	return item
end

-- Main entry point
function p.slot( f )
	local args = f.args or f
	if f == mw.getCurrentFrame() and args[1] == nil then
		args = f:getParent().args
	end
	
	if not args.parsed then
		args[1] = mw.text.trim( args[1] or '' )
	end
	
	local modData = {
		aliases = args.modaliases or '',
		default = args.mod
	}
	if modData.aliases ~= '' then
		modData.aliases = mw.loadData( 'Module:' .. modData.aliases )
	else
		modData.aliases = nil
	end
	if args.mod == '' then
		modData.default = nil
	end
	-- if mod == 'parallel' then  -- <------ THIS IS NEW
	-- 	modData.aliases = mw.loadData( 'Module:ParallelAliases' )
	-- end
	
	local frames
	if args.parsed then
		frames = args[1]
	elseif args[1] ~= '' then
		local randomise = args.class == 'invslot-large' and 'never' or nil
		frames = p.parseFrameText( args[1], randomise, false, modData )
	end
	local animated = frames and #frames > 1
	local imgClass = args.imgclass
	local numStyle = args.numstyle
	local body = mw.html.create( 'span' ):addClass( 'invslot' ):css{ ['vertical-align'] = args.align }
	if animated then
		body:addClass( 'animated' )
	end
	if args.class then
		body:addClass( args.class )
	end
	if args.style then
		body:cssText( args.style )
	end
	if ( args.default or '' ) ~= '' then
		body:addClass( 'invslot-default-' .. string.lower( args.default ):gsub( ' ', '-' ) )
	end
	
	--mw.logObject( frames )
	if not frames then
		return tostring( body )
	end
	
	local activeFrame = frames.randomise == true and random( #frames ) or 1
	for i, frame in ipairs( frames ) do
		local item
		-- Table is a list, must contain subframes
		if frame[1] then
			item = body:tag( 'span' ):addClass( 'animated-subframe' )
			local subActiveFrame = frame.randomise and random( #frame ) or 1
			for sI, sFrame in ipairs( frame ) do
				local sItem = makeItem( sFrame, sI, args )
				item:node( sItem )
				
				if sI == subActiveFrame then
					sItem:addClass( 'animated-active' )
				end
			end
		else
			item = makeItem( frame, i, args )
			body:node( item )
		end
		if i == activeFrame and animated then
			item:addClass( 'animated-active' )
		end
	end
	
	return tostring( body )
end

--[[Parses the frame text into a table of frames and subframes,
	expanding aliases (and optionally retaining a reference), and
	deciding if the slot can be randomised
--]]
function p.parseFrameText( framesText, randomise, aliasReference, modData )
	local frames = { randomise = randomise }
	local subframes = {}
	local subframe
	local expandedAliases
	local splitFrames = splitOnUnenclosedSemicolons( framesText )
	for i, frameText in ipairs( splitFrames ) do
		frameText = frameText:gsub( '^%s*{%s*', function()
			subframe = true
			return ''
		end )
		if subframe then
			frameText = frameText:gsub( '%s*}%s*$', function()
				subframe = 'last'
				return ''
			end )
		end
		local frame = p.makeFrame( frameText, modData and modData.default )
		local newFrame = frame
		if aliases or modData.aliases then
			local id = frame.name
			-- if frame.mod then
			-- 	id = frame.mod .. ':' .. id
			-- end
			if frame.mod then -- <--- THIS IS CHANGED
				if frame.mod == 'parallel' then
					modData.aliases = parallelAliases
				else
					id = frame.mod .. ':' .. id
				end
			end			
			
			local alias = modData and modData.aliases and modData.aliases[id] or
				aliases and aliases[id]
			if alias then
				newFrame = p.getAlias( alias, frame )
				if aliasReference then
					local curFrame = #frames + 1
					local aliasData = { frame = frame, length = #newFrame }
					if subframe then
						if not subframes.aliasReference then
							subframes.aliasReference = {}
						end
						subframes.aliasReference[#subframes + 1] = aliasData
					else
						if not expandedAliases then
							expandedAliases = {}
						end
						expandedAliases[curFrame] = aliasData
					end
				end
			end
		end
		
		if subframe then
			mergeList( subframes, newFrame )
			-- Randomise starting frame for "Any *" aliases, as long as the alias is the only subframe
			if frames.randomise ~= 'never' and subframes.randomise == nil and
				frame.name:match( '^' .. i18n.prefixes.any .. ' ' ) then
				subframes.randomise = true
			else
				subframes.randomise = false
			end
			if frames.randomise ~= 'never' then
				frames.randomise = false
			end
			if subframe == 'last' then
				-- No point having a subframe containing a single frame,
				-- or the subframe being the only frame
				if #subframes == 1 or #splitFrames == i and #frames == 0 then
					mergeList( frames, subframes )
				else
					table.insert( frames, subframes )
				end
				subframes = {}
				subframe = nil
			end
		else
			-- Randomise starting frame for "Any *" aliases, as long as the alias is the only frame
			if frames.randomise == nil and frame.name:match( '^' .. i18n.prefixes.any .. ' ' ) then
				frames.randomise = true
			elseif frames.randomise ~= 'never' then
				frames.randomise = false
			end
			mergeList( frames, newFrame )
		end
	end
	
	frames.aliasReference = expandedAliases
	
	return frames
end

--[[Returns a new table with the parts of the parent frame
	added to the alias
--]]
function p.getAlias( aliasFrames, parentFrame )
	-- If alias is just a name, return the parent frame with the new name
	if type( aliasFrames ) == 'string' then
		local expandedFrame = mw.clone( parentFrame )
		expandedFrame.name = aliasFrames
		return { expandedFrame }
	end
	
	-- Single frame alias, put in list
	if aliasFrames.name then
		aliasFrames = { aliasFrames }
	end
	
	local expandedFrames = {}
	for i, aliasFrame in ipairs( aliasFrames ) do
		local expandedFrame
		if type( aliasFrame ) == 'string' then
			expandedFrame = { name = aliasFrame }
		else
			expandedFrame = cloneTable( aliasFrame )
		end
		expandedFrame.title = parentFrame.title or expandedFrame.title
		expandedFrame.mod = parentFrame.mod or expandedFrame.mod
		expandedFrame.num = parentFrame.num or expandedFrame.num
		expandedFrame.text = parentFrame.text or expandedFrame.text
		
		expandedFrames[i] = expandedFrame
	end
	
	return expandedFrames
end

function p.expandAlias( parentFrame, alias )
	return p.getAlias( alias, parentFrame )
end

function p.stringifyFrame( frame )
	if not frame.name then
		return ''
	end
	return string.format(
		'[%s]%s:%s,%s[%s]',
		frame.title or '',
		frame.mod or 'Minecraft',
		frame.name,
		frame.num or '',
		frame.text or ''
	)
end

function p.stringifyFrames( frames )
	for i, frame in ipairs( frames ) do
		frames[i] = p.stringifyFrame( frame )
	end
	return table.concat( frames, ';' )
end

-- Splits up the frame text into its parts
function p.makeFrame( frameText, mod )
	-- Simple frame with no parts
	if not frameText:match( '[%[:,]' ) then
		return {
			mod = mod,
			name = mw.text.trim( frameText ),
		}
	end
	
	frameText = frameText:gsub( '%s*([%[%]:,;])%s*', '%1' )
	
	local frame = {}
	frame.title = frameText:match( '^%[([^%]]+)%]' )
	
	frame.mod = frameText:match( '([^:%]]+):' ) or mod
	local vanilla = { v = 1, vanilla = 1, mc = 1, minecraft = 1 }
	if frame.mod and vanilla[mw.ustring.lower( frame.mod )] or frame.mod == '' then
		frame.mod = nil
	end
	
	local nameStart = ( frameText:find( ':' ) or frameText:find( '%]' ) or 0 ) + 1
	if nameStart - 1 == #frameText then
		nameStart = 1
	end
	frame.name = frameText:sub( nameStart, ( frameText:find( '[,%[]', nameStart ) or 0 ) - 1 )
	
	frame.num = math.floor( frameText:match( ',(%d+)' ) or 0 )
	if frame.num == 0 then
		frame.num = nil
	end
	
	frame.text = frameText:match( '%[([^%]]+)%]$' )
	
	return frame
end
function p.getParts( frameText, mod )
	return p.makeFrame( frameText, mod )
end
 
return p