More actions
Content deleted Content added
// via Wikitext Extension for VSCode Tag: Reverted |
// via Wikitext Extension for VSCode Tag: Manual revert |
||
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 |
||
-- Attempts to preprocess generated wikitext when available, with fallback to raw output |
|||
local p = {} |
local p = {} |
||
local html = mw.html |
local html = mw.html |
||
local |
local text = mw.text |
||
-- Trim whitespace from both ends |
-- Trim whitespace from both ends |
||
Line 14: | Line 13: | ||
-- Split the full roll string into parts and operators (+, -) |
-- Split the full roll string into parts and operators (+, -) |
||
local function splitParts(s) |
local function splitParts(s) |
||
local parts |
local parts = {} |
||
local i = 1 |
|||
while i <= #s do |
while i <= #s do |
||
local c = s:sub(i,i) |
local c = s:sub(i,i) |
||
Line 44: | Line 44: | ||
local function parsePart(part) |
local function parsePart(part) |
||
local s = trim(part) |
local s = trim(part) |
||
local prefixCount, prefixFlag |
local prefixCount, prefixFlag |
||
local diceCount, diceFaces |
|||
local qualifiers = {} |
|||
-- Extract qualifiers in [brackets] |
-- Extract qualifiers in [brackets] |
||
Line 90: | Line 92: | ||
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 = {} |
||
local content = {} |
|||
for _, part in ipairs(parts) do |
for _, part in ipairs(parts) do |
||
Line 98: | 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 sequence (ignore flags) |
||
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.upper(prefixFlag) |
||
if prefixCount and prefixCount ~= 1 then tpl = tpl .. "|" .. prefixCount end |
|||
tpl = tpl .. "}}" |
|||
table.insert(content, tpl) |
table.insert(content, tpl) |
||
end |
end |
||
-- Dice link or standalone prefix |
|||
⚫ | |||
if diceCount then |
if diceCount then |
||
local |
local displayDice = (diceCount == 1) and ("d" .. diceFaces) or (diceCount .. "d" .. diceFaces) |
||
local |
local linkLabel = displayDice |
||
-- Embed prefix in label when type='none' and no qualifiers |
|||
if prefixFlag and typ == "none" and #qualifiers == 0 then |
if prefixFlag and typ == "none" and #qualifiers == 0 then |
||
linkLabel = (prefixCount or 1) .. string.upper(prefixFlag) .. displayDice |
|||
end |
end |
||
⚫ | |||
table.insert(content, |
table.insert(content, link) |
||
⚫ | |||
elseif prefixFlag and not diceCount and typ ~= "none" then |
|||
) |
|||
-- Standalone prefix (no dice) |
|||
table.insert(content, |
table.insert(content, "{{" .. string.upper(prefixFlag) .. "}}") |
||
end |
end |
||
-- Qualifier labels |
-- Qualifier labels |
||
for _, q in ipairs(qualifiers) do |
for _, q in ipairs(qualifiers) do |
||
table.insert(content, |
table.insert(content, "{{L|" .. capitalize(typ) .. "|" .. capitalize(q) .. "}}") |
||
end |
end |
||
end |
end |
||
end |
end |
||
-- Combine quick-roll and inner wikitext |
|||
⚫ | |||
local inner = table.concat(content) |
local inner = table.concat(content) |
||
⚫ | |||
-- Construct span via mw.html for proper parsing |
|||
⚫ | |||
local |
local span = 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', quickRoll) |
||
:attr('data-type', typ) |
:attr('data-type', typ) |
||
:wikitext(inner) |
:wikitext(inner) |
||
:allDone() |
|||
-- Preprocess the generated HTML+wikitext so MediaWiki parses templates correctly |
|||
-- Attempt to preprocess; fallback to raw if unavailable |
|||
local |
local output = span:allDone() |
||
-- return frame:preprocess(output) |
|||
if f and type(f.preprocess) == 'function' then |
|||
return output |
|||
else |
|||
return raw |
|||
end |
|||
end |
end |
||
Revision as of 23:27, 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
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 = {}
local 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 sequence (ignore flags)
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.upper(prefixFlag)
if prefixCount and prefixCount ~= 1 then tpl = tpl .. "|" .. prefixCount end
tpl = tpl .. "}}"
table.insert(content, tpl)
end
-- Build dice link
if diceCount then
local displayDice = (diceCount == 1) and ("d" .. diceFaces) or (diceCount .. "d" .. diceFaces)
local linkLabel = displayDice
-- Embed prefix in label when type='none' and no qualifiers
if prefixFlag and typ == "none" and #qualifiers == 0 then
linkLabel = (prefixCount or 1) .. string.upper(prefixFlag) .. displayDice
end
local link = string.format("[https://dice.run/#/d/%dd%s %s]", diceCount, diceFaces, linkLabel)
table.insert(content, link)
elseif prefixFlag and not diceCount and typ ~= "none" then
-- Standalone prefix (no dice)
table.insert(content, "{{" .. string.upper(prefixFlag) .. "}}")
end
-- Qualifier labels
for _, q in ipairs(qualifiers) do
table.insert(content, "{{L|" .. capitalize(typ) .. "|" .. capitalize(q) .. "}}")
end
end
end
-- Combine quick-roll and inner wikitext
local quickRoll = table.concat(quickParts, " ")
local inner = table.concat(content)
-- Construct span via mw.html for proper parsing
local span = html.create('span')
:addClass('dice')
:attr('data-full-roll', fullRoll)
:attr('data-quick-roll', quickRoll)
:attr('data-type', typ)
:wikitext(inner)
-- Preprocess the generated HTML+wikitext so MediaWiki parses templates correctly
local output = span:allDone()
-- return frame:preprocess(output)
return output
end
return p