Module:Inventory slot: Difference between revisions
Jump to navigation
Jump to search
m It's always those last second changes that get me... |
Rewrite for better readability; add i18n; improve performance; support subframes; improve randomness; support already parsed frames |
||
Line 1: | Line 1: | ||
local p = {} | local p = {} | ||
-- List of special prefixes which should be handled by | local i18n = { | ||
-- other modules (such as being moved outside links) | filename = 'Invicon $1', | ||
legacyFilename = 'Grid $1.png', | |||
modLink = 'Mods/$1/$2', | |||
moduleAliases = [[Module:Inventory slot/Aliases]], | |||
' | moduleInvIds = [[Module:InvSprite/IDs]], | ||
moduleModIds = 'Module:InvSprite/Mods/$1/IDs', | |||
moduleRandom = [[Module:Random]], | |||
moduleSprite = [[Module:Sprite]], | |||
-- List of special prefixes which should be handled by | |||
-- other modules (such as being moved outside links) | |||
prefixes = { | |||
'Any', | |||
'Matching', | |||
'Damaged', | |||
any = 'Any', | |||
matching = 'Matching', | |||
damaged = 'Damaged', | |||
}, | |||
templateFileUrl = 'FileUrl', | |||
} | } | ||
p.i18n = i18n | |||
p.prefixes = i18n.prefixes | |||
local | local random = require( i18n.moduleRandom ).random | ||
local sprite = require( i18n.moduleSprite ).sprite | |||
local aliases = mw.loadData( i18n.moduleAliases ) | |||
local ids = mw.loadData( i18n.moduleInvIds ).ids | |||
local modIds = {} | |||
local pageName = mw.title.getCurrentTitle().text | |||
-- Performs a simple recursive clone of a table's values | |||
local function cloneTable( origTable ) | local function cloneTable( origTable ) | ||
local newTable = {} | local newTable = {} | ||
Line 32: | Line 44: | ||
end | end | ||
function | --[[Merges a list, or inserts a string | ||
local | or table into a table | ||
if | --]] | ||
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 | |||
item:tag( 'br' ) | |||
return item | |||
end | end | ||
local category | |||
local title = frame.title or mw.text.trim( args.title or '' ) | |||
local mod = frame.mod | |||
local name = frame.name or '' | |||
local num = frame.num | |||
local description = frame.text | |||
local img, idData | |||
if mod then | |||
local modData = modIds[mod] | |||
if not modData and mw.title.new( i18n.moduleModIds:gsub( '%$1', mod ) ).exists then | |||
modData = mw.loadData( i18n.moduleModIds:gsub( '%$1', mod ) ) | |||
modIds[mod] = modData | |||
end | |||
if modData and modData[name] then | |||
idData = modData[name] | |||
else | |||
img = i18n.legacyFilename:gsub( '%$1', name .. ' (' .. mod .. ')' ) | |||
end | |||
elseif ids[name] then | |||
idData = ids[name] | |||
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 | else | ||
img = i18n.legacyFilename:gsub( '%$1', name ) | |||
end | end | ||
local | local link = args.link or '' | ||
if | if link == '' then | ||
if mod then | |||
link = i18n.modLink:gsub( '%$1', mod ):gsub( '%$2', name ) | |||
else | |||
link = name:gsub( '^' .. i18n.prefixes.damaged .. ' ', '' ) | |||
end | |||
elseif link:lower() == 'none' then | |||
link = nil | |||
end | end | ||
local | if link == pageName then | ||
link = nil | |||
end | |||
local formattedTitle | |||
local plainTitle | |||
if title == '' then | |||
plainTitle = name | |||
elseif title:lower() ~= 'none' then | |||
plainTitle = title:gsub( '\\\\', '\' ):gsub( '\\&', '&' ) | |||
local | local formatPattern = '&[0-9a-fk-or]' | ||
if | if plainTitle:match( formatPattern ) then | ||
formattedTitle = title | |||
plainTitle = plainTitle:gsub( formatPattern, '' ) | |||
end | end | ||
if plainTitle == '' then | |||
if | plainTitle = name | ||
else | |||
plainTitle = plainTitle:gsub( '\', '\\' ):gsub( '&', '&' ) | |||
end | end | ||
elseif link then | |||
if | if img then | ||
formattedTitle = '' | |||
else | else | ||
plainTitle = '' | |||
end | end | ||
-- | end | ||
-- | |||
if | item:attr{ | ||
['data-minetip-title'] = formattedTitle, | |||
['data-minetip-text'] = description | |||
} | |||
if img then | |||
-- & is re-escaped because mw.html treats attributes | |||
-- as plain text, but MediaWiki doesn't | |||
local escapedTitle = ( plainTitle or '' ):gsub( '&', '&' ) | |||
item:addClass( 'invslot-item-image' ) | |||
:wikitext( '[[File:', img, '|32x32px|link=', link or '', '|', escapedTitle, ']]' ) | |||
else | |||
local image | |||
if mod then | |||
image = args.spritesheet or mod .. 'Sprite.png' | |||
end | |||
if link then | |||
item:wikitext( '[[', link, '|' ) | |||
end | |||
local image, spriteCat = sprite{ | |||
iddata = idData, title = plainTitle, | |||
image = image, settings = 'InvSprite' | |||
} | |||
item:node( image ) | |||
category = spriteCat | |||
end | |||
if num and num > 1 and num < 1000 then | |||
if img and link then | |||
item:wikitext( '[[', link, '|' ) | |||
end | |||
local number = item | |||
:tag( 'span' ) | |||
:addClass( 'invslot-stacksize' ) | |||
:attr{ title = plainTitle } | |||
:wikitext( num ) | |||
if numStyle then | |||
number:cssText( numStyle ) | |||
end | |||
if img and link then | |||
item:wikitext( ']]' ) | |||
end | end | ||
end | end | ||
local | if idData and link then | ||
item:wikitext( ']]' ) | |||
local | end | ||
local | |||
local | 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 | |||
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 imgClass = args.imgclass | ||
local numStyle = args.numstyle | local numStyle = args.numstyle | ||
Line 100: | Line 236: | ||
if args.style then | if args.style then | ||
body:cssText( args.style ) | body:cssText( args.style ) | ||
end | |||
if ( args.default or '' ) ~= '' then | |||
body:css( 'background-image', f:expandTemplate{ name = i18n.templateFileUrl, args = { args.default .. '.png' } } ) | |||
end | end | ||
--mw.logObject( frames ) | |||
body: | if not frames then | ||
body:tag( 'br' ) | |||
return tostring( body ) | |||
end | end | ||
local activeFrame = randomise and | local activeFrame = frames.randomise == true and random( #frames ) or 1 | ||
for i, frame in ipairs( frames ) do | for i, frame in ipairs( frames ) do | ||
local item | local item | ||
if frame | -- Table is a list, must contain subframes | ||
item = body:tag( 'span' ):addClass( ' | if frame[1] then | ||
if | 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 | 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 = mw.text.split( mw.text.trim( framesText ), '%s*;%s*' ) | |||
for _, 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 | 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 | |||
local | end | ||
local | local alias = modData and modData.aliases and modData.aliases[id] or | ||
if | aliases and aliases[id] | ||
if alias then | |||
if | 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 | |||
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 | else | ||
subframes.randomise = false | |||
end | end | ||
if frames.randomise ~= 'never' then | |||
frames.randomise = false | |||
end | end | ||
if | 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 ) | |||
if | |||
else | else | ||
table.insert( frames, subframes ) | |||
end | end | ||
subframes = {} | |||
subframe = nil | |||
end | 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 | |||
if | |||
end | end | ||
mergeList( frames, newFrame ) | |||
end | end | ||
end | end | ||
return | frames.aliasReference = expandedAliases | ||
return frames | |||
end | 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 alias is just a name, return the | |||
if type( aliasFrames ) == 'string' then | if type( aliasFrames ) == 'string' then | ||
local | local expandedFrame = mw.clone( parentFrame ) | ||
expandedFrame.name = aliasFrames | |||
return | return { expandedFrame } | ||
end | end | ||
Line 274: | Line 382: | ||
local expandedFrames = {} | local expandedFrames = {} | ||
for i, aliasFrame in ipairs( aliasFrames ) do | for i, aliasFrame in ipairs( aliasFrames ) do | ||
local | local expandedFrame | ||
if type( aliasFrame ) == 'string' then | if type( aliasFrame ) == 'string' then | ||
expandedFrame = { name = aliasFrame } | |||
else | else | ||
expandedFrame = cloneTable( aliasFrame ) | |||
end | 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] = | expandedFrames[i] = expandedFrame | ||
end | end | ||
return expandedFrames | return expandedFrames | ||
end | end | ||
function p.expandAlias( parentFrame, alias ) | function p.expandAlias( parentFrame, alias ) | ||
return p.getAlias( alias, parentFrame ) | return p.getAlias( alias, parentFrame ) | ||
Line 315: | Line 424: | ||
end | end | ||
-- Splits up the frame text into its parts | |||
function p.makeFrame( frameText, mod ) | function p.makeFrame( frameText, mod ) | ||
-- Simple frame with no parts | -- Simple frame with no parts |
Revision as of 09:28, 6 December 2016
This module implements {{inventory slot}}
.
Dependencies
de:Modul:Slot es:Módulo:Inventory slot fr:Module:Case inventaire ja:モジュール:Inventory slot ko:모듈:Inventory slot pl:Moduł:Inventory slot ru:Модуль:Инвентарный слот pt:Módulo:Inventory slot uk:Модуль:Інвентарний слот zh:模块:Inventory slot
local p = {}
local i18n = {
filename = 'Invicon $1',
legacyFilename = 'Grid $1.png',
modLink = 'Mods/$1/$2',
moduleAliases = [[Module:Inventory slot/Aliases]],
moduleInvIds = [[Module:InvSprite/IDs]],
moduleModIds = 'Module:InvSprite/Mods/$1/IDs',
moduleRandom = [[Module:Random]],
moduleSprite = [[Module:Sprite]],
-- List of special prefixes which should be handled by
-- other modules (such as being moved outside links)
prefixes = {
'Any',
'Matching',
'Damaged',
any = 'Any',
matching = 'Matching',
damaged = 'Damaged',
},
templateFileUrl = 'FileUrl',
}
p.i18n = i18n
p.prefixes = i18n.prefixes
local random = require( i18n.moduleRandom ).random
local sprite = require( i18n.moduleSprite ).sprite
local aliases = mw.loadData( i18n.moduleAliases )
local ids = mw.loadData( i18n.moduleInvIds ).ids
local modIds = {}
local pageName = mw.title.getCurrentTitle().text
-- 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
item:tag( 'br' )
return item
end
local category
local title = frame.title or mw.text.trim( args.title or '' )
local mod = frame.mod
local name = frame.name or ''
local num = frame.num
local description = frame.text
local img, idData
if mod then
local modData = modIds[mod]
if not modData and mw.title.new( i18n.moduleModIds:gsub( '%$1', mod ) ).exists then
modData = mw.loadData( i18n.moduleModIds:gsub( '%$1', mod ) )
modIds[mod] = modData
end
if modData and modData[name] then
idData = modData[name]
else
img = i18n.legacyFilename:gsub( '%$1', name .. ' (' .. mod .. ')' )
end
elseif ids[name] then
idData = ids[name]
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
img = i18n.legacyFilename:gsub( '%$1', name )
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 .. ' ', '' )
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( '\\\\', '\' ):gsub( '\\&', '&' )
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( '\', '\\' ):gsub( '&', '&' )
end
elseif link then
if img then
formattedTitle = ''
else
plainTitle = ''
end
end
item:attr{
['data-minetip-title'] = formattedTitle,
['data-minetip-text'] = description
}
if img then
-- & is re-escaped because mw.html treats attributes
-- as plain text, but MediaWiki doesn't
local escapedTitle = ( plainTitle or '' ):gsub( '&', '&' )
item:addClass( 'invslot-item-image' )
:wikitext( '[[File:', img, '|32x32px|link=', link or '', '|', escapedTitle, ']]' )
else
local image
if mod then
image = args.spritesheet or mod .. 'Sprite.png'
end
if link then
item:wikitext( '[[', link, '|' )
end
local image, spriteCat = sprite{
iddata = idData, title = plainTitle,
image = image, settings = 'InvSprite'
}
item:node( image )
category = spriteCat
end
if num and num > 1 and num < 1000 then
if img and link then
item:wikitext( '[[', link, '|' )
end
local number = item
:tag( 'span' )
:addClass( 'invslot-stacksize' )
:attr{ title = plainTitle }
:wikitext( num )
if numStyle then
number:cssText( numStyle )
end
if img and link then
item:wikitext( ']]' )
end
end
if idData and link then
item:wikitext( ']]' )
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
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:css( 'background-image', f:expandTemplate{ name = i18n.templateFileUrl, args = { args.default .. '.png' } } )
end
--mw.logObject( frames )
if not frames then
body:tag( 'br' )
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 = mw.text.split( mw.text.trim( framesText ), '%s*;%s*' )
for _, 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
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