Difference between revisions of "Module:Message box"
From D&D 5e
(more ambox stuff - still a little broken) |
(Fixed a few of the ambox bugs. Still have to add category support.) |
||
Line 17: | Line 17: | ||
end | end | ||
end | end | ||
− | return page | + | 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 | end | ||
Line 24: | Line 33: | ||
local title = mw.title.getCurrentTitle() | local title = mw.title.getCurrentTitle() | ||
local nsid = title.namespace | 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 | -- Commenting this out for now - this will require tinkering with Namespace detect to differentiate between | ||
Line 48: | Line 60: | ||
-- Process data for collapsible text fields | -- Process data for collapsible text fields | ||
− | local | + | local name, issue, talk, fix, date, info |
if data.useCollapsibleTextFields then | if data.useCollapsibleTextFields then | ||
− | text = args.issue | + | 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 = 'This article ' | ||
+ | elseif type(sect) == 'string' then | ||
+ | sect = 'This ' .. sect .. ' ' | ||
+ | end | ||
+ | issue = (sect or '') .. (args.issue or '') .. ' ' .. (args.text or '') | ||
talk = args.talk | talk = args.talk | ||
+ | if presentButBlank(talk) and isTemplatePage then | ||
+ | talk = '#' | ||
+ | end | ||
fix = args.fix | fix = args.fix | ||
date = args.date | date = args.date | ||
+ | if presentButBlank(date) and isTemplatePage then | ||
+ | date = lang:formatDate('F Y') | ||
+ | end | ||
info = args.info | info = args.info | ||
− | else | + | 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 | end | ||
-- Find whether we are using a small message box and process our data accordingly. | -- 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, imageSize | + | local smallClass, image, imageRight, text, 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 text | + | if data.useCollapsibleTextFields then |
+ | text = args.smalltext or issue | ||
+ | else | ||
+ | text = args.smalltext or args.text | ||
+ | end | ||
imageSize = data.imageSmallSize or '30x30px' | imageSize = data.imageSmallSize or '30x30px' | ||
else | else | ||
Line 72: | Line 124: | ||
imageRight = args.imageright | imageRight = args.imageright | ||
imageSize = '40x40px' | imageSize = '40x40px' | ||
+ | text = args.text | ||
end | end | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
------------------------ Build the box ---------------------------- | ------------------------ Build the box ---------------------------- | ||
+ | |||
+ | local root = htmlBuilder.create() | ||
-- Do the subst check. | -- Do the subst check. | ||
if data.substCheck and args.subst == 'SUBST' then | if data.substCheck and args.subst == 'SUBST' then | ||
if type(args.name) == 'string' then | if type(args.name) == 'string' then | ||
− | + | root | |
− | .wikitext(mw.ustring.format( | + | .tag('b') |
− | + | .addClass('error') | |
− | + | .wikitext(mw.ustring.format( | |
− | + | 'Template <code>%s%s%s</code> has been incorrectly substituted.', | |
− | + | mw.text.nowiki('{{'), | |
− | + | args.name, | |
+ | mw.text.nowiki('}}') | ||
+ | )) | ||
end | end | ||
− | root.wikitext('[[Category:Pages with incorrectly substituted templates]]') | + | root.wikitext('[[Category:Pages with incorrectly substituted templates]]') |
end | end | ||
-- Build the box. | -- Build the box. | ||
+ | local box = root.tag('table') | ||
box | box | ||
.attr('id', args.id) | .attr('id', args.id) | ||
Line 116: | Line 164: | ||
-- Add the left-hand image. | -- Add the left-hand image. | ||
+ | local row = box.tag('tr') | ||
+ | local imageLeftCell = row.tag('td').addClass('mbox-image') | ||
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 | ||
Line 130: | Line 180: | ||
-- Add the text. | -- Add the text. | ||
+ | local textCell = row.tag('td').addClass('mbox-text') | ||
if data.useCollapsibleTextFields then | if data.useCollapsibleTextFields then | ||
textCell | textCell | ||
Line 136: | Line 187: | ||
textCellSpan | textCellSpan | ||
.addClass('mbox-text-span') | .addClass('mbox-text-span') | ||
− | .wikitext( | + | .wikitext(issue) |
if not isSmall then | if not isSmall then | ||
textCellSpan | textCellSpan | ||
Line 142: | Line 193: | ||
.addClass('hide-when-compact') | .addClass('hide-when-compact') | ||
.wikitext(talk) | .wikitext(talk) | ||
+ | .wikitext(' ') | ||
.wikitext(fix) | .wikitext(fix) | ||
.done() | .done() | ||
Line 160: | Line 212: | ||
-- Add the right-hand image. | -- Add the right-hand image. | ||
+ | local imageRightCell = row.tag('td').addClass('mbox-imageright') | ||
if imageRight and not (data.imageRightNone and imageRight == 'none') then | if imageRight and not (data.imageRightNone and imageRight == 'none') then | ||
if not isSmall and data.imageCellDiv then | if not isSmall and data.imageCellDiv then |
Revision as of 06:14, 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 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 function p.build(data, args) -- 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 = 'This article ' 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 ------------------------ Build the box ---------------------------- local root = htmlBuilder.create() -- Do the subst check. if data.substCheck and args.subst == 'SUBST' then if type(args.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('{{'), args.name, mw.text.nowiki('}}') )) end root.wikitext('[[Category:Pages with incorrectly substituted templates]]') end -- Build the box. 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 imageLeftCell = row.tag('td').addClass('mbox-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. 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. local imageRightCell = row.tag('td').addClass('mbox-imageright') 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