Jump to content

Module:PadUtils: Difference between revisions

From PAD Wiki
No edit summary
No edit summary
Line 2: Line 2:
local p = {}
local p = {}


-- Split helper (ignores empty parts)
-- 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 13:
end
end


-- Build a UL/OL list of <a> links that point to subpages of `base`.
-- 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)
    -- Strip [[...]] if present
    local inner = item:match("^%[%[(.*)%]%]$")
    if inner then item = inner end
    -- Split on pipe "|"
    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
 
-- 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)
    -- Remove leading/trailing spaces
    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 .. "/"
    if target:sub(1, #withSlash) == withSlash then
        target = target:sub(#withSlash + 1)
    end
 
    -- Final title is ALWAYS base/target
    local titleText = base .. "/" .. target
    return titleText
end
 
-- Build a UL/OL list of HTML <a> links: base/floor
-- Args:
-- Args:
--  base  : page prefix; default = current page (FULLPAGENAME)
--  base  : page prefix; default = FULLPAGENAME (the dungeon page)
--  floors : "A;B;C" or "Target|Label;Target2|Label2"
--  floors : "Floor A;Floor B" or "Floor_Target|Label" or wiki links
--  ol    : "1"/"true" to use <ol>; otherwise <ul>
--  ol    : "1"/"true" -> <ol>, otherwise <ul>
--  before : optional text prepended to each label (display only)
--  before : optional text before each label (display only)
--  after  : optional text appended to 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 28: Line 64:
     local after  = args.after or ""
     local after  = args.after or ""


     if #floors == 0 then
     if #floors == 0 then return "" end
        return ""
    end


     local items = {}
     local items = {}
     for _, item in ipairs(floors) do
     for _, raw in ipairs(floors) do
        -- Support "Target|Label" per item; default label = target
         local target, label = parseItem(raw)
         local target, label = item:match("^(.-)|(.*)$")
        if not target then
            target = item
            label  = item
        end
        target = mw.text.trim(target)
        label  = mw.text.trim(label)


         -- Build full subpage title and URL
         -- Normalize to always "base/floor"
         local titleText = base .. "/" .. target
         local titleText = normalizeTarget(base, target)
         local titleObj  = mw.title.new(titleText)
         local titleObj  = mw.title.new(titleText)
        local url = titleObj and titleObj:localUrl() or ("/wiki/" .. mw.uri.encode(titleText))


         -- Escape label for HTML; add optional before/after decorations (display only)
         -- Build URL safely
        local url = titleObj and titleObj:localUrl()
            or ("/wiki/" .. mw.uri.encode(titleText))
 
        -- Encode label for HTML (avoid breaking if label has special chars)
         local linkText = before .. label .. after
         local linkText = before .. label .. after
         table.insert(items, '<li><a href="' .. url .. '">' .. mw.text.encode(linkText) .. '</a></li>')
         table.insert(items,
            '<li><a href="' .. url .. '">' .. mw.text.encode(linkText) .. '</a></li>'
        )
     end
     end



Revision as of 04:43, 22 August 2025

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

-- Module:PadUtils
local p = {}

-- split "A;B;C" safely (ignores empty pieces)
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

-- 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)
    -- Strip [[...]] if present
    local inner = item:match("^%[%[(.*)%]%]$")
    if inner then item = inner end
    -- Split on pipe "|"
    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

-- 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)
    -- Remove leading/trailing spaces
    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 .. "/"
    if target:sub(1, #withSlash) == withSlash then
        target = target:sub(#withSlash + 1)
    end

    -- Final title is ALWAYS base/target
    local titleText = base .. "/" .. target
    return titleText
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)
    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

    local items = {}
    for _, raw in ipairs(floors) do
        local target, label = parseItem(raw)

        -- Normalize to always "base/floor"
        local titleText = normalizeTarget(base, target)
        local titleObj  = mw.title.new(titleText)

        -- Build URL safely
        local url = titleObj and titleObj:localUrl()
            or ("/wiki/" .. mw.uri.encode(titleText))

        -- Encode label for HTML (avoid breaking if label has special chars)
        local linkText = before .. label .. after
        table.insert(items,
            '<li><a href="' .. url .. '">' .. mw.text.encode(linkText) .. '</a></li>'
        )
    end

    return '<' .. listTag .. '>' .. table.concat(items) .. '</' .. listTag .. '>'
end

return p