Module:Instrument

From PickiPedia: A knowledge base of bluegrass, old time psychedelic jams, and other public domain music
Revision as of 04:45, 31 March 2026 by Magent (talk | contribs) (Fix: merge frame+parent args for Template:Guitar delegation; strip wikilinks from owner before {{m}})
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search

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

local p = {}

local function trim(s)
    return s:match('^%s*(.-)%s*$')
end

local function row(label, value)
    if not value or trim(value) == '' then return nil end
    return '|-\n! style="text-align: right; padding: 3px;" | ' .. label .. '\n| style="padding: 3px;" | ' .. trim(value)
end

local function sectionHeader(label)
    return '|-\n! colspan="2" style="background: #ddd; padding: 3px;" | ' .. label
end

local function any(...)
    for _, v in ipairs({...}) do
        if v and trim(v) ~= '' then return true end
    end
    return false
end

local function add(out, val)
    if val then table.insert(out, val) end
end

local function getArg(frameArgs, parentArgs, key)
    local v = frameArgs[key]
    if v and trim(v) ~= '' then return v end
    v = parentArgs[key]
    if v and trim(v) ~= '' then return v end
    return ''
end

-- Strip [[ ]] wikilink markup to get plain page name
local function stripWikilinks(s)
    -- [[Page|Display]] -> Display; [[Page]] -> Page
    s = s:gsub('%[%[([^%]|]+)|([^%]]+)%]%]', '%2')
    s = s:gsub('%[%[([^%]]+)%]%]', '%1')
    return trim(s)
end

function p.infobox(frame)
    -- Merge direct #invoke args with parent template args (direct wins)
    local fArgs = frame.args
    local pArgs = frame:getParent().args
    local type_ = getArg(fArgs, pArgs, 'type')
    if type_ == '' then type_ = 'Instrument' end
    local nickname = getArg(fArgs, pArgs, 'nickname')
    local make = getArg(fArgs, pArgs, 'make')
    local model = getArg(fArgs, pArgs, 'model')
    local serial = getArg(fArgs, pArgs, 'serial')
    local year = getArg(fArgs, pArgs, 'year')
    local image = getArg(fArgs, pArgs, 'image')
    local current_owner = getArg(fArgs, pArgs, 'current_owner')
    local previous_owners = getArg(fArgs, pArgs, 'previous_owners')
    local body_shape = getArg(fArgs, pArgs, 'body_shape')
    local top_wood = getArg(fArgs, pArgs, 'top_wood')
    local back_sides_wood = getArg(fArgs, pArgs, 'back_sides_wood')
    local neck_wood = getArg(fArgs, pArgs, 'neck_wood')
    local fingerboard_wood = getArg(fArgs, pArgs, 'fingerboard_wood')
    local bridge_wood = getArg(fArgs, pArgs, 'bridge_wood')
    local scale_length = getArg(fArgs, pArgs, 'scale_length')
    local nut_width = getArg(fArgs, pArgs, 'nut_width')
    local strings = getArg(fArgs, pArgs, 'strings')
    local electronics = getArg(fArgs, pArgs, 'electronics')

    -- SMW properties via #set parser function
    local setArgs = {}
    local propMap = {
        ['Instrument type'] = type_,
        ['Nickname'] = nickname,
        ['Make'] = make,
        ['Model'] = model,
        ['Serial'] = serial,
        ['Year built'] = year,
        ['Current owner'] = current_owner,
        ['Body shape'] = body_shape,
        ['Top wood'] = top_wood,
        ['Back and sides wood'] = back_sides_wood,
        ['Neck wood'] = neck_wood,
        ['Fingerboard wood'] = fingerboard_wood,
        ['Bridge wood'] = bridge_wood,
        ['Scale length'] = scale_length,
        ['Nut width'] = nut_width,
        ['Number of strings'] = strings,
        ['Electronics'] = electronics,
    }
    for k, v in pairs(propMap) do
        if v ~= '' then
            table.insert(setArgs, k .. '=' .. v)
        end
    end
    if #setArgs > 0 then
        frame:callParserFunction('#set', setArgs)
    end

    -- Header
    local header
    if make ~= '' then
        header = make .. ' ' .. model
        if serial ~= '' then
            if tonumber(serial) then
                header = header .. ' #' .. serial
            else
                header = header .. ' ' .. serial
            end
        end
    elseif nickname ~= '' then
        header = "''" .. nickname .. "''"
    else
        header = type_
    end

    -- Build table
    local out = {}
    table.insert(out, '{| class="infobox" style="width: 300px; border: 1px solid #aaa; background: #f9f9f9; padding: 10px; margin: 0 0 1em 1em; float: right;"')
    table.insert(out, '|-')
    table.insert(out, '! colspan="2" style="background: #ccc; font-size: 1.1em; padding: 5px;" | ' .. header)

    if trim(image) ~= '' then
        table.insert(out, '|-')
        table.insert(out, '| colspan="2" style="text-align: center; padding: 10px;" | [[File:' .. trim(image) .. '|280px]]')
    end

    add(out, row('Type', type_))
    add(out, row('Serial', serial))
    add(out, row('Year', year))

    if trim(current_owner) ~= '' then
        local ownerName = stripWikilinks(current_owner)
        local ownerDisplay = trim(frame:expandTemplate{ title = 'm', args = { ownerName } })
        add(out, row('Owner', ownerDisplay))
    end
    add(out, row('Previous', previous_owners))

    if any(body_shape, top_wood, back_sides_wood, neck_wood, fingerboard_wood, bridge_wood) then
        table.insert(out, sectionHeader('Construction'))
        add(out, row('Body', body_shape))
        add(out, row('Top', top_wood))
        add(out, row('Back/Sides', back_sides_wood))
        add(out, row('Neck', neck_wood))
        add(out, row('Fingerboard', fingerboard_wood))
        add(out, row('Bridge', bridge_wood))
    end

    if any(scale_length, nut_width, strings) then
        table.insert(out, sectionHeader('Specifications'))
        add(out, row('Scale', scale_length))
        add(out, row('Nut Width', nut_width))
        add(out, row('Strings', strings))
    end

    if trim(electronics) ~= '' then
        table.insert(out, sectionHeader('Electronics'))
        table.insert(out, '|-')
        table.insert(out, '| colspan="2" style="padding: 3px;" | ' .. trim(electronics))
    end

    local detailsForm = ({
        Guitar = 'GuitarDetails',
        Banjo = 'BanjoDetails',
        Mandolin = 'MandolinDetails',
    })[type_] or 'InstrumentDetails'

    local pageName = mw.title.getCurrentTitle().fullText
    table.insert(out, '|-')
    table.insert(out, '| colspan="2" style="text-align: center; padding: 8px 3px 3px;" | [[Special:FormEdit/' .. detailsForm .. '/' .. pageName .. '|Add details & photos]]')
    table.insert(out, '|}')
    table.insert(out, '[[Category:Instruments]][[Category:' .. type_ .. 's]]')

    return table.concat(out, '\n')
end

return p