Module:Message box

Revision as of 01:56, 21 September 2013 by >Mr. Stradivarius (add imbox)

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

-- This is a meta-module for producing message box templates, including {{mbox}}, {{ambox}}, {{imbox}}, {{tmbox}}, {{ombox}}, {{cmbox}} and {{fmbox}}.

local htmlBuilder = require('Module:HtmlBuilder')
local yesno = require('Module:Yesno')

local p = {}

local function generateBoxStructure()
    local root = htmlBuilder.create() -- Includes error messages and categories added after the box.
    local box = root.tag('table')
    local row = box.tag('tr')
    return root, box, row
end

function p.build(data, args)
    -- Process config data.
    local typeData = data.types[args.type]
    local invalidType = args.type and not typeData and true or false
    typeData = typeData or data.types[data.default]

    local isSmall = (args.small == 'yes' or args.small == true) and true or false
    local image, imageRight, text, imageSize
    if isSmall then
        image = args.smallimage or args.image
        imageRight = args.smallimageright or args.imageright
        text = args.smalltext or args.text
        imageSize = data.imageSizeSmall or data.imageSize or '40x40px'
    else
        image = args.image
        imageRight = args.imageright
        text = args.text
        imageSize = data.imageSizeLarge or data.imageSize or '40x40px'
    end

    -- Get the box structure.
    local root, box, row = generateBoxStructure()

    -- Build the box.
    box
        .attr('id', args.id)
    for i, class in ipairs(data.classes) do
        box
            .addClass(class)
    end
    box
        .addClass(isSmall and 'mbox-small')
        .addClass(data.classPlainlinksYesno and yesno(args.plainlinks or true) and 'plainlinks')
        .addClass(typeData.class)
        .addClass(args.class)
        .cssText(args.style)
        .attr('role', 'presentation')

    -- Add the left-hand image.
    if image ~= 'none' then
        row.tag('td')
            .addClass('mbox-image')
            .wikitext(image or mw.ustring.format('[[File:%s|%s|link=|alt=]]', typeData.image, imageSize))
    elseif data.imageEmptyCell then
        row.tag('td')
            .addClass('mbox-empty-cell') -- No image. Cell with some width or padding necessary for text cell to have 100% width.
    end

    -- Add the text.
    row.tag('td')
        .addClass('mbox-text')
        .cssText(args.textstyle)
        .wikitext(text)

    -- Add the right-hand image.
    if imageRight and not (data.imageRightNone and imageRight == 'none') then
        row.tag('td')
            .addClass('mbox-imageright')
            .wikitext(imageRight)
    end

    -- Add the below row.
    if data.below and args.below then
        box.tag('tr')
            .tag('td')
                .attr('colspan', args.imageright and '3' or '2')
                .addClass('mbox-text')
                .cssText(args.textstyle)
                .wikitext(args.below)
    end

    -- Add error messages and categories.
    if invalidType then
        local title = mw.title.getCurrentTitle()
        local catsort = (title.namespace == 0 and 'Main:' or '') .. title.prefixedText
        root.tag('div')
            .css('text-align', 'center')
            .wikitext(mw.ustring.format('This message box is using an invalid "type=%s" parameter and needs fixing.', args.type or ''))
            .done()
        .wikitext(mw.ustring.format('[[Category:Wikipedia message box parameter needs fixing|%s]]', catsort))
    end
    return tostring(root)
end

function p._fmbox(args)
    local data = {}
    data.types = {
        warning = {
            class = 'fmbox-warning',
            image = 'Cmbox deletion.png'
        },
        editnotice = {
            class = 'fmbox-editnotice',
            image = 'Imbox notice.png'
        },
        system = {
            class = 'fmbox-system',
            image = 'Imbox notice.png'
        }
    }
    data.default = 'system'
    data.classes = { 'plainlinks', 'fmbox' }
    data.imageEmptyCell = false
    data.imageRightNone = false
    return p.build(data, args)
end

function p._ombox(args)
    local data = {}
    data.types = {
        speedy = {
            class = 'ombox-speedy',
            image = 'Imbox speedy deletion.png'
        },
        delete = {
            class = 'ombox-delete',
            image = 'Imbox deletion.png'
        },
        content = {
            class = 'ombox-content',
            image = 'Imbox content.png'
        },
        style = {
            class = 'ombox-style',
            image = 'Edit-clear.svg'
        },
        move = {
            class = 'ombox-move',
            image = 'Imbox move.png'
        },
        protection = {
            class = 'ombox-protection',
            image = 'Imbox protection.png'
        },
        notice = {
            class = 'ombox-notice',
            image = 'Imbox notice.png'
        }
    }
    data.default = 'notice'
    data.classes = {'plainlinks', 'ombox'}
    data.imageSizeLarge = '40x40px'
    data.imageSizeSmall = '30x30px'
    data.imageEmptyCell = true
    data.imageRightNone = true
    return p.build(data, args)
end

function p._imbox(args)
    local data = {}
    data.types = {
        speedy = {
            class = 'imbox-speedy',
            image = 'Imbox speedy deletion.png'
        },
        delete = {
            class = 'imbox-delete',
            image = 'Imbox deletion.png'
        },
        content = {
            class = 'imbox-content',
            image = 'Imbox content.png'
        },
        style = {
            class = 'imbox-style',
            image = 'Edit-clear.svg'
        },
        move = {
            class = 'imbox-move',
            image = 'Imbox move.png'
        },
        protection = {
            class = 'imbox-protection',
            image = 'Imbox protection.png'
        },
        license = {
            class = 'imbox-license',
            image = 'Imbox license.png'
        },
        featured = {
            class = 'imbox-featured',
            image = 'Imbox featured.png'
        },
        notice = {
            class = 'imbox-notice',
            image = 'Imbox notice.png'
        }
    }
    data.default = 'notice'
    data.classes = {'imbox'}
    data.classPlainlinksYesno = true
    data.imageEmptyCell = true
    data.below = true
    return p.build(data, args)
end

local function makeWrapper(func)
    return function (frame)
        -- If called via #invoke, use the args passed into the invoking
        -- template, or the args passed to #invoke if any exist. Otherwise
        -- assume args are being passed directly in from the debug console
        -- or from another Lua module.
        local origArgs
        if frame == mw.getCurrentFrame() then
            origArgs = frame:getParent().args
            for k, v in pairs(frame.args) do
                origArgs = frame.args
                break
            end
        else
            origArgs = frame
        end
        -- Trim whitespace and remove blank arguments.
        local args = {}
        for k, v in pairs(origArgs) do
            if type(v) == 'string' then
                v = mw.text.trim(v)
            end
            if v ~= '' then
                args[k] = v
            end
        end
        return func(args)
    end
end

p.fmbox = makeWrapper(p._fmbox)
p.imbox = makeWrapper(p._imbox)
p.ombox = makeWrapper(p._ombox)

return p