Jump to content

Module:PadUtils: Difference between revisions

From PAD Wiki
No edit summary
No edit summary
Line 1: Line 1:
-- Module:PadUtils
local p = {}
local p = {}


-- split "A;B;C" safely (ignores empty pieces)
local function split(text, delim)
local function split(text, delim)
     local out = {}
     local out = {}
Line 13: Line 11:
end
end


-- Extract target + label from one item.
-- Accepts any of:
--  "Floor Name"
--  "Floor_Target|Floor Label"
--  "[[Dungeon/Floor_Target|Floor Label]]"
--  "[[Floor_Target|Floor Label]]"
local function parseItem(item)
local function parseItem(item)
    -- Strip [[...]] if present
     local inner = item:match("^%[%[(.*)%]%]$")
     local inner = item:match("^%[%[(.*)%]%]$")
     if inner then item = inner end
     if inner then item = inner end
    -- Split on pipe "|"
     local t, l = item:match("^(.-)|(.*)$")
     local t, l = item:match("^(.-)|(.*)$")
     local target = mw.text.trim(t or item)
     local target = mw.text.trim(t or item)
Line 30: Line 20:
end
end


-- Normalize a target so it is ALWAYS a subpage of `base`.
-- If the target already includes "base/", strip that prefix.
-- Otherwise, we treat target as just the floor segment.
local function normalizeTarget(base, target)
local function normalizeTarget(base, target)
    -- Remove leading/trailing spaces
     target = mw.text.trim(target)
     target = mw.text.trim(target)
    -- If target is like "Base/Floor" (with spaces or underscores), strip the base part
    -- Compare case-sensitively (MediaWiki titles are case-sensitive after the first char)
     local withSlash = base .. "/"
     local withSlash = base .. "/"
     if target:sub(1, #withSlash) == withSlash then
     if target:sub(1, #withSlash) == withSlash then
         target = target:sub(#withSlash + 1)
         target = target:sub(#withSlash + 1)
     end
     end
 
     return base .. "/" .. target
     -- Final title is ALWAYS base/target
    local titleText = base .. "/" .. target
    return titleText
end
end


-- Build a UL/OL list of HTML <a> links: base/floor
-- Args:
--  base  : page prefix; default = FULLPAGENAME (the dungeon page)
--  floors : "Floor A;Floor B" or "Floor_Target|Label" or wiki links
--  ol    : "1"/"true" -> <ol>, otherwise <ul>
--  before : optional text before each label (display only)
--  after  : optional text after each label  (display only)
function p.dungeonFloors(frame)
function p.dungeonFloors(frame)
     local args    = frame.args
     local args    = frame.args
Line 66: Line 39:
     if #floors == 0 then return "" end
     if #floors == 0 then return "" end


     local items = {}
    -- Use mw.html so MediaWiki treats the output as safe HTML
     local list = mw.html.create(listTag)
 
     for _, raw in ipairs(floors) do
     for _, raw in ipairs(floors) do
         local target, label = parseItem(raw)
         local target, label = parseItem(raw)
        -- Normalize to always "base/floor"
         local titleText = normalizeTarget(base, target)
         local titleText = normalizeTarget(base, target)
         local titleObj  = mw.title.new(titleText)
         local titleObj  = mw.title.new(titleText)
        local url = titleObj and titleObj:fullUrl() or ("/wiki/" .. mw.uri.encode(titleText))


         -- Build URL safely
         list:tag("li")
        local url = titleObj and titleObj:localUrl()
             :tag("a")
             or ("/wiki/" .. mw.uri.encode(titleText))
                :attr("href", url)
 
                :wikitext(before .. label .. after)
        -- Encode label for HTML (avoid breaking if label has special chars)
             :done()
        local linkText = before .. label .. after
         :done()
        table.insert(items,
             '<li><a href="' .. url .. '">' .. mw.text.encode(linkText) .. '</a></li>'
         )
     end
     end


     return '<' .. listTag .. '>' .. table.concat(items) .. '</' .. listTag .. '>'
     return tostring(list) -- ensures proper HTML rendering
end
end


return p
return p

Revision as of 04:45, 22 August 2025

Documentation for this module may be created at Module:PadUtils/doc

local p = {}

local function split(text, delim)
    local out = {}
    if not text or text == "" then return out end
    for part in mw.text.gsplit(text, delim, true) do
        part = mw.text.trim(part)
        if part ~= "" then table.insert(out, part) end
    end
    return out
end

local function parseItem(item)
    local inner = item:match("^%[%[(.*)%]%]$")
    if inner then item = inner end
    local t, l = item:match("^(.-)|(.*)$")
    local target = mw.text.trim(t or item)
    local label  = mw.text.trim(l or item)
    return target, label
end

local function normalizeTarget(base, target)
    target = mw.text.trim(target)
    local withSlash = base .. "/"
    if target:sub(1, #withSlash) == withSlash then
        target = target:sub(#withSlash + 1)
    end
    return base .. "/" .. target
end

function p.dungeonFloors(frame)
    local args    = frame.args
    local base    = args.base and mw.text.trim(args.base) or mw.title.getCurrentTitle().fullText
    local floors  = split(args.floors or "", ";")
    local listTag = (args.ol == "1" or args.ol == "true") and "ol" or "ul"
    local before  = args.before or ""
    local after   = args.after or ""

    if #floors == 0 then return "" end

    -- Use mw.html so MediaWiki treats the output as safe HTML
    local list = mw.html.create(listTag)

    for _, raw in ipairs(floors) do
        local target, label = parseItem(raw)
        local titleText = normalizeTarget(base, target)
        local titleObj  = mw.title.new(titleText)
        local url = titleObj and titleObj:fullUrl() or ("/wiki/" .. mw.uri.encode(titleText))

        list:tag("li")
            :tag("a")
                :attr("href", url)
                :wikitext(before .. label .. after)
            :done()
        :done()
    end

    return tostring(list)  -- ensures proper HTML rendering
end

return p