Module:Comma separated entries

local p = {}

local function _main( args )
    local sep = mw.message.new( 'comma-separator' ):plain()
    return table.concat( args, sep )
end

function p.main( frame )
    local origArgs
    if frame == mw.getCurrentFrame() then
        -- We're being called via #invoke. If the invoking template passed any arguments,
        -- use them. Otherwise, use the arguments that were passed into the template.
        origArgs = frame:getParent().args
        for k, v in pairs( frame.args ) do
            origArgs = frame.args
            break
        end
    else        
        -- We're being called from another module or from the debug console, so assume
        -- the arguments are passed in directly.
        origArgs = frame
    end
    
    -- Use integer args only, and allow for explicit positional arguments
    -- that are specified out of order, e.g. {{br separated entries|3=entry3}}.
    -- After processing, the args can be accessed accurately from ipairs.
    local args = {}
    for k, v in pairs( origArgs ) do
        if type( k ) == 'number' 
            and k >= 1 
            and math.floor( k ) == k
            and mw.ustring.match( v, '%S' ) -- Remove blank or whitespace values.
            then
            table.insert( args, k )
        end
    end
    table.sort( args )
    for i,v in ipairs( args ) do
        args[ i ] = origArgs[ v ]
        -- Trim whitespace from all args.
        if type( args[ i ] ) == 'string' then
            args[ i ] = mw.text.trim( args[ i ] )
        end
    end
 
    return _main( args )
end

return p