| Line 1: |
Line 1: |
| − | require('strict') | + | -- This is a meta-module for producing message box templates, including |
| | + | -- {{mbox}}, {{ambox}}, {{imbox}}, {{tmbox}}, {{ombox}}, {{cmbox}} and {{fmbox}}. |
| | + | |
| | + | -- Load necessary modules. |
| | + | require('Module:No globals') |
| | local getArgs | | local getArgs |
| | local yesno = require('Module:Yesno') | | local yesno = require('Module:Yesno') |
| | + | |
| | + | -- Get a language object for formatDate and ucfirst. |
| | local lang = mw.language.getContentLanguage() | | local lang = mw.language.getContentLanguage() |
| | | | |
| | + | -- Define constants |
| | local CONFIG_MODULE = 'Module:Message box/configuration' | | local CONFIG_MODULE = 'Module:Message box/configuration' |
| | local DEMOSPACES = {talk = 'tmbox', image = 'imbox', file = 'imbox', category = 'cmbox', article = 'ambox', main = 'ambox'} | | local DEMOSPACES = {talk = 'tmbox', image = 'imbox', file = 'imbox', category = 'cmbox', article = 'ambox', main = 'ambox'} |
| Line 155: |
Line 162: |
| | self.typeClass = typeData.class | | self.typeClass = typeData.class |
| | self.typeImage = typeData.image | | self.typeImage = typeData.image |
| − | self.typeImageNeedsLink = typeData.imageNeedsLink
| |
| | | | |
| | -- Find if the box has been wrongly substituted. | | -- Find if the box has been wrongly substituted. |
| Line 166: |
Line 172: |
| | ) | | ) |
| | | | |
| − | -- Set the below row.
| |
| − | self.below = cfg.below and args.below
| |
| − |
| |
| | -- Add attributes, classes and styles. | | -- Add attributes, classes and styles. |
| | self.id = args.id | | self.id = args.id |
| Line 177: |
Line 180: |
| | if yesno(args.plainlinks) ~= false then | | if yesno(args.plainlinks) ~= false then |
| | self:addClass('plainlinks') | | self:addClass('plainlinks') |
| − | end
| |
| − | if self.below then
| |
| − | self:addClass('mbox-with-below')
| |
| | end | | end |
| | for _, class in ipairs(cfg.classes or {}) do | | for _, class in ipairs(cfg.classes or {}) do |
| Line 194: |
Line 194: |
| | -- Set text style. | | -- Set text style. |
| | self.textstyle = args.textstyle | | self.textstyle = args.textstyle |
| − |
| |
| − | -- Set image classes.
| |
| − | self.imageRightClass = args.imagerightclass or args.imageclass
| |
| − | self.imageLeftClass = args.imageleftclass or args.imageclass
| |
| | | | |
| | -- Find if we are on the template page or not. This functionality is only | | -- Find if we are on the template page or not. This functionality is only |
| Line 272: |
Line 268: |
| | end | | end |
| | if talkTitle and talkTitle.exists then | | if talkTitle and talkTitle.exists then |
| − | local talkText
| + | local talkText = 'Relevant discussion may be found on' |
| − | if self.isSmall then
| + | if talkArgIsTalkPage then |
| − | local talkLink = talkArgIsTalkPage and talk or (talkTitle.prefixedText .. (talk == '#' and '' or '#') .. talk)
| + | talkText = string.format( |
| − | talkText = string.format('([[%s|talk]])', talkLink)
| + | '%s [[%s|%s]].', |
| − | else
| + | talkText, |
| − | talkText = 'Relevant discussion may be found on'
| + | talk, |
| − | if talkArgIsTalkPage then
| + | talkTitle.prefixedText |
| − | talkText = string.format(
| + | ) |
| − | '%s [[%s|%s]].',
| + | else |
| − | talkText,
| + | talkText = string.format( |
| − | talk,
| + | '%s the [[%s#%s|talk page]].', |
| − | talkTitle.prefixedText
| + | talkText, |
| − | )
| + | talkTitle.prefixedText, |
| − | else
| + | talk |
| − | talkText = string.format(
| + | ) |
| − | '%s the [[%s' .. (talk == '#' and '' or '#') .. '%s|talk page]].',
| + | end |
| − | talkText,
| |
| − | talkTitle.prefixedText,
| |
| − | talk
| |
| − | )
| |
| − | end
| |
| − | end
| |
| | self.talk = talkText | | self.talk = talkText |
| | end | | end |
| Line 307: |
Line 297: |
| | end | | end |
| | if date then | | if date then |
| − | self.date = string.format(" <span class='date-container'><i>(<span class='date'>%s</span>)</i></span>", date) | + | self.date = string.format(" <small class='date-container'>''(<span class='date'>%s</span>)''</small>", date) |
| | end | | end |
| | self.info = args.info | | self.info = args.info |
| Line 322: |
Line 312: |
| | self.text = args.text | | self.text = args.text |
| | end | | end |
| | + | |
| | + | -- Set the below row. |
| | + | self.below = cfg.below and args.below |
| | | | |
| | -- General image settings. | | -- General image settings. |
| | self.imageCellDiv = not self.isSmall and cfg.imageCellDiv | | self.imageCellDiv = not self.isSmall and cfg.imageCellDiv |
| | self.imageEmptyCell = cfg.imageEmptyCell | | self.imageEmptyCell = cfg.imageEmptyCell |
| | + | if cfg.imageEmptyCellStyle then |
| | + | self.imageEmptyCellStyle = 'border:none;padding:0px;width:1px' |
| | + | end |
| | | | |
| | -- Left image settings. | | -- Left image settings. |
| Line 337: |
Line 333: |
| | and (cfg.imageSmallSize or '30x30px') | | and (cfg.imageSmallSize or '30x30px') |
| | or '40x40px' | | or '40x40px' |
| − | self.imageLeft = string.format('[[File:%s|%s%s|alt=]]', self.typeImage | + | self.imageLeft = string.format('[[File:%s|%s|link=|alt=]]', self.typeImage |
| − | or 'Information icon4.svg', imageSize, self.typeImageNeedsLink and "" or "|link=" ) | + | or 'Imbox notice.png', imageSize) |
| | end | | end |
| | end | | end |
| Line 347: |
Line 343: |
| | self.imageRight = imageRight | | self.imageRight = imageRight |
| | end | | end |
| − |
| |
| − | -- set templatestyles
| |
| − | self.base_templatestyles = cfg.templatestyles
| |
| − | self.templatestyles = args.templatestyles
| |
| | end | | end |
| | | | |
| Line 471: |
Line 463: |
| | page = self.args.page | | page = self.args.page |
| | } | | } |
| − | end
| |
| − |
| |
| − | function MessageBox:exportDiv()
| |
| − | local root = mw.html.create()
| |
| − |
| |
| − | -- Add the subst check error.
| |
| − | if self.isSubstituted and self.name then
| |
| − | root:tag('b')
| |
| − | :addClass('error')
| |
| − | :wikitext(string.format(
| |
| − | 'Template <code>%s[[Template:%s|%s]]%s</code> has been incorrectly substituted.',
| |
| − | mw.text.nowiki('{{'), self.name, self.name, mw.text.nowiki('}}')
| |
| − | ))
| |
| − | end
| |
| − |
| |
| − | local frame = mw.getCurrentFrame()
| |
| − | root:wikitext(frame:extensionTag{
| |
| − | name = 'templatestyles',
| |
| − | args = { src = self.base_templatestyles },
| |
| − | })
| |
| − | -- Add support for a single custom templatestyles sheet. Undocumented as
| |
| − | -- need should be limited and many templates using mbox are substed; we
| |
| − | -- don't want to spread templatestyles sheets around to arbitrary places
| |
| − | if self.templatestyles then
| |
| − | root:wikitext(frame:extensionTag{
| |
| − | name = 'templatestyles',
| |
| − | args = { src = self.templatestyles },
| |
| − | })
| |
| − | end
| |
| − |
| |
| − | -- Create the box.
| |
| − | local mbox = root:tag('div')
| |
| − | mbox:attr('id', self.id or nil)
| |
| − | for i, class in ipairs(self.classes or {}) do
| |
| − | mbox:addClass(class or nil)
| |
| − | end
| |
| − | mbox
| |
| − | :cssText(self.style or nil)
| |
| − |
| |
| − | if self.attrs then
| |
| − | mbox:attr(self.attrs)
| |
| − | end
| |
| − |
| |
| − | local flex_container
| |
| − | if self.below then
| |
| − | -- we need to wrap the flex components (`image(right)` and `text`) in their
| |
| − | -- own container div to support the `below` parameter
| |
| − | flex_container = mw.html.create('div')
| |
| − | flex_container:addClass('mbox-flex')
| |
| − | else
| |
| − | -- the mbox itself is the parent, so we need no HTML flex_container
| |
| − | flex_container = mw.html.create()
| |
| − | end
| |
| − |
| |
| − | -- Add the left-hand image.
| |
| − | if self.imageLeft then
| |
| − | local imageLeftCell = flex_container:tag('div'):addClass('mbox-image')
| |
| − | imageLeftCell
| |
| − | :addClass(self.imageLeftClass)
| |
| − | :wikitext(self.imageLeft or nil)
| |
| − | end
| |
| − |
| |
| − | -- Add the text.
| |
| − | local textCell = flex_container:tag('div'):addClass('mbox-text')
| |
| − | if self.useCollapsibleTextFields then
| |
| − | -- The message box uses advanced text parameters that allow things to be
| |
| − | -- collapsible. At the moment, only ambox uses this.
| |
| − | textCell:cssText(self.textstyle or nil)
| |
| − | local textCellDiv = textCell:tag('div')
| |
| − | textCellDiv
| |
| − | :addClass('mbox-text-span')
| |
| − | :wikitext(self.issue or nil)
| |
| − | if (self.talk or self.fix) then
| |
| − | textCellDiv:tag('span')
| |
| − | :addClass('hide-when-compact')
| |
| − | :wikitext(self.talk and (' ' .. self.talk) or nil)
| |
| − | :wikitext(self.fix and (' ' .. self.fix) or nil)
| |
| − | end
| |
| − | textCellDiv:wikitext(self.date and (' ' .. self.date) or nil)
| |
| − | if self.info and not self.isSmall then
| |
| − | textCellDiv
| |
| − | :tag('span')
| |
| − | :addClass('hide-when-compact')
| |
| − | :wikitext(self.info and (' ' .. self.info) or nil)
| |
| − | end
| |
| − | if self.removalNotice then
| |
| − | textCellDiv:tag('span')
| |
| − | :addClass('hide-when-compact')
| |
| − | :tag('i')
| |
| − | :wikitext(string.format(" (%s)", self.removalNotice))
| |
| − | end
| |
| − | else
| |
| − | -- Default text formatting - anything goes.
| |
| − | textCell
| |
| − | :cssText(self.textstyle or nil)
| |
| − | :wikitext(self.text or nil)
| |
| − | end
| |
| − |
| |
| − | -- Add the right-hand image.
| |
| − | if self.imageRight then
| |
| − | local imageRightCell = flex_container:tag('div'):addClass('mbox-imageright')
| |
| − | imageRightCell
| |
| − | :addClass(self.imageRightClass)
| |
| − | :wikitext(self.imageRight or nil)
| |
| − | end
| |
| − |
| |
| − | mbox:node(flex_container)
| |
| − |
| |
| − | -- Add the below row.
| |
| − | if self.below then
| |
| − | mbox:tag('div')
| |
| − | :addClass('mbox-text mbox-below')
| |
| − | :cssText(self.textstyle or nil)
| |
| − | :wikitext(self.below or nil)
| |
| − | end
| |
| − |
| |
| − | -- Add error message for invalid type parameters.
| |
| − | if self.invalidTypeError then
| |
| − | root:tag('div')
| |
| − | :addClass('mbox-invalid-type')
| |
| − | :wikitext(string.format(
| |
| − | 'This message box is using an invalid "type=%s" parameter and needs fixing.',
| |
| − | self.type or ''
| |
| − | ))
| |
| − | end
| |
| − |
| |
| − | -- Add categories.
| |
| − | root:wikitext(self:renderCategories() or nil)
| |
| − |
| |
| − | return tostring(root)
| |
| | end | | end |
| | | | |
| | function MessageBox:export() | | function MessageBox:export() |
| − |
| |
| | local root = mw.html.create() | | local root = mw.html.create() |
| | | | |
| Line 615: |
Line 476: |
| | mw.text.nowiki('{{'), self.name, self.name, mw.text.nowiki('}}') | | mw.text.nowiki('{{'), self.name, self.name, mw.text.nowiki('}}') |
| | )) | | )) |
| − | end
| |
| − |
| |
| − | local frame = mw.getCurrentFrame()
| |
| − | root:wikitext(frame:extensionTag{
| |
| − | name = 'templatestyles',
| |
| − | args = { src = self.base_templatestyles },
| |
| − | })
| |
| − | -- Add support for a single custom templatestyles sheet. Undocumented as
| |
| − | -- need should be limited and many templates using mbox are substed; we
| |
| − | -- don't want to spread templatestyles sheets around to arbitrary places
| |
| − | if self.templatestyles then
| |
| − | root:wikitext(frame:extensionTag{
| |
| − | name = 'templatestyles',
| |
| − | args = { src = self.templatestyles },
| |
| − | })
| |
| | end | | end |
| | | | |
| Line 655: |
Line 501: |
| | -- image width to 52px. If any images in a div are wider than that, | | -- image width to 52px. If any images in a div are wider than that, |
| | -- they may overlap with the text or cause other display problems. | | -- they may overlap with the text or cause other display problems. |
| − | imageLeftCell = imageLeftCell:tag('div'):addClass('mbox-image-div') | + | imageLeftCell = imageLeftCell:tag('div'):css('width', '52px') |
| | end | | end |
| − | imageLeftCell | + | imageLeftCell:wikitext(self.imageLeft or nil) |
| − | :addClass(self.imageLeftClass)
| |
| − | :wikitext(self.imageLeft or nil)
| |
| | elseif self.imageEmptyCell then | | elseif self.imageEmptyCell then |
| | -- Some message boxes define an empty cell if no image is specified, and | | -- Some message boxes define an empty cell if no image is specified, and |
| Line 667: |
Line 511: |
| | row:tag('td') | | row:tag('td') |
| | :addClass('mbox-empty-cell') | | :addClass('mbox-empty-cell') |
| | + | :cssText(self.imageEmptyCellStyle or nil) |
| | end | | end |
| | | | |
| Line 679: |
Line 524: |
| | :addClass('mbox-text-span') | | :addClass('mbox-text-span') |
| | :wikitext(self.issue or nil) | | :wikitext(self.issue or nil) |
| − | if (self.talk or self.fix) then | + | if (self.talk or self.fix) and not self.isSmall then |
| | textCellDiv:tag('span') | | textCellDiv:tag('span') |
| | :addClass('hide-when-compact') | | :addClass('hide-when-compact') |
| Line 693: |
Line 538: |
| | end | | end |
| | if self.removalNotice then | | if self.removalNotice then |
| − | textCellDiv:tag('span') | + | textCellDiv:tag('small') |
| | :addClass('hide-when-compact') | | :addClass('hide-when-compact') |
| | :tag('i') | | :tag('i') |
| Line 711: |
Line 556: |
| | -- If we are using a div, redefine imageRightCell so that the image | | -- If we are using a div, redefine imageRightCell so that the image |
| | -- is inside it. | | -- is inside it. |
| − | imageRightCell = imageRightCell:tag('div'):addClass('mbox-image-div') | + | imageRightCell = imageRightCell:tag('div'):css('width', '52px') |
| | end | | end |
| | imageRightCell | | imageRightCell |
| − | :addClass(self.imageRightClass)
| |
| | :wikitext(self.imageRight or nil) | | :wikitext(self.imageRight or nil) |
| | end | | end |
| Line 731: |
Line 575: |
| | if self.invalidTypeError then | | if self.invalidTypeError then |
| | root:tag('div') | | root:tag('div') |
| − | :addClass('mbox-invalid-type') | + | :css('text-align', 'center') |
| | :wikitext(string.format( | | :wikitext(string.format( |
| | 'This message box is using an invalid "type=%s" parameter and needs fixing.', | | 'This message box is using an invalid "type=%s" parameter and needs fixing.', |
| Line 761: |
Line 605: |
| | box:setParameters() | | box:setParameters() |
| | box:setCategories() | | box:setCategories() |
| − | -- DIV MIGRATION CONDITIONAL
| |
| − | if box.cfg.div_structure then
| |
| − | return box:exportDiv()
| |
| − | end
| |
| − | -- END DIV MIGRATION CONDITIONAL
| |
| | return box:export() | | return box:export() |
| | end | | end |