Difference between revisions of "Module:Factory slot"
Jump to navigation
Jump to search
(Add `title` attribute to item count and disable inline styles) |
(Fix support for Tier suffixes) |
||
| Line 11: | Line 11: | ||
display: inline-block; | display: inline-block; | ||
border: 1px solid black; | border: 1px solid black; | ||
| + | background-color: rgba(255, 255, 255, 0.4); | ||
width: 32px; | width: 32px; | ||
height: 32px; | height: 32px; | ||
padding: 8px; | padding: 8px; | ||
| + | margin: -1px; | ||
line-height: 1; | line-height: 1; | ||
| + | ]], | ||
| + | |||
| + | [".factoryslot.locked"] = [[ | ||
| + | background-color: #333; | ||
| + | ]], | ||
| + | |||
| + | [".factoryslot.factoryslot-large"] = [[ | ||
| + | padding: 12px; | ||
]], | ]], | ||
| Line 26: | Line 36: | ||
]], | ]], | ||
| − | [". | + | [".factoryslot-item-image"] = [[ |
image-rendering: crisp-edges; | image-rendering: crisp-edges; | ||
image-rendering: pixelated; | image-rendering: pixelated; | ||
| Line 104: | Line 114: | ||
end | end | ||
| − | local img = | + | local escapedName = name:gsub("%[(T%d+)%]$", "[%1]"); |
| + | local pageName = name:gsub("%[(T%d+)%]$", "%1"); | ||
| + | local img = pageName .. ".png"; | ||
local link = args.link; | local link = args.link; | ||
| Line 113: | Line 125: | ||
end | end | ||
| − | local altText = img .. ": The Perfect Tower 2 Factory inventory icon of " .. | + | local altText = img .. ": The Perfect Tower 2 Factory inventory icon of " .. escapedName; |
if (link) then | if (link) then | ||
| − | altText = altText .. " linking to " .. link | + | altText = altText .. " linking to " .. link; |
end | end | ||
item:addClass("pixel-image") | item:addClass("pixel-image") | ||
| − | -- :cssText(styles[". | + | -- :cssText(styles[".factoryslot-item-image"]) |
| − | :wikitext("[[File:", img, "|32x32px|link=", link or "", "|alt=", altText, "|", | + | :wikitext("[[File:", img, "|32x32px|link=", link or "", "|alt=", altText, "|", escapedName, "]]"); |
local count = stack.count; | local count = stack.count; | ||
| Line 145: | Line 157: | ||
end | end | ||
p._makeItem = makeItem; | p._makeItem = makeItem; | ||
| + | |||
| + | local function fixTier(name) | ||
| + | local prefix, tier; | ||
| + | prefix, tier = name:match("^%s*(.*) (T%d+)%s*$"); | ||
| + | if (tier) then | ||
| + | name = prefix .. " [" .. tier .. "]"; | ||
| + | else | ||
| + | name = mw.text.trim(name) | ||
| + | end | ||
| + | return name; | ||
| + | end | ||
--- Parses an Item Stack Definition into an ItemStack table | --- Parses an Item Stack Definition into an ItemStack table | ||
| Line 158: | Line 181: | ||
-- Simple stack definition with no parts or reserved characters | -- Simple stack definition with no parts or reserved characters | ||
if (not string.match(itemStackDesc, "[:,]")) then | if (not string.match(itemStackDesc, "[:,]")) then | ||
| − | return { name = itemStackDesc }; | + | return { name = fixTier(itemStackDesc) }; |
end | end | ||
| Line 171: | Line 194: | ||
end | end | ||
if (count) then | if (count) then | ||
| − | + | name = mw.text.trim(name); | |
if (count >= 1e18) then | if (count >= 1e18) then | ||
count = math.huge; | count = math.huge; | ||
| Line 179: | Line 202: | ||
stack.count = count; | stack.count = count; | ||
else | else | ||
| − | + | name = mw.text.trim(itemStackDesc); | |
end | end | ||
| + | stack.name = fixTier(name); | ||
return stack; | return stack; | ||
Revision as of 14:01, 21 April 2026
Documentation for this module may be created at Module:Factory slot/doc
-- Used to render Factory inventory slots
-- Inspired by and partially based on Minecraft Wiki's [[Module:Inventory slot]]
require("Module:No globals");
local checkType = require("libraryUtil").checkType;
local ustr = mw.ustring;
local INFINITY = "∞";
-- Workaround until this wiki gets TemplateStyles
local styles = {
[".factoryslot"] = [[
display: inline-block;
border: 1px solid black;
background-color: rgba(255, 255, 255, 0.4);
width: 32px;
height: 32px;
padding: 8px;
margin: -1px;
line-height: 1;
]],
[".factoryslot.locked"] = [[
background-color: #333;
]],
[".factoryslot.factoryslot-large"] = [[
padding: 12px;
]],
[".factoryslot-item"] = [[
display: block;
position: relative;
width: 32px;
height: 32px;
margin: -4px;
padding: 4px;
]],
[".factoryslot-item-image"] = [[
image-rendering: crisp-edges;
image-rendering: pixelated;
]],
[".factoryslot-item .factoryslot-stacksize"] = [[
position: absolute;
bottom: 0;
right: 0;
white-space: nowrap;
font-family: sans-serif !important;
font-style: normal !important;
]],
};
local p = {};
--- Formats the item stack count
--- @param count integer
--- @return string|nil
function p.formatCount(count)
checkType('"Module:Factory slot".formatCount', 1, count, "number");
count = math.floor(count);
if (count >= 1e18) then
return INFINITY;
end
if (count < 2) then
return nil;
end
if (count < 1e6) then
-- less than a million
return tostring(count);
end
local exp = 3;
while true do
exp = exp + 3;
count = math.floor(count / 1e3 + 0.5);
if (count < 1e6 or exp == 15) then
--- @type string, string
local result, b = tostring(count):match("^(%d-%d)(%d%d%d)$");
b = b:gsub("0+$", "");
if (b ~= "") then
result = result .. "." .. b;
end
result = result .. "e" .. exp;
return result;
end
end
end
--- @class ItemStack
--- @field name string
--- @field count? number
--- Creates the actual HTML node for a given item stack
---
--- @param stack ItemStack
--- @param args? table
local function makeItem(stack, args)
args = args or {}
local item = mw.html.create("span")
:addClass("factoryslot-item")
:addClass(args.itemClass)
-- :cssText(styles[".factoryslot-item"])
:cssText(args.itemStyle);
local name = stack.name;
if ((name or "") == "") then
-- Empty stack
return nil;
end
local escapedName = name:gsub("%[(T%d+)%]$", "[%1]");
local pageName = name:gsub("%[(T%d+)%]$", "%1");
local img = pageName .. ".png";
local link = args.link;
if ((link or "") == "") then
link = nil;
elseif (string.lower(link) == "no") then
link = nil;
end
local altText = img .. ": The Perfect Tower 2 Factory inventory icon of " .. escapedName;
if (link) then
altText = altText .. " linking to " .. link;
end
item:addClass("pixel-image")
-- :cssText(styles[".factoryslot-item-image"])
:wikitext("[[File:", img, "|32x32px|link=", link or "", "|alt=", altText, "|", escapedName, "]]");
local count = stack.count;
if (count and count > 1) then
count = p.formatCount(count);
if (count ~= nil) then
if (link) then
item:wikitext("[[", link, "|");
end
local number = item:tag("span")
:addClass("factoryslot-stacksize")
-- :cssText(styles[".factoryslot-item .factoryslot-stacksize"])
:attr("title", name)
:wikitext(count);
number:cssText(args.numStyle);
if (link) then
item:wikitext("]]");
end
end
end
return item;
end
p._makeItem = makeItem;
local function fixTier(name)
local prefix, tier;
prefix, tier = name:match("^%s*(.*) (T%d+)%s*$");
if (tier) then
name = prefix .. " [" .. tier .. "]";
else
name = mw.text.trim(name)
end
return name;
end
--- Parses an Item Stack Definition into an ItemStack table
---
--- Syntax:
--- ```text
--- <Name:string> ( ',' <Count:number> )?
--- ```
---
--- @param itemStackDesc string
--- @return ItemStack
function p.parseStack(itemStackDesc)
-- Simple stack definition with no parts or reserved characters
if (not string.match(itemStackDesc, "[:,]")) then
return { name = fixTier(itemStackDesc) };
end
local stack = {};
local name, count;
name, count = ustr.match(itemStackDesc, "^%s*(.*),%s*([" .. INFINITY .. "0-9%.e]+)%s*$");
if (count == INFINITY) then
count = math.huge;
else
count = count and tonumber(count);
end
if (count) then
name = mw.text.trim(name);
if (count >= 1e18) then
count = math.huge;
else
count = math.floor(count);
end
stack.count = count;
else
name = mw.text.trim(itemStackDesc);
end
stack.name = fixTier(name);
return stack;
end
--- Stringifies an ItemStack table into an Item Stack Definition string
---
--- @param itemStack ItemStack
--- @return string
function p.stringifyStack(itemStack)
local name = itemStack.name;
local count = itemStack.count;
local result = name;
if (count and count >= 0) then
if (count >= 1e18) then
count = INFINITY;
else
count = tostring(count);
end
result = result .. "," .. count;
end
return result;
end
--- Main entry point.
--- Builds the HTML for a Factory inventory slot.
---
--- @param args any
function p.slot(args)
local stack = args[1];
if (type(stack) == "string") then
stack = p.parseStack(stack);
end
local body = mw.html.create("span")
:addClass("factoryslot")
:addClass(args.class)
-- :cssText(styles[".factoryslot"])
:cssText(args.style);
if (not stack) then
return body;
end
body:node(makeItem(stack, args));
return body;
end
-- Main template entry point.
function p.main(frame)
return p.slot(require("Module:Arguments").getArgs(frame, {
frameOnly = false,
wrappers = { "Template:Factory slot" },
}));
end
return p;