Module:Message box: Difference between revisions

    No edit summary
    m>Mr. Stradivarius
    (Allow passing attributes per protected edit request by User:Jackmcbarn. Also remove undocumented "hidden" parameter and format the module so it mostly fits within 80 chars.)
    Line 1: Line 1:
    -- This is a meta-module for producing message box templates, including {{mbox}}, {{ambox}},
    -- This is a meta-module for producing message box templates, including
    -- {{imbox}}, {{tmbox}}, {{ombox}}, {{cmbox}} and {{fmbox}}.
    -- {{mbox}}, {{ambox}}, {{imbox}}, {{tmbox}}, {{ombox}}, {{cmbox}} and {{fmbox}}.


    -- Require necessary modules.
    -- Require necessary modules.
    Line 122: Line 122:
    nsVals[i] = format('"%s"', val)
    nsVals[i] = format('"%s"', val)
    end
    end
    error('invalid ns parameter passed to box:addCat; valid values are ' .. mw.text.listToText(nsVals, nil, ' or '))
    error(
    'invalid ns parameter passed to box:addCat; valid values are '
    .. mw.text.listToText(nsVals, nil, ' or ')
    )
    end
    end
    self[tname] = self[tname] or {}
    self[tname] = self[tname] or {}
    Line 136: Line 139:
    self.classes = self.classes or {}
    self.classes = self.classes or {}
    tinsert(self.classes, class)
    tinsert(self.classes, class)
    end
    function box:addAttr(attr, val)
    if type(attr) ~= 'string' or type(val) ~= 'string' then return end
    self.attrs = self.attrs or {}
    tinsert(self.attrs, attr)
    end
    end


    Line 158: Line 167:
    end
    end
    tinsert(boxTypes, '"mbox"')
    tinsert(boxTypes, '"mbox"')
    error(format('invalid message box type "%s"; valid types are %s', tostring(boxType), mw.text.listToText(boxTypes)), 2)
    error(format(
    'invalid message box type "%s"; valid types are %s',
    tostring(boxType),
    mw.text.listToText(boxTypes)
    ), 2)
    end
    end
    return cfg
    return cfg
    Line 164: Line 177:


    function box:removeBlankArgs(cfg, args)
    function box:removeBlankArgs(cfg, args)
    -- Only allow blank arguments for the parameter names listed in cfg.allowBlankParams.
    -- Only allow blank arguments for the parameter names listed in
    -- cfg.allowBlankParams.
    local newArgs = {}
    local newArgs = {}
    for k, v in pairs(args) do
    for k, v in pairs(args) do
    Line 181: Line 195:
    self.type = args.type
    self.type = args.type
    local typeData = cfg.types[self.type]
    local typeData = cfg.types[self.type]
    self.invalidTypeError = cfg.showInvalidTypeError and self.type and not typeData and true or false
    self.invalidTypeError = cfg.showInvalidTypeError
    and self.type
    and not typeData
    and true
    or false
    typeData = typeData or cfg.types[cfg.default]
    typeData = typeData or cfg.types[cfg.default]
    self.typeClass = typeData.class
    self.typeClass = typeData.class
    Line 206: Line 224:
    self.id = args.id
    self.id = args.id
    end
    end
    self:addClass(cfg.usePlainlinksParam and yesno(args.plainlinks or true) and 'plainlinks')
    self:addClass(
    cfg.usePlainlinksParam and yesno(args.plainlinks or true) and 'plainlinks'
    )
    for _, class in ipairs(cfg.classes or {}) do
    for _, class in ipairs(cfg.classes or {}) do
    self:addClass(class)
    self:addClass(class)
    Line 212: Line 232:
    if self.isSmall then
    if self.isSmall then
    self:addClass(cfg.smallClass or 'mbox-small')
    self:addClass(cfg.smallClass or 'mbox-small')
    end
    if yesno(args.hidden) then
    self:addClass('infobox editsection')
    end
    end
    self:addClass(self.typeClass)
    self:addClass(self.typeClass)
    self:addClass(args.class)
    self:addClass(args.class)
    self.style = args.style
    self.style = args.style
    self.attrs = args.attrs


    -- Set text style.
    -- Set text style.
    self.textstyle = args.textstyle
    self.textstyle = args.textstyle


    -- Find if we are on the template page or not. This functionality is only used if useCollapsibleTextFields is set,
    -- Find if we are on the template page or not. This functionality is only
    -- or if both cfg.templateCategory and cfg.templateCategoryRequireName are set.
    -- used if useCollapsibleTextFields is set, or if both cfg.templateCategory
    -- and cfg.templateCategoryRequireName are set.
    self.useCollapsibleTextFields = cfg.useCollapsibleTextFields
    self.useCollapsibleTextFields = cfg.useCollapsibleTextFields
    if self.useCollapsibleTextFields or cfg.templateCategory and cfg.templateCategoryRequireName then
    if self.useCollapsibleTextFields
    or cfg.templateCategory
    and cfg.templateCategoryRequireName
    then
    self.name = args.name
    self.name = args.name
    if self.name then
    if self.name then
    local templateName = mw.ustring.match(self.name, '^[tT][eE][mM][pP][lL][aA][tT][eE][%s_]*:[%s_]*(.*)$') or self.name
    local templateName = mw.ustring.match(
    self.name,
    '^[tT][eE][mM][pP][lL][aA][tT][eE][%s_]*:[%s_]*(.*)$'
    ) or self.name
    templateName = 'Template:' .. templateName
    templateName = 'Template:' .. templateName
    self.templateTitle = getTitleObject(templateName)
    self.templateTitle = getTitleObject(templateName)
    end
    end
    self.isTemplatePage = self.templateTitle and mw.title.equals(self.title, self.templateTitle) or false
    self.isTemplatePage = self.templateTitle
    and mw.title.equals(self.title, self.templateTitle)
    or false
    end
    end


    -- Process data for collapsible text fields. At the moment these are only used in {{ambox}}.
    -- Process data for collapsible text fields. At the moment these are only
    -- used in {{ambox}}.
    if self.useCollapsibleTextFields then
    if self.useCollapsibleTextFields then
    -- Get the self.issue value.
    -- Get the self.issue value.
    Line 261: Line 289:
    -- Get the self.talk value.
    -- Get the self.talk value.
    local talk = args.talk
    local talk = args.talk
    if talk == '' -- Show talk links on the template page or template subpages if the talk parameter is blank.
    -- Show talk links on the template page or template subpages if the talk
    -- parameter is blank.
    if talk == ''
    and self.templateTitle  
    and self.templateTitle  
    and (mw.title.equals(self.templateTitle, self.title) or self.title:isSubpageOf(self.templateTitle))
    and (
    mw.title.equals(self.templateTitle, self.title)
    or self.title:isSubpageOf(self.templateTitle)
    )
    then
    then
    talk = '#'
    talk = '#'
    Line 270: Line 303:
    end
    end
    if talk then
    if talk then
    -- If the talk value is a talk page, make a link to that page. Else assume that it's a section heading,
    -- If the talk value is a talk page, make a link to that page. Else
    -- and make a link to the talk page of the current page with that section heading.
    -- assume that it's a section heading, and make a link to the talk
    -- page of the current page with that section heading.
    local talkTitle = getTitleObject(talk)
    local talkTitle = getTitleObject(talk)
    local talkArgIsTalkPage = true
    local talkArgIsTalkPage = true
    if not talkTitle or not talkTitle.isTalkPage then
    if not talkTitle or not talkTitle.isTalkPage then
    talkArgIsTalkPage = false
    talkArgIsTalkPage = false
    talkTitle = getTitleObject(self.title.text, mw.site.namespaces[self.title.namespace].talk.id)
    talkTitle = getTitleObject(
    self.title.text,
    mw.site.namespaces[self.title.namespace].talk.id
    )
    end
    end
    if talkTitle and talkTitle.exists then
    if talkTitle and talkTitle.exists then
    local talkText = 'Relevant discussion may be found on'
    local talkText = 'Relevant discussion may be found on'
    if talkArgIsTalkPage then
    if talkArgIsTalkPage then
    talkText = format('%s [[%s|%s]].', talkText, talk, talkTitle.prefixedText)
    talkText = format(
    '%s [[%s|%s]].',
    talkText,
    talk,
    talkTitle.prefixedText
    )
    else
    else
    talkText = format('%s the [[%s#%s|talk page]].', talkText, talkTitle.prefixedText, talk)
    talkText = format(
    '%s the [[%s#%s|talk page]].',
    talkText,
    talkTitle.prefixedText,
    talk
    )
    end
    end
    self.talk = talkText
    self.talk = talkText
    Line 303: Line 350:
    end
    end


    -- Set the non-collapsible text field. At the moment this is used by all box types other than ambox,
    -- Set the non-collapsible text field. At the moment this is used by all box
    -- and also by ambox when small=yes.
    -- types other than ambox, and also by ambox when small=yes.
    if self.isSmall then
    if self.isSmall then
    self.text = args.smalltext or args.text
    self.text = args.smalltext or args.text
    Line 328: Line 375:
    self.imageLeft = imageLeft
    self.imageLeft = imageLeft
    if not imageLeft then
    if not imageLeft then
    local imageSize = self.isSmall and (cfg.imageSmallSize or '30x30px') or '40x40px'
    local imageSize = self.isSmall
    self.imageLeft = format('[[File:%s|%s|link=|alt=]]', self.typeImage or 'Imbox notice.png', imageSize)
    and (cfg.imageSmallSize or '30x30px')
    or '40x40px'
    self.imageLeft = format('[[File:%s|%s|link=|alt=]]', self.typeImage
    or 'Imbox notice.png', imageSize)
    end
    end
    end
    end
    Line 360: Line 410:
    local preposition = 'from'
    local preposition = 'from'
    for _, num in ipairs(self.categoryParamNums) do
    for _, num in ipairs(self.categoryParamNums) do
    local mainCat = args['cat' .. tostring(num)] or args['category' .. tostring(num)]
    local mainCat = args['cat' .. tostring(num)]
    or args['category' .. tostring(num)]
    local allCat = args['all' .. tostring(num)]
    local allCat = args['all' .. tostring(num)]
    mainCat = type(mainCat) == 'string' and mainCat
    mainCat = type(mainCat) == 'string' and mainCat
    Line 369: Line 420:
    catTitle = getTitleObject('Category:' .. catTitle)
    catTitle = getTitleObject('Category:' .. catTitle)
    if not catTitle or not catTitle.exists then
    if not catTitle or not catTitle.exists then
    self:addCat('main', 'Articles with invalid date parameter in template')
    self:addCat(
    'main',
    'Articles with invalid date parameter in template'
    )
    end
    end
    elseif mainCat and (not date or date == '') then
    elseif mainCat and (not date or date == '') then
    Line 426: Line 480:
    end
    end


    -- Convert category tables to strings and pass them through [[Module:Category handler]].
    -- Convert category tables to strings and pass them through
    -- [[Module:Category handler]].
    self.categories = categoryHandler{
    self.categories = categoryHandler{
    main = tconcat(self.mainCats or {}),
    main = tconcat(self.mainCats or {}),
    Line 462: Line 517:
    .cssText(self.style)
    .cssText(self.style)
    .attr('role', 'presentation')
    .attr('role', 'presentation')
    for attr, val in pairs(self.attrs or {}) do
    boxTable
    .attr(attr, val)
    end


    -- Add the left-hand image.
    -- Add the left-hand image.
    Line 468: Line 527:
    local imageLeftCell = row.tag('td').addClass('mbox-image')
    local imageLeftCell = row.tag('td').addClass('mbox-image')
    if self.imageCellDiv then
    if self.imageCellDiv then
    -- If we are using a div, redefine imageLeftCell so that the image is inside it.
    -- If we are using a div, redefine imageLeftCell so that the image
    -- Divs use style="width: 52px;", which limits the image width to 52px. If any
    -- is inside it. Divs use style="width: 52px;", which limits the
    -- images in a div are wider than that, they may overlap with the text or cause
    -- image width to 52px. If any images in a div are wider than that,
    -- other display problems.
    -- they may overlap with the text or cause other display problems.
    imageLeftCell = imageLeftCell.tag('div').css('width', '52px')  
    imageLeftCell = imageLeftCell.tag('div').css('width', '52px')  
    end
    end
    Line 477: Line 536:
    .wikitext(self.imageLeft)
    .wikitext(self.imageLeft)
    elseif self.imageEmptyCell then
    elseif self.imageEmptyCell then
    -- Some message boxes define an empty cell if no image is specified, and some don't.
    -- Some message boxes define an empty cell if no image is specified, and
    -- The old template code in templates where empty cells are specified gives the following hint:
    -- some don't. The old template code in templates where empty cells are
    -- "No image. Cell with some width or padding necessary for text cell to have 100% width."
    -- specified gives the following hint: "No image. Cell with some width
    -- or padding necessary for text cell to have 100% width."
    row.tag('td')
    row.tag('td')
    .addClass('mbox-empty-cell')  
    .addClass('mbox-empty-cell')  
    Line 488: Line 548:
    local textCell = row.tag('td').addClass('mbox-text')
    local textCell = row.tag('td').addClass('mbox-text')
    if self.useCollapsibleTextFields then
    if self.useCollapsibleTextFields then
    -- The message box uses advanced text parameters that allow things to be collapsible. At the
    -- The message box uses advanced text parameters that allow things to be
    -- moment, only ambox uses this.
    -- collapsible. At the moment, only ambox uses this.
    textCell
    textCell
    .cssText(self.textstyle)
    .cssText(self.textstyle)
    Line 522: Line 582:
    local imageRightCell = row.tag('td').addClass('mbox-imageright')
    local imageRightCell = row.tag('td').addClass('mbox-imageright')
    if self.imageCellDiv then
    if self.imageCellDiv then
    imageRightCell = imageRightCell.tag('div').css('width', '52px') -- If we are using a div, redefine imageRightCell so that the image is inside it.
    -- If we are using a div, redefine imageRightCell so that the image
    -- is inside it.
    imageRightCell = imageRightCell.tag('div').css('width', '52px')
    end
    end
    imageRightCell
    imageRightCell
    Line 543: Line 605:
    .tag('div')
    .tag('div')
    .css('text-align', 'center')
    .css('text-align', 'center')
    .wikitext(format('This message box is using an invalid "type=%s" parameter and needs fixing.', self.type or ''))
    .wikitext(format(
    'This message box is using an invalid "type=%s" parameter and needs fixing.',
    self.type or ''
    ))
    end
    end