Module:EquipmentGallery

From Dune: Awakening Community Wiki
Jump to navigation Jump to search

Module:EquipmentGallery

Parses Menu Garments images listed by DPL3 into captioned entries compatible with Template:Gallery.

This module should not be invoked directly. To add a dynamic image gallery to a Garment page, use Template:EquipmentGallery.

This module provides the following function(s):

  • main - parses a newline-separated list of Menu Garments filenames, generates captions from the filename structure, and returns sorted filename~caption lines.

Usage

Render a dynamic Garment gallery

{{#invoke:EquipmentGallery|main|{{ #dpl:
|namespace = File
|titlematch = Menu Garments%{{BASEPAGENAME}}%
|format = ,%TITLE%\n,,
}}}}

Parameters

main

1
string
Newline-separated list of filenames (without the File: namespace prefix).
2 (optional)
string
Override for the item name used as the parsing anchor within each filename.
Defaults to the current page's base title (BASEPAGENAME).

Notes

Filename format

The module expects filenames matching the following structure:

Menu Garments <GENDER> [SWATCH] <ITEM_NAME> [SIDE].jpg
GENDER
Masculine or Feminine. Required.
SWATCH
Zero or more words between GENDER and ITEM_NAME. Optional.
ITEM_NAME
Must match the item name parameter (defaults to BASEPAGENAME). Required.
SIDE
Front or Back. Optional.

Sort order

Output lines are sorted by the following priority:

  1. Swatch presence - unswatched images first, swatched images after.
  2. Swatch name - alphabetical within the swatched group.
  3. Gender - Masculine before Feminine.
  4. Side - Front before Back. Files without 'Front/Back' will be left as unspecified.

Error handling

Filenames that do not match the expected structure are appended at the end of the output without a caption, rather than producing an error.


local p = {}

local common = require("Module:Common")

-- ---------- Data ----------

local PREFIX = "Menu Garments "
local GENDERS = { Masculine = 1, Feminine = 2 }
local SIDES = { Front = 1, Back = 2 }

-- ---------- Processing ----------

function p.parseFilename(filename, itemName)
    -- strip prefix
    if filename:sub(1, #PREFIX) ~= PREFIX then
        return nil
    end
    local base = filename:sub(#PREFIX + 1)

    -- strip file extension
    base = base:match("^(.+)%..+$")

    -- extract gender
    local gender, rest = base:match("^(%S+)%s+(.*)")
    if not gender or not GENDERS[gender] then
        return nil
    end

    -- find item name anchor
    local itemPos = rest:find(itemName, 1, true)
    if not itemPos then
        return nil
    end

    -- extract swatch, if present
    local swatch = nil
    if itemPos > 1 then
        local raw = common.trim(rest:sub(1, itemPos - 1))
        if raw ~= "" then
            swatch = raw
        end
    end

    -- extract front/back, if present
    local afterItem = common.trim(rest:sub(itemPos + #itemName))
    local side = nil
    if SIDES[afterItem] then
        side = afterItem
    end

    return {
        gender = gender,
        swatch = swatch,
        side = side,
    }
end

function p.buildCaption(parsed)
    local caption = parsed.swatch and "'''" .. parsed.swatch .. " Swatch'''" or "'''Default Swatch'''"

    caption = caption .. "<br>" .. parsed.gender

    if parsed.side then
        caption = caption .. " (" .. parsed.side .. ")"
    end

    return caption
end

-- ---------- Interface ----------

function p.main(frame)
    local args = frame.args

    local input = common.trim(args[1] or "")
    if input == "" then
        return "Placeholder.jpg~No matching images"
    end

    -- allow item name override
    local itemName = common.trim(args[2] or "")
    if itemName == "" then
        itemName = mw.title.getCurrentTitle().baseText  -- defaults to page title
    end

    local entries = {}
    for line in input:gmatch("[^\r\n]+") do
        line = common.trim(line)
        if line ~= "" then
            local parsed = p.parseFilename(line, itemName)
            entries[#entries + 1] = {
                filename = line,
                parsed = parsed,
            }
        end
    end

    -- sort order: swatch (none first) > gender (Masc first) > side (Front first)
    table.sort(entries, function(a, b)
        local ap, bp = a.parsed, b.parsed

        -- unparseable entries go to the end
        if not ap then return false end
        if not bp then return true end

        -- push un-swatched images to the front
        local aHas = ap.swatch and 1 or 0
        local bHas = bp.swatch and 1 or 0
        if aHas ~= bHas then return aHas < bHas end

        -- sort swatches alphabetically
        if ap.swatch and bp.swatch and ap.swatch ~= bp.swatch then
            return ap.swatch < bp.swatch
        end

        -- gender
        local aGender = GENDERS[ap.gender]
        local bGender = GENDERS[bp.gender]
        if aGender ~= bGender then return aGender < bGender end

        -- side (but also account for those that don't have front/back yet)
        local aSide = SIDES[ap.side] or 3
        local bSide = SIDES[bp.side] or 3
        return aSide < bSide
    end)

    -- build output lines
    local lines = {}
    for i = 1, #entries do
        local e = entries[i]
        if e.parsed then
            lines[#lines + 1] = e.filename .. "~" .. p.buildCaption(e.parsed)
        else
            lines[#lines + 1] = e.filename
        end
    end

    return table.concat(lines, "\n")
end

return p