Module:InfoboxBasic: Difference between revisions
Appearance
	
	
|  Created page with "-- Module:InfoboxBasic local p = {}  local trim = mw.text.trim  local function isBlank(v)     return v == nil or trim(tostring(v)) == '' end  local function labelFromKey(k)     -- keep author's casing; just swap underscores for spaces and trim     k = k:gsub('_', ' ')     k = trim(k)     return k end  function p.render(frame)     local parent = frame:getParent()     local args = parent and parent.args or frame.args      local title = args.name or args.Name or args.title..." | No edit summary | ||
| (7 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
| -- Module:InfoboxBasic | -- Module:InfoboxBasic | ||
| local p = {} | local p = {} | ||
| local trim = mw.text.trim | local trim = mw.text.trim | ||
| local function isBlank(v) | local function isBlank(v) return v == nil or trim(tostring(v)) == '' end | ||
| local function labelFromKey(k) return trim((k:gsub('_',' '))) end | |||
| end | |||
| local function  | -- Extract optional numeric prefix to force ordering, e.g. "01 Born", "002_Born" | ||
| local function splitOrderPrefix(key) | |||
|      local n, rest = tostring(key):match('^%s*(%d+)[%s_%-%.]*(.+)$') | |||
|      if n then | |||
|      return  |         return tonumber(n), trim(rest) | ||
|     end | |||
|      return nil, key | |||
| end | end | ||
| function p.render(frame) | function p.render(frame) | ||
|      local parent = frame:getParent() |      local parent = frame:getParent() or frame | ||
|      local args =  |      local args   = parent.args or {}   -- never nil | ||
|      local title = args.name or args.Name or args.title or args.Title or 'Infobox' |      local title   = args.name or args.Name or args.title or args.Title or 'Infobox' | ||
|      local image = args.image or args.Image |      local image   = args.image or args.Image | ||
|     local caption = args.caption or args.Caption | |||
|     local color   = args.color or args.Color or args.colour or args.Colour | |||
|     -- Table | |||
|      local tbl = mw.html.create('table') |      local tbl = mw.html.create('table') | ||
|          :addClass('infobox') |          :addClass('infobox') | ||
|          :css('float', 'right') |          :css('float','right') | ||
|          :css('clear', 'right') |          :css('clear','right') | ||
|          :css('margin', '0 0 1em 1em') |          :css('margin','0 0 1em 1em') | ||
|      -- Title |      -- Title | ||
|      tbl:tag('tr') |      local th = tbl:tag('tr'):tag('th') | ||
|          :attr('colspan','2') |          :attr('colspan','2') | ||
|          :addClass('infobox-title') |          :addClass('infobox-title') | ||
|         :css('text-align','center') | |||
|         :css('font-size','125%') | |||
|          :wikitext(title) |          :wikitext(title) | ||
|     if not isBlank(color) then | |||
|         th:addClass('has-title-color') | |||
|         th:css('--ib-title-bg', color) -- only used by light-mode CSS | |||
|     end | |||
|      -- Optional image |      -- Optional image | ||
|      if not isBlank(image) then |      if not isBlank(image) then | ||
|          tbl:tag('tr') |          local cell = tbl:tag('tr'):tag('td') | ||
|              :attr('colspan','2') |              :attr('colspan','2') | ||
|              : |              :addClass('infobox-image-cell') | ||
|         cell:wikitext('[[File:' .. image .. '|frameless]]') | |||
|         if not isBlank(caption) then | |||
|             cell:tag('div') | |||
|                 :css('text-align','center') | |||
|                 :css('font-size','90%') | |||
|                 :css('font-style','italic') | |||
|                 :css('margin-top','0.2em') | |||
|                 :wikitext(caption) | |||
|         end | |||
|      end |      end | ||
|     -- Keys to skip (already handled) | |||
|      local skip = { |      local skip = { | ||
|          name=true, Name=true, title=true, Title=true, |          name=true, Name=true, title=true, Title=true, | ||
|          image=true, Image=true, class=true, style=true |          image=true, Image=true, | ||
|         caption=true, Caption=true, | |||
|         color=true, Color=true, colour=true, Colour=true, | |||
|         class=true, style=true | |||
|      } |      } | ||
|      local function addRow(label, value) | |||
|          local row = tbl:tag('tr') | |||
|         row:tag('th'):attr('scope','row'):wikitext(labelFromKey(label)) | |||
|         row:tag('td'):wikitext(value) | |||
|     end | |||
|     -- Build a stable order map from the editor's source order if possible | |||
|     local sourceOrder = {} | |||
|              end |     if parent.argumentPairs then | ||
|         local temp = {} | |||
|         for key, _ in parent:argumentPairs() do | |||
|              temp[#temp+1] = key | |||
|         end | |||
|         for i = #temp, 1, -1 do | |||
|             sourceOrder[temp[i]] = i | |||
|          end |          end | ||
|     elseif parent.getArgumentNames then | |||
|         local names = parent:getArgumentNames() or {} | |||
|         for i, key in ipairs(names) do | |||
|             sourceOrder[key] = i | |||
|         end | |||
|     end | |||
|     -- Collect rows with computed sort keys | |||
|     local rows = {} | |||
|     for key, value in pairs(args) do | |||
|         if not skip[key] and not tonumber(key) and not isBlank(value) then | |||
|             local forcedN, displayKey = splitOrderPrefix(key) | |||
|             local srcIndex = sourceOrder[key] or 10^9 | |||
|             rows[#rows+1] = { | |||
|                 forced = forcedN or 10^8, | |||
|                 src    = srcIndex, | |||
|                 key    = displayKey, | |||
|                 rawkey = key, | |||
|                 value  = value | |||
|             } | |||
|         end | |||
|     end | |||
|     -- Sort: first by explicit numeric prefix (if any), then by source order | |||
|     table.sort(rows, function(a,b) | |||
|         if a.forced ~= b.forced then | |||
|             return a.forced < b.forced | |||
|         end | |||
|         return a.src < b.src | |||
|     end) | |||
|     -- Render rows | |||
|     for _, r in ipairs(rows) do | |||
|         addRow(r.key, r.value) | |||
|      end |      end | ||
Latest revision as of 00:30, 2 October 2025
Documentation for this module may be created at Module:InfoboxBasic/doc
-- Module:InfoboxBasic
local p = {}
local trim = mw.text.trim
local function isBlank(v) return v == nil or trim(tostring(v)) == '' end
local function labelFromKey(k) return trim((k:gsub('_',' '))) end
-- Extract optional numeric prefix to force ordering, e.g. "01 Born", "002_Born"
local function splitOrderPrefix(key)
    local n, rest = tostring(key):match('^%s*(%d+)[%s_%-%.]*(.+)$')
    if n then
        return tonumber(n), trim(rest)
    end
    return nil, key
end
function p.render(frame)
    local parent = frame:getParent() or frame
    local args   = parent.args or {}   -- never nil
    local title   = args.name or args.Name or args.title or args.Title or 'Infobox'
    local image   = args.image or args.Image
    local caption = args.caption or args.Caption
    local color   = args.color or args.Color or args.colour or args.Colour
    -- Table
    local tbl = mw.html.create('table')
        :addClass('infobox')
        :css('float','right')
        :css('clear','right')
        :css('margin','0 0 1em 1em')
    -- Title
    local th = tbl:tag('tr'):tag('th')
        :attr('colspan','2')
        :addClass('infobox-title')
        :css('text-align','center')
        :css('font-size','125%')
        :wikitext(title)
    if not isBlank(color) then
        th:addClass('has-title-color')
        th:css('--ib-title-bg', color) -- only used by light-mode CSS
    end
    -- Optional image
    if not isBlank(image) then
        local cell = tbl:tag('tr'):tag('td')
            :attr('colspan','2')
            :addClass('infobox-image-cell')
        cell:wikitext('[[File:' .. image .. '|frameless]]')
        if not isBlank(caption) then
            cell:tag('div')
                :css('text-align','center')
                :css('font-size','90%')
                :css('font-style','italic')
                :css('margin-top','0.2em')
                :wikitext(caption)
        end
    end
    -- Keys to skip (already handled)
    local skip = {
        name=true, Name=true, title=true, Title=true,
        image=true, Image=true,
        caption=true, Caption=true,
        color=true, Color=true, colour=true, Colour=true,
        class=true, style=true
    }
    local function addRow(label, value)
        local row = tbl:tag('tr')
        row:tag('th'):attr('scope','row'):wikitext(labelFromKey(label))
        row:tag('td'):wikitext(value)
    end
    -- Build a stable order map from the editor's source order if possible
    local sourceOrder = {}
    if parent.argumentPairs then
        local temp = {}
        for key, _ in parent:argumentPairs() do
            temp[#temp+1] = key
        end
        for i = #temp, 1, -1 do
            sourceOrder[temp[i]] = i
        end
    elseif parent.getArgumentNames then
        local names = parent:getArgumentNames() or {}
        for i, key in ipairs(names) do
            sourceOrder[key] = i
        end
    end
    -- Collect rows with computed sort keys
    local rows = {}
    for key, value in pairs(args) do
        if not skip[key] and not tonumber(key) and not isBlank(value) then
            local forcedN, displayKey = splitOrderPrefix(key)
            local srcIndex = sourceOrder[key] or 10^9
            rows[#rows+1] = {
                forced = forcedN or 10^8,
                src    = srcIndex,
                key    = displayKey,
                rawkey = key,
                value  = value
            }
        end
    end
    -- Sort: first by explicit numeric prefix (if any), then by source order
    table.sort(rows, function(a,b)
        if a.forced ~= b.forced then
            return a.forced < b.forced
        end
        return a.src < b.src
    end)
    -- Render rows
    for _, r in ipairs(rows) do
        addRow(r.key, r.value)
    end
    return tostring(tbl)
end
return p
