Module:Dice: Difference between revisions
From Teriock
More actions
// via Wikitext Extension for VSCode Tags: Manual revert Reverted |
// via Wikitext Extension for VSCode Tag: Reverted |
||
| Line 1: | Line 1: | ||
-- Module:Dice | -- Module:Dice | ||
-- Processes dice input strings and outputs HTML spans with roll links, templates, and data attributes | -- Processes dice input strings and outputs HTML spans with roll links, templates, and data attributes | ||
-- Now uses mw.text.preprocess to ensure generated wikitext is fully expanded | |||
local p = {} | local p = {} | ||
| Line 92: | Line 93: | ||
local typ = frame.args[2] or "none" | local typ = frame.args[2] or "none" | ||
local parts = splitParts(fullRoll) | local parts = splitParts(fullRoll) | ||
local quickParts = {} | local quickParts, content = {}, {} | ||
for _, part in ipairs(parts) do | for _, part in ipairs(parts) do | ||
| Line 101: | Line 101: | ||
else | else | ||
local prefixCount, prefixFlag, diceCount, diceFaces, qualifiers = parsePart(part) | local prefixCount, prefixFlag, diceCount, diceFaces, qualifiers = parsePart(part) | ||
-- Build quick-roll | -- Build quick-roll | ||
if diceCount then | if diceCount then | ||
table.insert(quickParts, diceCount .. "d" .. diceFaces) | table.insert(quickParts, diceCount .. "d" .. diceFaces) | ||
end | end | ||
-- Prefix template for non-'none' types | -- Prefix template for non-'none' types | ||
if prefixFlag and typ ~= "none" and diceCount then | if prefixFlag and typ ~= "none" and diceCount then | ||
local tpl = "{{" | local tpl = string.format("{{%s%s}}", | ||
string.upper(prefixFlag), prefixCount and prefixCount ~= 1 and "|"..prefixCount or "") | |||
table.insert(content, tpl) | table.insert(content, tpl) | ||
end | end | ||
-- Dice link or standalone prefix | |||
-- | |||
if diceCount then | if diceCount then | ||
local | local display = diceCount == 1 and ("d"..diceFaces) or (diceCount.."d"..diceFaces) | ||
local | local label = display | ||
if prefixFlag and typ == "none" and #qualifiers == 0 then | if prefixFlag and typ == "none" and #qualifiers == 0 then | ||
label = (prefixCount or 1) .. string.upper(prefixFlag) .. display | |||
end | end | ||
table.insert(content, | |||
string.format("[https://dice.run/#/d/%dd%s %s]", diceCount, diceFaces, label) | |||
elseif prefixFlag | ) | ||
elseif prefixFlag and typ ~= "none" then | |||
table.insert(content, "{{" | table.insert(content, string.format("{{%s}}", string.upper(prefixFlag))) | ||
end | end | ||
-- Qualifier labels | -- Qualifier labels | ||
for _, q in ipairs(qualifiers) do | for _, q in ipairs(qualifiers) do | ||
table.insert(content, "{{L|" | table.insert(content, string.format("{{L|%s|%s}}", capitalize(typ), capitalize(q))) | ||
end | end | ||
end | end | ||
end | end | ||
local inner = table.concat(content) | local inner = table.concat(content) | ||
local quick = table.concat(quickParts, " ") | |||
-- | -- Build span and preprocess | ||
local | local raw = html.create('span') | ||
:addClass('dice') | :addClass('dice') | ||
:attr('data-full-roll', fullRoll) | :attr('data-full-roll', fullRoll) | ||
:attr('data-quick-roll', | :attr('data-quick-roll', quick) | ||
:attr('data-type', typ) | :attr('data-type', typ) | ||
:wikitext(inner) | :wikitext(inner) | ||
:allDone() | |||
return text.preprocess(raw) | |||
return | |||
end | end | ||
return p | return p | ||
Revision as of 23:25, 19 June 2025
Documentation for this module may be created at Module:Dice/doc
-- Module:Dice
-- Processes dice input strings and outputs HTML spans with roll links, templates, and data attributes
-- Now uses mw.text.preprocess to ensure generated wikitext is fully expanded
local p = {}
local html = mw.html
local text = mw.text
-- Trim whitespace from both ends
local function trim(s)
return (s:gsub("^%s*(.-)%s*$", "%1"))
end
-- Split the full roll string into parts and operators (+, -)
local function splitParts(s)
local parts = {}
local i = 1
while i <= #s do
local c = s:sub(i,i)
if c == "+" or c == "-" then
table.insert(parts, c)
i = i + 1
elseif c == " " then
i = i + 1
else
local j = s:find("[%+%-]", i)
if j then
table.insert(parts, trim(s:sub(i, j-1)))
i = j
else
table.insert(parts, trim(s:sub(i)))
break
end
end
end
return parts
end
-- Capitalize first letter
local function capitalize(s)
return (s:gsub("^%l", string.upper))
end
-- Parse an individual part into prefix, dice, and qualifiers
local function parsePart(part)
local s = trim(part)
local prefixCount, prefixFlag
local diceCount, diceFaces
local qualifiers = {}
-- Extract qualifiers in [brackets]
local main, qualStr = s:match("^(.-)%[([^%]]+)%]$")
if qualStr then
s = trim(main)
for q in qualStr:gmatch("([^ ]+)") do
table.insert(qualifiers, q)
end
end
-- Extract parenthesized prefix, e.g. (2@p) or (@f)
local pref = s:match("^%(([%d]*@%a+)%)")
if pref then
local num, flag = pref:match("^(%d*)@(%a+)")
prefixCount = tonumber(num) or 1
prefixFlag = flag
s = s:gsub("^%b()", "", 1)
else
-- Pure prefix without dice
local pure = s:match("^@(%a+)$")
if pure then
prefixCount = 1
prefixFlag = pure
s = ""
end
end
-- Extract dice, e.g. 2d6 or d8
if s:match("^d%d+") then
diceCount = 1
diceFaces = s:match("^d(%d+)")
elseif s:match("^%d+d%d+") then
local cnt, faces = s:match("^(%d+)d(%d+)")
diceCount = tonumber(cnt)
diceFaces = faces
end
return prefixCount, prefixFlag, diceCount, diceFaces, qualifiers
end
-- Main entry for #invoke:Dice|d|<roll>|<type>
function p.d(frame)
local fullRoll = frame.args[1] or ""
local typ = frame.args[2] or "none"
local parts = splitParts(fullRoll)
local quickParts, content = {}, {}
for _, part in ipairs(parts) do
if part == "+" or part == "-" then
table.insert(quickParts, part)
table.insert(content, " " .. part .. " ")
else
local prefixCount, prefixFlag, diceCount, diceFaces, qualifiers = parsePart(part)
-- Build quick-roll
if diceCount then
table.insert(quickParts, diceCount .. "d" .. diceFaces)
end
-- Prefix template for non-'none' types
if prefixFlag and typ ~= "none" and diceCount then
local tpl = string.format("{{%s%s}}",
string.upper(prefixFlag), prefixCount and prefixCount ~= 1 and "|"..prefixCount or "")
table.insert(content, tpl)
end
-- Dice link or standalone prefix
if diceCount then
local display = diceCount == 1 and ("d"..diceFaces) or (diceCount.."d"..diceFaces)
local label = display
if prefixFlag and typ == "none" and #qualifiers == 0 then
label = (prefixCount or 1) .. string.upper(prefixFlag) .. display
end
table.insert(content,
string.format("[https://dice.run/#/d/%dd%s %s]", diceCount, diceFaces, label)
)
elseif prefixFlag and typ ~= "none" then
table.insert(content, string.format("{{%s}}", string.upper(prefixFlag)))
end
-- Qualifier labels
for _, q in ipairs(qualifiers) do
table.insert(content, string.format("{{L|%s|%s}}", capitalize(typ), capitalize(q)))
end
end
end
local inner = table.concat(content)
local quick = table.concat(quickParts, " ")
-- Build span and preprocess
local raw = html.create('span')
:addClass('dice')
:attr('data-full-roll', fullRoll)
:attr('data-quick-roll', quick)
:attr('data-type', typ)
:wikitext(inner)
:allDone()
return text.preprocess(raw)
end
return p