Module:Data Table/Tags

local File = require("Module:File") local Franchise = require("Module:Franchise") local GalleryList = require("Module:Gallery List") local Sequences = require("Module:Sequences") local Term = require("Module:Term") local TermList = require("Module:Term List") local utilsMarkup = require("Module:UtilsMarkup") local utilsString = require("Module:UtilsString") local utilsTable = require("Module:UtilsTable")

local frame = mw.getCurrentFrame

local playerNameOutput local function playerName return playerNameOutput or frame:expandTemplate({		title = "Player Name"	}) end

local function list(items, listType) if listType == "*" then return utilsMarkup.bulletList(items) elseif listType == "#" then return utilsMarkup.numberList(items) elseif listType == "plain" then return utilsMarkup.list(items) elseif #items > 1 then return utilsMarkup.list(items) else return items[1] end end

local function value(templateName, hasGameParam) return { formatter = function(cell, tableArgs, tagArgs) local values = utilsString.split(cell, '%s*,[%D+|%s*]') local amountGame = tableArgs.game or tagArgs[1] local format = tagArgs[2] local cellSize = 0 local sortValue values = utilsTable.map(values, function(value)				local value, info = utilsMarkup.separateMarkup(value)				if #values == 1 then					sortValue = value:gsub(",", "")				end				cellSize = math.max(cellSize, value:len)				local args = {value, format}				if hasGameParam then					table.insert(args, 1, amountGame)				end				local text = frame:expandTemplate({ title = templateName, args = args, })				return text..info			end) local valuesList = list(values, "plain") return { text = valuesList, size = cell:len, sortValue = sortValue }		end } end

local function terms(tagName, plural) return { formatter = function(cell, tableArgs, tagArgs) local game = tagArgs[1] or tableArgs.game cell = string.gsub(cell, "%[Player Name%]", "Link") local pages if tagName == "Term" or tagName == "Plural" then pages = {cell} else pages = utilsString.split(cell) end local entries = utilsTable.map(pages, function(page)				-- We use GalleryList here because we have to be aware of any GalleryList syntax that could be present in the cell, 				-- which may be the case if the [Image] tag is also applied to the column				return GalleryList.parseEntry(page, game, "", { plural = plural, link = true })			end) local cellSize = 0 for i, entry in ipairs(entries) do				local term = entry.term or "" cellSize = math.max(term:len, cellSize) end local isBulletList = tagName == "TermList" or tagName == "PluralList" local links = utilsTable.map(entries, "link") local list = list(links, isBulletList and "*" or "plain") local sortValue if #entries == 1 then sortValue = entries[1].term end return { text = list, sortValue = sortValue, size = cellSize }		end } end

local spanningCellsByColumn = {} local spanCountsByColumn = {} function computeRowspan(cell) local columnIndex = cell.columnIndex if not columnIndex then return end local spanningCell = spanningCellsByColumn[columnIndex] local spanCount = spanCountsByColumn[columnIndex] if not spanningCell then spanningCell = cell spanCount = 1 elseif tostring(cell.content) == tostring(spanningCell.content) then cell.skip = true spanCount = spanCount + 1 else spanningCell.rowspan = spanCount spanningCell = cell spanCount = 1 end if cell.isLastRow then spanningCell.rowspan = spanCount end spanCountsByColumn[columnIndex] = spanCount spanningCellsByColumn[columnIndex] = spanningCell end

-- So that the template is evaluated at most once per page local NA function notApplicable NA = NA or mw.getCurrentFrame:expandTemplate({ title = "NA" }) return NA end

local p = { -- formatter (required): a function that returns an object with the following properties: -- - text (required): the text to display in the cell -- - size (optional): an estimation of the cell's width in characters -- - sortValue (optional): a column sort value — column is unsortable if false, sorted by its content if nil

-- noCopy (optional): if set to true, the tag will not be automatically carried over to copies of the table contentTags = { [""] = {			formatter = function(cell) -- default: no tags local text = string.gsub(cell, "%[Player Name%]", playerName) local sortValue local markupStripped = string.gsub(text, "'", "") -- strip any bold or italics formatting local leadingNumber = string.match(markupStripped, "^(%d[%d,]*)") if leadingNumber then leadingNumber = string.gsub(leadingNumber, ",", "") leadingNumber = tonumber(leadingNumber) sortValue = leadingNumber end return { text = cell, size = cell:len, sortValue = sortValue, }			end, },		["EmptyCell"] = { formatter = function(cell) -- special case: empty cell return { text = " ", sortValue = "", size = 0, }			end, },		["NotApplicable"] = { formatter = function(cell) -- special case: cell starts with N/A local text, info = utilsMarkup.separateMarkup(cell) text = text:gsub("N/A", notApplicable) return { text = text..info, sortValue = text, size = cell:len, }			end, },

["Amounts"] = { formatter = function(cell, tableArgs, tagArgs) local text = frame:expandTemplate({					title = "Amounts",					args = {tableArgs.game, cell}				}) local cellSize = 0 local amounts = utilsString.split(cell, '%s*,[%D+|%s*]') for i, amount in ipairs(amounts) do					local item = string.gsub(amount, "$[%d,]+ ", "") local subject, info = utilsMarkup.separateMarkup(item) cellSize = math.max(cellSize, subject:len) end return { text = text, size = cellSize, sortValue = false, }			end, },		["Code"] = { formatter = function(cell, tableArgs, tagArgs) local value, info = utilsMarkup.separateMarkup(cell) return { text = " "..info, size = value:len, }			end, },		["Defense"] = value("Defense", true), ["Description"] = { formatter = function(cell, tableArgs, tagArgs) local text = string.gsub(cell, "%[Player Name%]", playerName) text = "\n"..text.."\n" -- bullet lists don't work without the newlines return { text = text, size = cell:len, sortValue = false, }			end, },		["Effect"] = value("Effect", false), ["HeartAmount"] = { formatter = function(cell, tableArgs, tagArgs) local text = frame:expandTemplate({					title = "HeartAmount",					args = {cell, "true"}				}) return { text = text, size = 12, sortValue = cell }			end, },		["IconList"] = { formatter = function(cell, tableArgs, tagArgs) local cellSize = 0 local listItems = utilsString.split(cell) for i, listItem in ipairs(listItems) do					cellSize = math.max(listItem:len, cellSize) end local iconList = frame:expandTemplate({					title = "Icon List",					args = {tableArgs.game, cell}				}) return { text = iconList, size = cellSize, sortValue = false, }			end, },		["Image"] = { formatter = function(cell, tableArgs, tagArgs) cell = string.gsub(cell, "%[Player Name%]", "Link") local fileType = tagArgs[1] or Franchise.graphics(tableArgs.game) == "2D" and "Sprite" or "Icon" local entry = GalleryList.parseEntry(cell, tableArgs.game, fileType, {					useTerms = false,				}) local image = File.image(entry.file, {					size = tagArgs[2] or "64x64px",					checkExists = false,				}) return { text = image, size = 20, sortValue = false, }			end, },		["List"] = { formatter = function(cell, tableArgs, tagArgs) local listItems = utilsString.split(cell, '%s*,[%D+|%s*]') local cellSize = 0 for i, listItem in ipairs(listItems) do					cellSize = math.max(cellSize, listItem:len) end local list = list(listItems, tagArgs[1] or "*") return { text = list, sortValue = false, }			end, },		["Mon"] = value("Mon", false), ["Name"] = { formatter = function(cell, tableArgs, tagArgs) local cellSize = cell:len -- We use GalleryList here because we have to be aware of any GalleryList syntax that could be present in the cell, -- which may be the case if the [Image] tag is also applied to the column -- We have to escape the brackets in [Player Name] so that GalleryList doesn't parse it as a variant local text = string.gsub(cell, "%[Player Name%]", "{Player Name}") local entry = GalleryList.parseEntry(text, "", "", {					useTerms = false				}) local text = string.gsub(entry.subject, "{Player Name}", playerName) return { text = text, }			end, },		["Plural"] = terms("Plural", true), ["PluralList"] = terms("PluralList", true), ["Rupees"] = value("Rupee", true), ["SortValue"] = { formatter = function(cell, tableArgs, tagArgs) cell = string.gsub(cell, "%[Player Name%]", "Link") local sortValue = Sequences.sortValue(tableArgs.game, nil, cell) local termLink = Term.link(cell, tableArgs.game) return { size = cell:len, text = termLink, sortValue = sortValue, }			end, },		["SyntaxHighlight"] = { formatter = function(cell, tableArgs, tagArgs) local text, notes = utilsMarkup.separateMarkup(cell) local codeBlock = frame:extensionTag({					name = "syntaxhighlight",					args = {						inline = true,						lang = tagArgs[1] or "lua"					},					content = text				}) return { text = codeBlock..notes, size = text:len, }			end, },		["Term"] = terms("Term"), ["Terms"] = terms("Terms"), ["TermList"] = terms("TermList"), ["Transcript"] = { formatter = function(cell, tableArgs, tagArgs) local text = string.gsub(cell, "%[Player Name%]", playerName) text = "\n"..text.."\n" -- bullet lists don't work without the newlines return { text = text, size = cell:len, sortValue = false, }			end, },	},	attributeTags = { ["ID"] = { formatter = function(cell, tableArgs, tagArgs) cell.id = string.gsub(cell.raw, "%[Player Name%]", "Link") end, },		["Nowrap"] = { formatter = function(cell, tableArgs, tagArgs) cell.content:addClass("data-table__cell-content--nowrap") end, },		["Rowspan"] = { formatter = function(cell, tableArgs, tagArgs) computeRowspan(cell) end, },		["Unsortable"] = { formatter = function(cell, tableArgs, tagArgs) cell.sortValue = false end, },		["Width"] = { noCopy = true, formatter = function(cell, tableArgs, tagArgs) cell.styles = cell.styles or {} cell.styles["width"] = tagArgs[1] end, },	} }

return p