Module:Message box
Lua error in package.lua at line 80: module 'Module:HtmlBuilder' not found. Lua error in package.lua at line 80: module 'Module:HtmlBuilder' not found. Lua error in package.lua at line 80: module 'Module:HtmlBuilder' not found.
- REDIRECT Template:Intricate template
This is a meta-module that implements the message box templates {{mbox}}, {{ambox}}, {{cmbox}}, {{fmbox}}, {{imbox}}, {{ombox}}, and {{tmbox}}. It is intended to be used from Lua modules, and should not be used directly from wiki pages. If you want to use this module's functionality from a wiki page, please use the individual message box templates instead.
Usage
To use this module from another Lua module, first you need to load it.
<source lang="lua"> local messageBox = require('Module:Message box') </source>
To create a message box, use the main
function. It takes two parameters: the first is the box type (as a string), and the second is a table containing the message box parameters.
<source lang="lua"> local box = messageBox.main( boxType, {
param1 = param1, param2 = param2, -- More parameters...
}) </source>
There are seven available box types:
Box type | Template | Purpose |
---|---|---|
mbox |
{{mbox}} | For message boxes to be used in multiple namespaces |
ambox |
{{ambox}} | For article message boxes |
cmbox |
{{cmbox}} | For category message boxes |
fmbox |
{{fmbox}} | For interface message boxes |
imbox |
{{imbox}} | For file namespace message boxes |
tmbox |
{{tmbox}} | For talk page message boxes |
ombox |
{{ombox}} | For message boxes in other namespaces |
See the template page of each box type for the available parameters.
Usage from #invoke
As well as the main
function, this module has separate functions for each box type. They are accessed using the code {{#invoke:Message box|mbox|...}}
, {{#invoke:Message box|ambox|...}}
, etc. These will work when called from other modules, but they access code used to process arguments passed from #invoke, and so calling them will be less efficient than calling main
.
Technical details
The module uses the same basic code for each of the templates listed above; the differences between each of them are configured using the data at Module:Message box/configuration. Here are the various configuration options and what they mean:
types
- a table containing data used by the type parameter of the message box. The table keys are the values that can be passed to the type parameter, and the table values are tables containing the class and the image used by that type.default
- the type to use if no value was passed to the type parameter, or if an invalid value was specified.showInvalidTypeError
- whether to show an error if the value passed to the type parameter was invalid.allowBlankParams
- usually blank values are stripped from parameters passed to the module. However, whitespace is preserved for the parameters included in the allowBlankParams table.allowSmall
- whether a small version of the message box can be produced with "small=yes".smallParam
- a custom name for the small parameter. For example, if set to "left" you can produce a small message box using "small=left".smallClass
- the class to use for small message boxes.substCheck
- whether to perform a subst check or not.classes
- an array of classes to use with the message box.imageEmptyCell
- whether to use an empty<td>...</td>
cell if there is no image set. This is used to preserve spacing for message boxes with a width of less than 100% of the screen.imageEmptyCellStyle
- whether empty image cells should be styled.imageCheckBlank
- whether "image=blank" results in no image being displayed.imageSmallSize
- usually, images used in small message boxes are set to 30x30px. This sets a custom size.imageCellDiv
- whether to enclose the image in a div enforcing a maximum image size.useCollapsibleTextFields
- whether to use text fields that can be collapsed, i.e. "issue", "fix", "talk", etc. Currently only used in ambox.imageRightNone
- whether imageright=none results in no image being displayed on the right-hand side of the message box.sectionDefault
- the default name for the "section" parameter. Depends onuseCollapsibleTextFields
.allowMainspaceCategories
- allow categorisation in the main namespace.templateCategory
- the name of a category to be placed on the template page.templateCategoryRequireName
- whether thename
parameter is required to display the template category.templateErrorCategory
- the name of the error category to be used on the template page.templateErrorParamsToCheck
- an array of parameter names to check. If any are absent, thetemplateErrorCategory
is applied to the template page.
-- 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 categoryHandler = require('Module:Category handler').main 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 end local function presentButBlank(s) if type(s) ~= 'string' then return end if s and not mw.ustring.find(s, '%S') then return true else return false end end local function formatCategory(cat, date, all) local ret = {} cat = type(cat) == 'string' and cat date = type(date) == 'string' and date all = type(all) == 'string' and all local preposition = 'from' if cat and date then local catTitle = mw.ustring.format('Category:%s %s %s', cat, preposition, date) table.insert(ret, mw.ustring.format('[[%s]]', catTitle)) catTitle = getTitleObject(catTitle) if not catTitle or not catTitle.exists then table.insert(ret, '[[Category:Articles with invalid date parameter in template]]') end elseif cat and not date then table.insert(ret, mw.ustring.format('[[Category:%s]]', cat)) end if all then table.insert(ret, mw.ustring.format('[[Category:%s]]', all)) end return table.concat(ret) end local function union(t1, t2) -- Returns the union of two arrays. local vals = {} for i, v in ipairs(t1) do vals[v] = true end for i, v in ipairs(t2) do vals[v] = true end local ret = {} for k, v in pairs(vals) do table.insert(ret, k) end return ret end local function getArgNums(args, prefix) local nums = {} for k, v in pairs(args) do local num = mw.ustring.match(tostring(k), '^' .. prefix .. '([1-9]%d*)$') if num then table.insert(nums, tonumber(num)) end end table.sort(nums) return nums end function p.build(boxType, args) -- Get the box config data from the data page. local dataTables = mw.loadData('Module:Message box/data') local data = dataTables[boxType] if not data then local boxTypes = {} for k, v in pairs(dataTables) do table.insert(boxTypes, mw.ustring.format('"%s"', k)) end error(mw.ustring.format('Invalid message box type. Valid types are %s.', mw.text.listToText(boxTypes))) end -- Get the title object and the namespace. local title = mw.title.getCurrentTitle() local nsid = title.namespace -- Get a language object for formatDate. local lang = mw.language.getContentLanguage() -- 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 name, issue, talk, fix, date, info if data.useCollapsibleTextFields then name = args.name local nameTitle = getTitleObject(name) local isTemplatePage = nameTitle and title.prefixedText == ('Template:' .. nameTitle.text) and true or false local sect = args.sect if presentButBlank(sect) then sect = mw.ustring.format('This %s ', data.sectionDefault or 'page') elseif type(sect) == 'string' then sect = 'This ' .. sect .. ' ' end issue = (sect or '') .. (args.issue or '') .. ' ' .. (args.text or '') talk = args.talk if presentButBlank(talk) and isTemplatePage then talk = '#' end fix = args.fix date = args.date if presentButBlank(date) and isTemplatePage then date = lang:formatDate('F Y') end info = args.info end -- Process the talk link, if present. if talk then -- See if the talk link exists and is for a talk or a content namespace. local talkTitle = type(talk) == 'string' and getTitleObject(talk) if not talkTitle or not talkTitle.isTalkPage then -- If we couldn't process the talk page link, get the talk page of the current page. local success success, talkTitle = pcall(title.talkPageTitle, title) if not success then talkTitle = nil end end if talkTitle and talkTitle.exists then local talkText = ' Relevant discussion may be found on' if talkTitle.isTalkPage then talkText = mw.ustring.format('%s [[%s|%s]].', talkText, talk, talkTitle.prefixedText) else talkText = mw.ustring.format('%s the [[%s#%s|talk page]].', talkText, talkTitle.prefixedText, talk) end talk = talkText end 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, text, imageSize if isSmall then smallClass = data.smallClass or 'mbox-small' image = args.smallimage or args.image imageRight = args.smallimageright or args.imageright if data.useCollapsibleTextFields then text = args.smalltext or issue else text = args.smalltext or args.text end imageSize = data.imageSmallSize or '30x30px' else image = args.image imageRight = args.imageright imageSize = '40x40px' text = args.text end -- Process mainspace categories. local mainCats = {} local origCategoryNums -- origCategoryNums might be used in computing the template error category. if data.allowMainspaceCategories then -- Categories for the main namespace. local origCatNums = getArgNums(args, 'cat') local origCategoryNums = getArgNums(args, 'category') local catNums = union(origCatNums, origCategoryNums) for _, num in ipairs(catNums) do local cat = args['cat' .. tostring(num)] or args['category' .. tostring(num)] local all = args['all' .. tostring(num)] table.insert(mainCats, formatCategory(cat, args.date, all)) end end -- Process template namespace categories local templateCats = {} if data.templateCategory and not title.isSubpage and not yesno(args.nocat) then table.insert(templateCats, mw.ustring.format('[[Category:%s]]', data.templateCategory)) end -- Add an error category for the template namespace if appropriate. if data.templateErrorCategory then local catName = data.templateErrorCategory local templateCat if not name and not title.isSubpage then templateCat = mw.ustring.format('[[Category:%s]]', catName) elseif type(name) == 'string' and title.prefixedText == ('Template:' .. name) then local paramsToCheck = data.templateErrorParamsToCheck or {} local count = 0 for i, param in ipairs(paramsToCheck) do if not args[param] then count = count + 1 end end if count > 0 then templateCat = mw.ustring.format('[[Category:%s|%d]]', catName, count) end if origCategoryNums and #origCategoryNums > 0 then templateCat = mw.ustring.format('[[Category:%s|C]]', catName) end end table.insert(templateCats, templatecat) end -- Categories for all namespaces. local allCats = {} if invalidType then local catsort = (nsid == 0 and 'Main:' or '') .. title.prefixedText table.insert(allCats, mw.ustring.format('[[Category:Wikipedia message box parameter needs fixing|%s]]', catsort)) end ------------------------ Build the box ---------------------------- local root = htmlBuilder.create() -- Do the subst check. if data.substCheck and args.subst == 'SUBST' then if type(name) == 'string' then root .tag('b') .addClass('error') .wikitext(mw.ustring.format( 'Template <code>%s%s%s</code> has been incorrectly substituted.', mw.text.nowiki('{{'), name, mw.text.nowiki('}}') )) end table.insert(allCats, '[[Category:Pages with incorrectly substituted templates]]') end -- Create the box table. local box = root.tag('table') 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 row = box.tag('tr') local imageCheckBlank = data.imageCheckBlank if image ~= 'none' and not imageCheckBlank or image ~= 'none' and imageCheckBlank and image ~= 'blank' then local imageLeftCell = row.tag('td').addClass('mbox-image') 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. local textCell = row.tag('td').addClass('mbox-text') if data.useCollapsibleTextFields then textCell .cssText(args.textstyle) local textCellSpan = textCell.tag('span') textCellSpan .addClass('mbox-text-span') .wikitext(issue) if not isSmall then textCellSpan .tag('span') .addClass('hide-when-compact') .wikitext(talk) .wikitext(' ') .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 local imageRightCell = row.tag('td').addClass('mbox-imageright') 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 ------------------------ Error messages and categories ---------------------------- -- Add error message for invalid type parameters. if invalidType then root .tag('div') .addClass('error') .css('text-align', 'center') .wikitext(mw.ustring.format('This message box is using an invalid type parameter (<code>type=%s</code>) and needs fixing.', args.type or '')) end -- Add categories using categoryHandler. root .wikitext(categoryHandler{ main = table.concat(mainCats), template = table.concat(templateCats), all = table.concat(allCats) }) return tostring(root) end local function makeWrapper(boxType) 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 p.build(boxType, args) end end p.ambox = makeWrapper('ambox') p.fmbox = makeWrapper('fmbox') p.imbox = makeWrapper('imbox') p.ombox = makeWrapper('ombox') p.cmbox = makeWrapper('cmbox') p.tmbox = makeWrapper('tmbox') return p