-The Dream Cancel Wiki has successfully upgraded it's wiki software and editing has returned. Tables for data have returned.
Module:Parser
Documentation for this module may be created at Module:Parser/doc
local p = {}
local cargo = mw.ext.cargo
-- Color frame advantage text based on value (positive or negative)
function p.colorizeFrameAdvantage(frame)
-- Set the string to the first argument given
local str = frame.args[1]
-- Surrond all plus values with a span with style color green
str = string.gsub(str, "(%+%d+)", "<span style=\"color:green;\">%1</span>")
-- Surrond all negative values with a span with style color green
str = string.gsub(str, "(%-%d+)", "<span style=\"color:red;\">%1</span>")
-- Return the string
return str
end
-- Create a wikitext hyperlink that links to the frame data page section of a move
-- Assumes the section header is the same as moveInput
function p.createFrameDataLink(frame)
-- Target cargo table to query
local cargoTable = frame.args['cargoTable']
-- MoveId to query
local moveId = frame.args['moveId']
-- Field in to return in query
local fields = "input"
-- Args for query
local args = { where = "moveId = '" .. moveId .. "'"}
-- Beginning of wikitext to return
local wikitext = "[[/Data#"
-- Cargo query for moveInput
local results = cargo.query( cargoTable, fields, args )
local moveInput = results[1]['input']
-- Replaces any left and right square brackets with their ascii code to make it wikitext compatible
moveInput = string.gsub(moveInput, '%[', "[")
moveInput = string.gsub(moveInput, "%]", "]")
-- TODO: Maybe add alternate text instead of it just saying '/Data#moveInput'?
-- Concatenates 'wikitext' with 'moveInput' and ending square brackets
wikitext = wikitext .. moveInput .. "]]"
-- Returns the wikitext
return wikitext
end
-- TODO: I might delete this one? I dunno. I'll take a look at it again later. Not going to bother comment it for the time being as it's not really being used except for displaying on the frame data page, which I might change?
-- Take a list of comma separated files names and transcribe them to wikitext file markup
function p.parseImages(frame)
local listOfFiles = frame.args[1] -- List of files
local extraParameters = frame.args[2] -- Extra parameters to use in each file
local addLineBreaks = frame.args['addLineBreaks'] -- Add extra line breaks if set to "true"
local lineBreak = ""
local wikitextFiles = ""
if addLineBreaks == "true" then lineBreak = "<br>" end
if listOfFiles and string.len(listOfFiles) > 0 then
if extraParameters and string.len(extraParameters) > 0 then
extraParameters = "|" .. string.gsub(extraParameters, ",", "|")
else
extraParameters = ""
end
-- Replaces any left and right square brackets with their ascii code to make it wikitext compatible
wikitextFiles = string.gsub(listOfFiles, '%[', "[")
wikitextFiles = string.gsub(listOfFiles, '%]', "]")
wikitextFiles = string.gsub(listOfFiles,",", extraParameters .. "]]" .. lineBreak .. "[[File:")
wikitextFiles = "[[File:" .. wikitextFiles .. extraParameters .. "]]"
end
return wikitextFiles
end
-- Franck made this to take a list of items separated by a delimiter and return a specific one (or all)
-- The default delimiter is a comma to parse through moveIds
function p.parseMoves(frame)
local moves = frame.args[1]
local s = frame.args[2]
local delimiter = frame.args['delimiter'] or ","
local listOfMoves = split(moves,delimiter)
if s then return listOfMoves[s+0] end
local result = ""
for r = 1, #listOfMoves do
result = result .. listOfMoves[r]
end
return result
end
-- Franck edited this function to also get hitboxes and to take into account display parameters
-- Cargo queries a comma separated list of moveIds and returns their images or hitboxes as wikitext
function p.parseImagesQueryF(frame)
-- Target cargo table to query
local cargoTable = frame.args[1]
-- List of moves queried by their arbitrary moveId
local moves = frame.args[2]
-- Choice between querying images or hitboxes
local type = frame.args[3]
-- Display parameters to use in each file
local display = frame.args['display']
-- List of captions entered by the user on function call
-- In other words, these captions are not queried from cargos
local captions = frame.args['captions']
-- Wikitext to return after function is completed
local wikitext = ""
-- List of moves as a table
local listOfMoves = {}
-- List of captions as a table
local listOfCaptions = {}
if display and string.len(display) > 0 then
display = "|" .. string.gsub(display, ",", "|") .. "]]"
else
display = "|175x250px|center]]"
end
-- Assign listOfMoves with the values 'moves' split by the delimiter ','
listOfMoves = split(moves,",")
-- If captions exist
if captions then
-- Assign listOfCaptions with the values 'captions' split by the delimiter ','
listOfCaptions = split(captions, ",")
end
-- 'where' part of the cargo query
local whereQuery = ""
-- boolean just to track if it's the first where argument and if we should add ' OR ' to the query
local firstWhere = true
-- Iterate through every value in 'listOfMoves'
for i,v in ipairs(listOfMoves) do
-- If it's the first where argument, don't prefix with ' OR '
if firstWhere then
firstWhere = false
else
whereQuery = whereQuery .. " OR "
end
-- Concatenate the current whereQuery with the current moveId
whereQuery = whereQuery .. "moveId = '" .. trim(v) .. "'"
end
-- 'fields' part of the cargo query
local fields = ""
-- We need to grab only the first instance of each image/hitbox sorted by orderId
if type == "images" then fields = "images, MIN(orderId)=sort" end
if type == "hitboxes" then fields = "hitboxes, MIN(orderId)=sort" end
-- 'args' part of the Lua cargo query
local args = {
-- 'whereQuery' from above which goes by moveIds
where = whereQuery,
-- 'group by' is used to remove duplicate images from this query
groupBy = type,
-- 'order by' goes off of the first instance based on moveId
orderBy = "sort"
}
-- Cargo query
local results = cargo.query( cargoTable, fields, args )
-- Iterate through results
for r = 1, #results do
-- The item at the current index
local result = results[r]
-- The caption to add below the image
local caption = ""
-- If the caption exists
if listOfCaptions[r] and string.len(listOfCaptions[r]) >0 then
-- Then assign 'caption' in MoveData format
caption = "<span class=caption><small>" .. trim(listOfCaptions[r]) .. "</small></span>"
end
-- Add this item's image/hitbox and caption to the wikitext
wikitext = wikitext .. "<div>[[File:" .. result[type] .. display .. caption .. "</div>"
end
-- Return the wikitext
return wikitext
end
-- Cargo queries a comma separated list of moveIds and returns their images as wikitext
function p.parseImagesQuery(frame)
-- Target cargo table to query
local cargoTable = frame.args['cargoTable']
-- List of moves queried by their arbitrary moveId
local moves = frame.args['moveIds']
-- List of captions entered by the user on function call
-- In other words, these captions are not queried from cargos
local captions = frame.args['captions']
-- TODO: Figure out how I want to implement hitbox images
--local listOfHitboxCaptions = frame.args['hitboxCaptions']
-- Wikitext to return after function is completed
local wikitext = ""
-- List of moves as a table
local listOfMoves = {}
-- List of captions as a table
local listOfCaptions = {}
-- Assign listOfMoves with the values 'moves' split by the delimiter ','
listOfMoves = split(moves,",")
-- If captions exist
if captions then
-- Assign listOfCaptions with the values 'captions' split by the delimiter ','
listOfCaptions = split(captions, ",")
end
-- 'where' part of the cargo query
local whereQuery = ""
-- boolean just to track if it's the first where argument and if we should add ' OR ' to the query
local firstWhere = true
-- Iterate through every value in 'listOfMoves'
for i,v in ipairs(listOfMoves) do
-- If it's the first where argument, don't prefix with ' OR '
if firstWhere then
firstWhere = false
else
whereQuery = whereQuery .. " OR "
end
-- Concatenate the current whereQuery with the current moveId
whereQuery = whereQuery .. "moveId = '" .. trim(v) .. "'"
end
-- 'fields' part of the cargo query
-- We need to grab only the first instance of each image "sorted" by moveId
local fields = "images, MIN(moveId)=sort"
-- 'args' part of the Lua cargo query
local args = {
-- 'whereQuery' from above which goes by moveIds
where = whereQuery,
-- 'order by' goes off of the first instance based on moveId
orderBy = "sort",
-- 'group by' is used to remove duplicate images from this query
groupBy = "images"
}
-- Cargo query
local results = cargo.query( cargoTable, fields, args )
-- Iterate through results
for r = 1, #results do
-- The item at the current index
local result = results[r]
-- The caption to add below the image
local caption = ""
-- If the caption exists
if listOfCaptions[r] and string.len(listOfCaptions[r]) >0 then
-- Then assign 'caption'
caption = "<br>" .. trim(listOfCaptions[r])
end
-- Add this item's image and caption to the wikitext
wikitext = wikitext .. "<div>[[File:" .. result.images .. "|175px]]" .. caption .. "</div>"
end
-- Return the wikitext
return wikitext
end
-- Cargo queries for a list of comma separated moveIds
function p.parseFrameData(frame)
-- Target cargo table to query
local cargoTable = frame.args['cargoTable']
-- 'fields' part of the cargo query
local fields = frame.args['fields']
-- moveIds to query
local moveIds = frame.args['moveIds']
-- template to use for the result of this query
local template = frame.args['template']
-- descriptions to display below template
local descriptions = frame.args['descriptions']
-- A table made from splitting 'moveIds' at every ','
local listOfMoves = split(moveIds, ",")
-- A table made from splitting 'fields' at every ','
local listOfFields = split(fields,",")
-- A table made from splitting 'descriptions' at every ';'
local listOfDescriptions = {}
-- If descriptions exist
if descriptions then
-- Assign listOfDescriptions with the values 'descriptions' split by the delimiter ';'
listOfDescriptions = split(descriptions, ";")
end
-- Wikitext to return at the end
local wikitext = ""
-- 'where' part of the cargo query
local whereQuery = ""
-- boolean just to track if it's the first where argument and if we should add ' OR ' to the query
local firstWhere = true
-- Iterate through every value in 'listOfMoves'
for i,v in ipairs(listOfMoves) do
-- If it's the first where argument, don't prefix with ' OR '
if firstWhere then
firstWhere = false
else
whereQuery = whereQuery .. " OR "
end
-- Concatenate the current whereQuery with the current moveId
whereQuery = whereQuery .. "moveId = '" .. trim(v) .. "'"
end
-- 'args' portion of cargo query
local args = {
-- 'whereQuery' from above
where = whereQuery,
-- 'order by' moveId
orderBy = "moveId"
}
-- Cargo query
local results = cargo.query( cargoTable, fields, args )
-- Iterate through all results of the query to put them into the target template
for r = 1, #results do
-- Arguments for the template
local arguments = {}
-- Iterate through all values in listOfFields
for j,k in ipairs(listOfFields) do
-- Remove all leading and trailing spaces in the value
local item = trim(k)
-- Add the passed in arguments of the current move into arguments
arguments[item] = results[r][item]
end
-- If the a description exists
if listOfDescriptions[r] and string.len(listOfDescriptions[r]) >0 then
-- Then assign the argument of index 'descriptions'
arguments['descriptions'] = trim(listOfDescriptions[r])
end
-- Add the move expanded into the target template into the wikitext
wikitext = wikitext .. frame:expandTemplate{ title = template, args = arguments }
end
-- Return the wikitext
return wikitext
end
-- Split string 's' at every 'delimiter' into an array
function split(s, delimiter)
-- Array to return
local result = {}
-- Iterate through the string finding every section split with delimiter
for match in (s..delimiter):gmatch("(.-)"..delimiter) do
-- Add the match to the result array
table.insert(result, match)
end
-- Return the result
return result
end
-- Split string 's' at every 'delimiter' into an array
function splitKeepDelimiter(s, delimiter)
-- Array to return
local result = {}
-- Boolean to check if this is the firstSplit (only applicable when keeping delimiter)
local firstSplit = true
-- Iterate through the string finding every section split with delimiter
for match in (s..delimiter):gmatch("(.-)"..delimiter) do
-- Don't add the delimiter until after the first split
if firstSplit then
firstSplit = false
else
table.insert(result, delimiter)
end
-- Remove a '%' character if it's leftover from a delimiter
local matchWithEscapedRemoved = match
if string.find(string.sub(match,-1, string.len(match)),"%%") then
mw.log(match)
matchWithEscapedRemoved = string.sub(match, 1, -2)
end
-- Add the match to the result array
table.insert(result, matchWithEscapedRemoved)
end
-- Return the result
return result
end
-- Return string 's' with all leading and trailing spaces trimmed away
function trim(s)
return (string.gsub(s, "^%s*(.-)%s*$", "%1"))
end
-- List of valid inputs to be used for p.inputsToIcons
local validInputs = {
-- Connectors
["~"] = "[[File:UNI_Input_Follow_up.png|x22px|~]]", -- Follow-up
["%+"] = "[[File:UNI_Input_Plus.png|x22px|+]]", -- Plus
["/"] = "[[File:UNI_Input_Or.png|x22px|/]]", -- Or
-- Motions
["360"] = "[[File:UNI_Input_360.png|x22px|360]]",
["41236"] = "[[File:UNI_Input_4.png|x22px|4]][[File:UNI_Input_1.png|x22px|1]][[File:UNI_Input_2.png|x22px|2]][[File:UNI_Input_3.png|x22px|3]][[File:UNI_Input_6.png|x22px|6]]",
["63214"] = "[[File:UNI_Input_6.png|x22px|6]][[File:UNI_Input_3.png|x22px|3]][[File:UNI_Input_2.png|x22px|2]][[File:UNI_Input_1.png|x22px|1]][[File:UNI_Input_4.png|x22px|4]]",
["236"] = "[[File:UNI_Input_2.png|x22px|2]][[File:UNI_Input_3.png|x22px|3]][[File:UNI_Input_6.png|x22px|6]]",
["214"] = "[[File:UNI_Input_2.png|x22px|2]][[File:UNI_Input_1.png|x22px|1]][[File:UNI_Input_4.png|x22px|4]]",
["623"] = "[[File:UNI_Input_6.png|x22px|6]][[File:UNI_Input_2.png|x22px|2]][[File:UNI_Input_3.png|x22px|3]]",
["421"] = "[[File:UNI_Input_4.png|x22px|4]][[File:UNI_Input_2.png|x22px|2]][[File:UNI_Input_1.png|x22px|1]]",
["22"] = "[[File:UNI_Input_2.png|x22px|2]][[File:UNI_Input_2.png|x22px|2]]",
["66"] = "[[File:UNI_Input_66.png|x22px|66]]",
["[4]6"] = "[[File:UNI_Input_Hold.png|x22px|]][[File:UNI_Input_4.png|x22px|[4]]][[File:UNI_Input_Then.png|x22px|]][[File:UNI_Input_6.png|x22px|6]]",
["[6]4"] = "[[File:UNI_Input_Hold.png|x22px|]][[File:UNI_Input_6.png|x22px|[6]]][[File:UNI_Input_Then.png|x22px|]][[File:UNI_Input_4.png|x22px|4]]",
["[2]8"] = "[[File:UNI_Input_Hold.png|x22px|]][[File:UNI_Input_2.png|x22px|[2]]][[File:UNI_Input_Then.png|x22px|]][[File:UNI_Input_8.png|x22px|8]]",
["[8]2"] = "[[File:UNI_Input_Hold.png|x22px|]][[File:UNI_Input_8.png|x22px|[8]]][[File:UNI_Input_Then.png|x22px|]][[File:UNI_Input_2.png|x22px|2]]",
-- Directions
["5"] = "", -- Neutral (No image needed)
["6"] = "[[File:UNI_Input_6.png|x22px|6]]", -- Forward
["3"] = "[[File:UNI_Input_3.png|x22px|3]]", -- Down-foward
["2"] = "[[File:UNI_Input_2.png|x22px|2]]", -- Down
["1"] = "[[File:UNI_Input_1.png|x22px|1]]", -- Down-back
["4"] = "[[File:UNI_Input_4.png|x22px|4]]", -- Back
["9"] = "[[File:UNI_Input_9.png|x22px|9]]", -- Up-Forward
["8"] = "[[File:UNI_Input_8.png|x22px|8]]", -- Up
["7"] = "[[File:UNI_Input_7.png|x22px|7]]", -- Up-back
-- Special Buttons
["throw"] = "[[File:UNI_Input_throw.png |x22px|throw]]",
["assault"] = "[[File:UNI_Input_assault.png|x22px|assault]]",
["cvo"] = "[[File:UNI_Input_cvo.png|x22px|cvo]]", -- Cross cast veil off
["cs"] = "[[File:UNI_Input_cs.png |x22px|cs]]", -- Chain shift
-- Special Notation
["land"] = "[[File:UNI_Input_land.png|x22px|land]]", -- Land
["jc"] = "[[File:UNI_Input_jc.png |x22px|jc]]", -- Jump cancel
-- Prefixes
["d"] = "[[File:UNI_Input_Delay.png|x22px|d]]", -- Delay
["j"] = "[[File:UNI_Input_Jump.png |x22px|j]]", -- Jump
["w"] = "[[File:UNI_Input_Whiff.png|x22px|w]]", -- Whiff
-- Buttons with '5' in alt text
["5A"] = "[[File:UNI_Input_A.png|x22px|5A]]",
["5B"] = "[[File:UNI_Input_B.png|x22px|5B]]",
["5C"] = "[[File:UNI_Input_C.png|x22px|5C]]",
["5D"] = "[[File:UNI_Input_D.png|x22px|5D]]",
["5X"] = "[[File:UNI_Input_X.png|x22px|5X]]",
-- Buttons
["A"] = "[[File:UNI_Input_A.png |x22px|A]]",
["B"] = "[[File:UNI_Input_B.png |x22px|B]]",
["C"] = "[[File:UNI_Input_C.png |x22px|C]]",
["D"] = "[[File:UNI_Input_D.png |x22px|D]]",
["X"] = "[[File:UNI_Input_X.png |x22px|X]]",
["vo"] = "[[File:UNI_Input_vo.png|x22px|vo]]", -- Veil off
["ff"] = "[[File:UNI_Input_ff.png|x22px|ff]]", -- Force function
-- Hold Buttons
["[A]"] = "[[File:UNI_Input_Hold.png|x22px|]][[File:UNI_Input_A.png|x22px|[A]]]",
["[B]"] = "[[File:UNI_Input_Hold.png|x22px|]][[File:UNI_Input_B.png|x22px|[B]]]",
["[C]"] = "[[File:UNI_Input_Hold.png|x22px|]][[File:UNI_Input_C.png|x22px|[C]]]",
["[D]"] = "[[File:UNI_Input_Hold.png|x22px|]][[File:UNI_Input_D.png|x22px|[D]]]",
["[X]"] = "[[File:UNI_Input_Hold.png|x22px|]][[File:UNI_Input_X.png|x22px|[X]]]",
["[vo]"] = "[[File:UNI_Input_vo_Hold.png|x22px|[vo]]]", -- Veil off
["[ff]"] = "[[File:UNI_Input_ff_Hold.png|x22px|[ff]]]", -- Force function
-- Release Buttons
["]A["] = "[[File:UNI_Input_A_Release.png|x22px|]A[]]",
["]B["] = "[[File:UNI_Input_B_Release.png|x22px|]B[]]",
["]C["] = "[[File:UNI_Input_C_Release.png|x22px|]C[]]",
["]D["] = "[[File:UNI_Input_D_Release.png|x22px|]D[]]",
["]X["] = "[[File:UNI_Input_X_Release.png|x22px|]X[]]",
["]vo["] = "[[File:UNI_Input_vo_Release.png|x22px|]vo[]]", -- Veil off
["]ff["] = "[[File:UNI_Input_ff_Release.png|x22px|]ff[]]", -- Force function
[" "] = "[[File:UNI_Input_next.png|x22px|>]]" -- Next Input
}
-- Change a string of characters to a list of images in wikitext format (reference above table)
function p.inputsToIcons(frame)
-- Get string
local inputText = frame.args[1]
local ret = ""
-- Check if current inputText is matching with any validInputs
local checkInputText = type(validInputs[inputText]) == "function" and validInputs[inputText]() or validInputs[inputText] or nil
-- If it doesn't match, then keep checking down
if checkInputText==nil then
-- If text contains spaces, split it down
if string.find(inputText, " ") then
local inputTextAsList = splitKeepDelimiter(inputText, " ")
for i,v in ipairs(inputTextAsList) do
ret = ret..p.inputsToIcons({args={v}})
end
-- If text contains '~', split it down
elseif string.find(inputText,"~") then
local inputTextAsList = splitKeepDelimiter(inputText, "~")
for i,v in ipairs(inputTextAsList) do
ret = ret..p.inputsToIcons({args={v}})
end
-- If text contains '+', split it down
elseif string.find(inputText,"%+") then
local inputTextAsList = splitKeepDelimiter(inputText, "%+")
for i,v in ipairs(inputTextAsList) do
ret = ret..p.inputsToIcons({args={v}})
end
-- If text contains '/', split it down
elseif string.find(inputText,"/") then
local inputTextAsList = splitKeepDelimiter(inputText, "/")
for i,v in ipairs(inputTextAsList) do
ret = ret..p.inputsToIcons({args={v}})
end
-- If text contain a digit then a letter, then split at that point
elseif string.find(inputText,"%d%a") then
local frontEnd,backEnd = string.find(inputText,"%d%a")
ret = ret..p.inputsToIcons({args={string.sub(inputText,1,frontEnd)}})..p.inputsToIcons({args={string.sub(inputText,backEnd)}})
-- If text contain a digit then a left square bracket, then split at that point
elseif string.find(inputText,"%d%[") then
local frontEnd,backEnd = string.find(inputText,"%d%[")
ret = ret..p.inputsToIcons({args={string.sub(inputText,1,frontEnd)}})..p.inputsToIcons({args={string.sub(inputText,backEnd)}})
-- If text starts with d, j, w, A, B, C, D, then split after that first character
elseif string.sub(inputText,1,1) == "d" or
string.sub(inputText,1,1) == "j" or
string.sub(inputText,1,1) == "w" or
string.sub(inputText,1,1) == "A" or
string.sub(inputText,1,1) == "B" or
string.sub(inputText,1,1) == "C" or
string.sub(inputText,1,1) == "D" then
ret = ret..p.inputsToIcons({args={string.sub(inputText,1,1)}})..p.inputsToIcons({args={string.sub(inputText,2)}})
-- Otherwise, return the text in parenthesis (Which I don't want to happen, because this would look bad if parsed poorly!!!)
else
ret = "("..inputText..")"
end
else
ret = checkInputText
end
-- Return the result
return ret
end
return p