Module:Message box: Difference between revisions

    From Nonbinary Wiki
    m>Mr. Stradivarius
    (initial code for ambox)
    m>Mr. Stradivarius
    (more ambox stuff - still a little broken)
    Line 18: Line 18:
         end
         end
         return page or mw.title.getCurrentTitle()
         return page or mw.title.getCurrentTitle()
    end
    local function generateBoxStructure()
        local root = htmlBuilder.create() -- Includes error messages and categories added after the box.
        local substCheck = root.tag('b').addClass('error')
        local box = root.tag('table')
        local row = box.tag('tr')
        local imageLeftCell = row.tag('td')
        return root, substCheck, box, row, imageLeftCell
    end
    end


    Line 49: Line 40:
    ]]
    ]]


         -- Process config data.
         ------------------------ Process config data ----------------------------
     
        -- Type data.
         local typeData = data.types[args.type]
         local typeData = data.types[args.type]
         local invalidType = args.type and not typeData and true or false
         local invalidType = args.type and not typeData and true or false
         typeData = typeData or data.types[data.default]
         typeData = typeData or data.types[data.default]


        -- Process data for collapsible text fields
        local text, talk, fix, date, info
        if data.useCollapsibleTextFields then
            text = args.issue
            talk = args.talk
            fix = args.fix
            date = args.date
            info = args.info
        else
            text = args.text
        end
        -- Find whether we are using a small message box and process our data accordingly.
         local isSmall = data.allowSmall and (args.small == 'yes' or args.small == true) and true or false
         local isSmall = data.allowSmall and (args.small == 'yes' or args.small == true) and true or false
         local smallClass, image, imageRight, text, imageSize
         local smallClass, image, imageRight, imageSize
         if isSmall then
         if isSmall then
             smallClass = data.smallClass or 'mbox-small'
             smallClass = data.smallClass or 'mbox-small'
             image = args.smallimage or args.image
             image = args.smallimage or args.image
             imageRight = args.smallimageright or args.imageright
             imageRight = args.smallimageright or args.imageright
             text = args.smalltext or args.text
             text = args.smalltext or text
             imageSize = data.imageSmallSize or '30x30px'
             imageSize = data.imageSmallSize or '30x30px'
         else
         else
             image = args.image
             image = args.image
             imageRight = args.imageright
             imageRight = args.imageright
            text = args.text
             imageSize = '40x40px'
             imageSize = '40x40px'
         end
         end


         -- Get the box structure.
         ------------------------ Get the box structure ----------------------------
         local root, substCheck, box, row, imageLeftCell = generateBoxStructure()
     
        local root = htmlBuilder.create() -- Includes error messages and categories added after the box.
         local substCheck = root.tag('b').addClass('error')
        local box = root.tag('table')
        local row = box.tag('tr')
        local imageLeftCell = row.tag('td').addClass('mbox-image')
        local textCell = row.tag('td').addClass('mbox-text')
        local imageRightCell = row.tag('td').addClass('mbox-imageright')
     
        ------------------------ Build the box ----------------------------


         -- Do the subst check.
         -- Do the subst check.
    Line 104: Line 118:
         local imageCheckBlank = data.imageCheckBlank
         local imageCheckBlank = data.imageCheckBlank
         if image ~= 'none' and not imageCheckBlank or image ~= 'none' and imageCheckBlank and image ~= 'blank' then
         if image ~= 'none' and not imageCheckBlank or image ~= 'none' and imageCheckBlank and image ~= 'blank' then
            imageLeftCell
                .addClass('mbox-image')
             if not isSmall and data.imageCellDiv then
             if not isSmall and data.imageCellDiv then
                 imageLeftCell = imageLeftCell.tag('div').css('width', '52px') -- If we are using a div, redefine imageLeftCell so that the image is inside it.
                 imageLeftCell = imageLeftCell.tag('div').css('width', '52px') -- If we are using a div, redefine imageLeftCell so that the image is inside it.
    Line 118: Line 130:


         -- Add the text.
         -- Add the text.
         row.tag('td')
         if data.useCollapsibleTextFields then
             .addClass('mbox-text')
            textCell
             .cssText(args.textstyle)
                .cssText(args.textstyle)
            .wikitext(text)
            local textCellSpan = textCell.tag('span')
             textCellSpan
                .addClass('mbox-text-span')
                .wikitext(text)
             if not isSmall then
                textCellSpan
                    .tag('span')
                        .addClass('hide-when-compact')
                        .wikitext(talk)
                        .wikitext(fix)
                        .done()
            end
            textCellSpan
                .wikitext(date and mw.ustring.format(" <small>''(%s)''</small>", date))
            if not isSmall then
                textCellSpan
                    .tag('span')
                        .addClass('hide-when-compact')
                        .wikitext(info and ' ' .. info)
            end
        else
            textCell
                .cssText(args.textstyle)
                .wikitext(text)
        end


         -- Add the right-hand image.
         -- Add the right-hand image.
         if imageRight and not (data.imageRightNone and imageRight == 'none') then
         if imageRight and not (data.imageRightNone and imageRight == 'none') then
             row.tag('td')
             if not isSmall and data.imageCellDiv then
                .addClass('mbox-imageright')
                imageRightCell = imageRightCell.tag('div').css('width', '52px') -- If we are using a div, redefine imageRightCell so that the image is inside it.
            end
            imageRightCell
                 .wikitext(imageRight)
                 .wikitext(imageRight)
         end
         end
    Line 140: Line 178:
         end
         end


         -- Add error messages and tracking categories.
         ------------------------ Add error messages and categories ----------------------------
     
        -- Add error message and tracking category for invalid type parameters.
         if invalidType then
         if invalidType then
             local catsort = (nsid == 0 and 'Main:' or '') .. title.prefixedText
             local catsort = (nsid == 0 and 'Main:' or '') .. title.prefixedText
    Line 199: Line 239:
         data.imageSmallSize = '20x20px'
         data.imageSmallSize = '20x20px'
         data.imageCellDiv = true
         data.imageCellDiv = true
         data.talkLink = true
         data.useCollapsibleTextFields = true
        data.imageRightNone = true
         return p.build(data, args)
         return p.build(data, args)
    end
    end
    Line 414: Line 455:
                     v = mw.text.trim(v)
                     v = mw.text.trim(v)
                 end
                 end
                 if v ~= '' then
                 if v ~= '' or k == 'talk' or k == 'sect' or k == 'date' then
                     args[k] = v
                     args[k] = v
                 end
                 end

    Revision as of 06:38, 23 September 2013

    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 nsDetect = require('Module:Namespace detect')
    local yesno = require('Module:Yesno')
    
    local p = {}
    
    local function getTitleObject(page)
        if type(page) == 'string' then
            -- Get the title object, passing the function through pcall 
            -- in case we are over the expensive function count limit.
            local success
            success, page = pcall(mw.title.new, page)
            if not success then
                page = nil
            end
        end
        return page or mw.title.getCurrentTitle()
    end
    
    function p.build(data, args)
        -- Get the title object and the namespace.
        local title = mw.title.getCurrentTitle()
        local nsid = title.namespace
        
    -- Commenting this out for now - this will require tinkering with Namespace detect to differentiate between
    -- invalid titles and pages where the expensive parser function count has been exceeded.
    --[[
        local title = nsDetect.getPageObject(args.page)
        local namespace = nsDetect.main{
            page = args.page,
            demospace = args.demospace,
            main = 'main',
            talk = 'talk',
            file = 'file',
            category = 'category',
            other = 'other'
        }
    ]]
    
        ------------------------ Process config data ----------------------------
    
        -- Type 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]
    
        -- Process data for collapsible text fields
        local text, talk, fix, date, info
        if data.useCollapsibleTextFields then
            text = args.issue
            talk = args.talk
            fix = args.fix
            date = args.date
            info = args.info
        else
            text = args.text
        end
    
        -- Find whether we are using a small message box and process our data accordingly.
        local isSmall = data.allowSmall and (args.small == 'yes' or args.small == true) and true or false
        local smallClass, image, imageRight, imageSize
        if isSmall then
            smallClass = data.smallClass or 'mbox-small'
            image = args.smallimage or args.image
            imageRight = args.smallimageright or args.imageright
            text = args.smalltext or text
            imageSize = data.imageSmallSize or '30x30px'
        else
            image = args.image
            imageRight = args.imageright
            imageSize = '40x40px'
        end
    
        ------------------------ Get the box structure ----------------------------
    
        local root = htmlBuilder.create() -- Includes error messages and categories added after the box.
        local substCheck = root.tag('b').addClass('error')
        local box = root.tag('table')
        local row = box.tag('tr')
        local imageLeftCell = row.tag('td').addClass('mbox-image')
        local textCell = row.tag('td').addClass('mbox-text')
        local imageRightCell = row.tag('td').addClass('mbox-imageright')
    
        ------------------------ Build the box ----------------------------
    
        -- Do the subst check.
        if data.substCheck and args.subst == 'SUBST' then
            if type(args.name) == 'string' then
                substCheck
                    .wikitext(mw.ustring.format(
                        'Template <code>%s%s%s</code> has been incorrectly substituted.',
                        mw.text.nowiki('{{'),
                        args.name,
                        mw.text.nowiki('}}')
                    ))
            end
            root.wikitext('[[Category:Pages with incorrectly substituted templates]]') -- This puts the category at the *end* of the output, rather than after the subst error message.
        end
    
        -- Build the box.
        box
            .attr('id', args.id)
        for i, class in ipairs(data.classes) do
            box
                .addClass(class)
        end
        box
            .addClass(isSmall and smallClass)
            .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.
        local imageCheckBlank = data.imageCheckBlank
        if image ~= 'none' and not imageCheckBlank or image ~= 'none' and imageCheckBlank and image ~= 'blank' then
            if not isSmall and data.imageCellDiv then
                imageLeftCell = imageLeftCell.tag('div').css('width', '52px') -- If we are using a div, redefine imageLeftCell so that the image is inside it.
            end
            imageLeftCell
                .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.
                .cssText(data.imageEmptyCellStyle and 'border:none;padding:0px;width:1px')
        end
    
        -- Add the text.
        if data.useCollapsibleTextFields then
            textCell
                .cssText(args.textstyle)
            local textCellSpan = textCell.tag('span')
            textCellSpan
                .addClass('mbox-text-span')
                .wikitext(text)
            if not isSmall then
                textCellSpan
                    .tag('span')
                        .addClass('hide-when-compact')
                        .wikitext(talk)
                        .wikitext(fix)
                        .done()
            end
            textCellSpan
                .wikitext(date and mw.ustring.format(" <small>''(%s)''</small>", date))
            if not isSmall then
                textCellSpan
                    .tag('span')
                        .addClass('hide-when-compact')
                        .wikitext(info and ' ' .. info)
            end
        else
            textCell
                .cssText(args.textstyle)
                .wikitext(text)
        end
    
        -- Add the right-hand image.
        if imageRight and not (data.imageRightNone and imageRight == 'none') then
            if not isSmall and data.imageCellDiv then
                imageRightCell = imageRightCell.tag('div').css('width', '52px') -- If we are using a div, redefine imageRightCell so that the image is inside it.
            end
            imageRightCell
                .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 ----------------------------
    
        -- Add error message and tracking category for invalid type parameters.
        if invalidType then
            local catsort = (nsid == 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
    
        -- Categorise template pages.
        if data.category and nsid == 10 and not title.isSubpage and not yesno(args.nocat) then
                root.wikitext(mw.ustring.format('[[Category:%s]]', data.category))
        end
        return tostring(root)
    end
    
    function p._ambox(args)
        local data = {}
        data.types = {
            speedy = {
                class = 'ambox-speedy',
                image = 'Ambox speedy deletion.png'
            },
            delete = {
                class = 'ambox-delete',
                image = 'Ambox deletion.png'
            },
            content = {
                class = 'ambox-content',
                image = 'Ambox content.png'
            },
            style = {
                class = 'ambox-style',
                image = 'Edit-clear.svg'
            },
            move = {
                class = 'ambox-move',
                image = 'Ambox move.png'
            },
            protection = {
                class = 'ambox-protection',
                image = 'Ambox protection.png'
            },
            notice = {
                class = 'ambox-notice',
                image = 'Ambox notice.png'
            }
        }
        data.default = 'notice'
        data.allowSmall = true
        data.substCheck = true
        data.classes = {'metadata', 'plainlinks', 'ambox'}
        data.smallClass = 'mbox-small-left'
        data.imageEmptyCell = true
        data.imageCheckBlank = true
        data.imageSmallSize = '20x20px'
        data.imageCellDiv = true
        data.useCollapsibleTextFields = true
        data.imageRightNone = true
        return p.build(data, args)
    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.allowSmall = true
        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
    
    function p._cmbox(args)
        local data = {}
        data.types = {
            speedy = {
                class = 'cmbox-speedy',
                image = 'Cmbox deletion.png'
            },
            delete = {
                class = 'cmbox-delete',
                image = 'Cmbox deletion.png'
            },
            content = {
                class = 'cmbox-content',
                image = 'Cmbox content.png'
            },
            style = {
                class = 'cmbox-style',
                image = 'Edit-clear.svg'
            },
            move = {
                class = 'cmbox-move',
                image = 'Cmbox move.png'
            },
            protection = {
                class = 'cmbox-protection',
                image = 'Cmbox protection.png'
            },
            notice = {
                class = 'cmbox-notice',
                image = 'Cmbox notice.png'
            }
        }
        data.default = 'notice'
        data.classes = {'plainlinks', 'cmbox'}
        return p.build(data, args)
    end
    
    function p._tmbox(args)
        local data = {}
        data.types = {
            speedy = {
                class = 'tmbox-speedy',
                image = 'Imbox speedy deletion.png'
            },
            delete = {
                class = 'tmbox-delete',
                image = 'Imbox deletion.png'
            },
            content = {
                class = 'tmbox-content',
                image = 'Imbox content.png'
            },
            style = {
                class = 'tmbox-style',
                image = 'Edit-clear.svg '
            },
            move = {
                class = 'tmbox-move',
                image = 'Imbox move.png'
            },
            protection = {
                class = 'tmbox-protection',
                image = 'Imbox protection.png'
            },
            notice = {
                class = 'tmbox-notice',
                image = 'Imbox notice.png'
            }
        }
        data.default = 'notice'
        data.classes = {'plainlinks', 'tmbox'}
        data.allowSmall = true
        data.imageRightNone = true
        data.imageEmptyCellStyle = true
        data.category = 'Talk message boxes'
        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 ~= '' or k == 'talk' or k == 'sect' or k == 'date' then
                    args[k] = v
                end
            end
            return func(args)
        end
    end
    
    p.ambox = makeWrapper(p._ambox)
    p.fmbox = makeWrapper(p._fmbox)
    p.imbox = makeWrapper(p._imbox)
    p.ombox = makeWrapper(p._ombox)
    p.cmbox = makeWrapper(p._cmbox)
    p.tmbox = makeWrapper(p._tmbox)
    
    return p