Module:Message box: Difference between revisions
Jump to navigation
Jump to search
No edit summary |
No edit summary Tag: Reverted |
||
Line 12: | Line 12: | ||
local function getTitleObject(...) | local function getTitleObject(...) | ||
local success, title = pcall(mw.title.new, ...) | local success, title = pcall(mw.title.new, ...) | ||
if success then | if success then | ||
Line 21: | Line 19: | ||
local function union(t1, t2) | local function union(t1, t2) | ||
local vals = {} | local vals = {} | ||
for i, v in ipairs(t1) do | for i, v in ipairs(t1) do | ||
Line 60: | Line 57: | ||
local obj = {} | local obj = {} | ||
obj.title = getTitleObject(args.page) or mw.title.getCurrentTitle() | obj.title = getTitleObject(args.page) or mw.title.getCurrentTitle() | ||
obj.cfg = cfg[boxType] | obj.cfg = cfg[boxType] | ||
if not obj.cfg then | if not obj.cfg then | ||
local ns = obj.title.namespace | local ns = obj.title.namespace | ||
if args.demospace and args.demospace ~= '' then | if args.demospace and args.demospace ~= '' then | ||
local demospace = string.lower(args.demospace) | local demospace = string.lower(args.demospace) | ||
if DEMOSPACES[demospace] then | if DEMOSPACES[demospace] then | ||
obj.cfg = cfg[DEMOSPACES[demospace]] | obj.cfg = cfg[DEMOSPACES[demospace]] | ||
elseif string.find( demospace, 'talk' ) then | elseif string.find(demospace, 'talk') then | ||
obj.cfg = cfg.tmbox | obj.cfg = cfg.tmbox | ||
else | else | ||
obj.cfg = cfg.ombox | obj.cfg = cfg.ombox | ||
end | end | ||
elseif ns == 0 then | elseif ns == 0 then | ||
obj.cfg = cfg.ambox | obj.cfg = cfg.ambox | ||
elseif ns == 6 then | elseif ns == 6 then | ||
obj.cfg = cfg.imbox | obj.cfg = cfg.imbox | ||
elseif ns == 14 then | elseif ns == 14 then | ||
obj.cfg = cfg.cmbox | obj.cfg = cfg.cmbox | ||
else | else | ||
local nsTable = mw.site.namespaces[ns] | local nsTable = mw.site.namespaces[ns] | ||
if nsTable and nsTable.isTalk then | if nsTable and nsTable.isTalk then | ||
obj.cfg = cfg.tmbox | obj.cfg = cfg.tmbox | ||
else | else | ||
obj.cfg = cfg.ombox | obj.cfg = cfg.ombox | ||
end | end | ||
end | end | ||
end | end | ||
do | do | ||
local newArgs = {} | local newArgs = {} | ||
Line 112: | Line 100: | ||
end | end | ||
obj.categories = {} | obj.categories = {} | ||
obj.classes = {} | obj.classes = {} | ||
obj.hasCategories = false | obj.hasCategories = false | ||
Line 122: | Line 108: | ||
function MessageBox:addCat(ns, cat, sort) | function MessageBox:addCat(ns, cat, sort) | ||
if not cat then | if not cat then return nil end | ||
if sort then | if sort then | ||
cat = string.format('[[Category:%s|%s]]', cat, sort) | cat = string.format('[[Category:%s|%s]]', cat, sort) | ||
Line 136: | Line 120: | ||
function MessageBox:addClass(class) | function MessageBox:addClass(class) | ||
if not class then | if not class then return nil end | ||
table.insert(self.classes, class) | table.insert(self.classes, class) | ||
end | end | ||
Line 146: | Line 128: | ||
local cfg = self.cfg | local cfg = self.cfg | ||
self.type = args.type | self.type = args.type | ||
local typeData = cfg.types[self.type] | local typeData = cfg.types[self.type] | ||
self.invalidTypeError = cfg.showInvalidTypeError | self.invalidTypeError = cfg.showInvalidTypeError and self.type and not typeData | ||
typeData = typeData or cfg.types[cfg.default] | typeData = typeData or cfg.types[cfg.default] | ||
self.typeClass = typeData.class | self.typeClass = typeData.class | ||
Line 157: | Line 136: | ||
self.typeImageNeedsLink = typeData.imageNeedsLink | self.typeImageNeedsLink = typeData.imageNeedsLink | ||
self.isSubstituted = cfg.substCheck and args.subst == 'SUBST' | self.isSubstituted = cfg.substCheck and args.subst == 'SUBST' | ||
self.isSmall = cfg.allowSmall and ( | self.isSmall = cfg.allowSmall and ( | ||
cfg.smallParam and args.small == cfg.smallParam | cfg.smallParam and args.small == cfg.smallParam | ||
Line 166: | Line 143: | ||
) | ) | ||
self.id = args.id | self.id = args.id | ||
self.name = args.name | self.name = args.name | ||
if self.name then | if self.name then | ||
self:addClass('box-' .. string.gsub(self.name,' ','_')) | self:addClass('box-' .. string.gsub(self.name, ' ', '_')) | ||
end | end | ||
if yesno(args.plainlinks) ~= false then | if yesno(args.plainlinks) ~= false then | ||
Line 186: | Line 162: | ||
self.attrs = args.attrs | self.attrs = args.attrs | ||
self.textstyle = args.textstyle | self.textstyle = args.textstyle | ||
self.imageRightClass = args.imagerightclass or args.imageclass | self.imageRightClass = args.imagerightclass or args.imageclass | ||
self.imageLeftClass = args.imageleftclass or args.imageclass | self.imageLeftClass = args.imageleftclass or args.imageclass | ||
self.useCollapsibleTextFields = cfg.useCollapsibleTextFields | self.useCollapsibleTextFields = cfg.useCollapsibleTextFields | ||
if self.useCollapsibleTextFields | if self.useCollapsibleTextFields or (cfg.templateCategory and cfg.templateCategoryRequireName) then | ||
if self.name then | if self.name then | ||
local templateName = mw.ustring.match( | local templateName = mw.ustring.match( | ||
Line 209: | Line 177: | ||
self.templateTitle = getTitleObject(templateName) | self.templateTitle = getTitleObject(templateName) | ||
end | end | ||
self.isTemplatePage = self.templateTitle | self.isTemplatePage = self.templateTitle and mw.title.equals(self.title, self.templateTitle) | ||
end | end | ||
if self.useCollapsibleTextFields then | if self.useCollapsibleTextFields then | ||
if self.isSmall and args.smalltext then | if self.isSmall and args.smalltext then | ||
self.issue = args.smalltext | self.issue = args.smalltext | ||
Line 237: | Line 201: | ||
end | end | ||
local talk = args.talk | local talk = args.talk | ||
if talk == '' | if talk == '' | ||
and self.templateTitle | and self.templateTitle | ||
Line 253: | Line 214: | ||
end | end | ||
if talk then | if talk then | ||
local talkTitle = getTitleObject(talk) | local talkTitle = getTitleObject(talk) | ||
local talkArgIsTalkPage = true | local talkArgIsTalkPage = true | ||
Line 266: | Line 224: | ||
end | end | ||
if talkTitle and talkTitle.exists then | if talkTitle and talkTitle.exists then | ||
local talkText | |||
if self.isSmall then | |||
local talkLink = talkArgIsTalkPage and talk or (talkTitle.prefixedText .. (talk == '#' and '' or '#') .. talk) | |||
talkText = string.format('([[%s|talk]])', talkLink) | |||
else | |||
talkText = 'Relevant discussion may be found on' | |||
if talkArgIsTalkPage then | |||
talkText = string.format('%s [[%s|%s]].', talkText, talk, talkTitle.prefixedText) | |||
else | |||
talkText = string.format('%s the [[%s' .. (talk == '#' and '' or '#') .. '%s|talk page]].', talkText, talkTitle.prefixedText, talk) | |||
end | |||
end | |||
self.talk = talkText | self.talk = talkText | ||
end | end | ||
end | end | ||
self.fix = args.fix ~= '' and args.fix or nil | self.fix = args.fix ~= '' and args.fix or nil | ||
local date | local date | ||
Line 309: | Line 256: | ||
end | end | ||
if self.isSmall then | if self.isSmall then | ||
self.text = args.smalltext or args.text | self.text = args.smalltext or args.text | ||
Line 317: | Line 262: | ||
end | end | ||
self.below = args.below | |||
self.below = | self.page = args.page | ||
return self | |||
end | end | ||
function MessageBox: | function MessageBox:getArgs() | ||
return self.args | |||
return | |||
end | end | ||
function MessageBox:export() | function MessageBox:export() | ||
local root = mw.html.create() | local root = mw.html.create('div') | ||
root | |||
:addClass('mbox') | |||
:addClass(table.concat(self.classes, ' ')) | |||
:attr('id', self.id) | |||
:attr('style', self.style) | |||
:attr('aria-label', self.cfg.ariaLabel) | |||
:attr('role', 'region') | |||
:attr('tabindex', 0) | |||
:attr('lang', self.cfg.lang or lang:getCode()) | |||
-- | -- Removed all dynamic templatestyles loading here to rely solely on MediaWiki:Common.css | ||
local | local content = mw.html.create('div') | ||
content:addClass('mbox-text') | |||
if self.textstyle then | |||
content:cssText(self.textstyle) | |||
end | end | ||
content:wikitext(self.text or '') | |||
root:node(content) | |||
if self.below and self.below ~= '' then | |||
root:wikitext(self.below) | |||
if self. | |||
end | end | ||
if self.hasCategories then | |||
if self. | for ns, cats in pairs(self.categories) do | ||
for _, cat in ipairs(cats) do | |||
root:wikitext(cat) | |||
end | |||
end | end | ||
end | end | ||
return tostring(root) | return tostring(root) | ||
Line 611: | Line 313: | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
-- | -- Module entry point | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
local | local function main(frame) | ||
local args = getArgs and getArgs(frame) or {} | |||
function | local cfg = mw.loadData(CONFIG_MODULE) | ||
local boxType = args.type or cfg.default | |||
local box = MessageBox.new(boxType, args, cfg) | |||
local box = MessageBox.new(boxType, args, | |||
box:setParameters() | box:setParameters() | ||
return box:export() | return box:export() | ||
end | end | ||
function | getArgs = function(frame) | ||
return | return frame:getParent().args or frame.args or {} | ||
end | end | ||
return | return { | ||
main = main, | |||
} |
Revision as of 07:07, 24 May 2025
This template is from Wikipedia.
require('strict')
local getArgs
local yesno = require('Module:Yesno')
local lang = mw.language.getContentLanguage()
local CONFIG_MODULE = 'Module:Message box/configuration'
local DEMOSPACES = {talk = 'tmbox', image = 'imbox', file = 'imbox', category = 'cmbox', article = 'ambox', main = 'ambox'}
--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------
local function getTitleObject(...)
local success, title = pcall(mw.title.new, ...)
if success then
return title
end
end
local function union(t1, t2)
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 in pairs(vals) do
table.insert(ret, k)
end
table.sort(ret)
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
--------------------------------------------------------------------------------
-- Box class definition
--------------------------------------------------------------------------------
local MessageBox = {}
MessageBox.__index = MessageBox
function MessageBox.new(boxType, args, cfg)
args = args or {}
local obj = {}
obj.title = getTitleObject(args.page) or mw.title.getCurrentTitle()
obj.cfg = cfg[boxType]
if not obj.cfg then
local ns = obj.title.namespace
if args.demospace and args.demospace ~= '' then
local demospace = string.lower(args.demospace)
if DEMOSPACES[demospace] then
obj.cfg = cfg[DEMOSPACES[demospace]]
elseif string.find(demospace, 'talk') then
obj.cfg = cfg.tmbox
else
obj.cfg = cfg.ombox
end
elseif ns == 0 then
obj.cfg = cfg.ambox
elseif ns == 6 then
obj.cfg = cfg.imbox
elseif ns == 14 then
obj.cfg = cfg.cmbox
else
local nsTable = mw.site.namespaces[ns]
if nsTable and nsTable.isTalk then
obj.cfg = cfg.tmbox
else
obj.cfg = cfg.ombox
end
end
end
do
local newArgs = {}
for k, v in pairs(args) do
if v ~= '' then
newArgs[k] = v
end
end
for i, param in ipairs(obj.cfg.allowBlankParams or {}) do
newArgs[param] = args[param]
end
obj.args = newArgs
end
obj.categories = {}
obj.classes = {}
obj.hasCategories = false
return setmetatable(obj, MessageBox)
end
function MessageBox:addCat(ns, cat, sort)
if not cat then return nil end
if sort then
cat = string.format('[[Category:%s|%s]]', cat, sort)
else
cat = string.format('[[Category:%s]]', cat)
end
self.hasCategories = true
self.categories[ns] = self.categories[ns] or {}
table.insert(self.categories[ns], cat)
end
function MessageBox:addClass(class)
if not class then return nil end
table.insert(self.classes, class)
end
function MessageBox:setParameters()
local args = self.args
local cfg = self.cfg
self.type = args.type
local typeData = cfg.types[self.type]
self.invalidTypeError = cfg.showInvalidTypeError and self.type and not typeData
typeData = typeData or cfg.types[cfg.default]
self.typeClass = typeData.class
self.typeImage = typeData.image
self.typeImageNeedsLink = typeData.imageNeedsLink
self.isSubstituted = cfg.substCheck and args.subst == 'SUBST'
self.isSmall = cfg.allowSmall and (
cfg.smallParam and args.small == cfg.smallParam
or not cfg.smallParam and yesno(args.small)
)
self.id = args.id
self.name = args.name
if self.name then
self:addClass('box-' .. string.gsub(self.name, ' ', '_'))
end
if yesno(args.plainlinks) ~= false then
self:addClass('plainlinks')
end
for _, class in ipairs(cfg.classes or {}) do
self:addClass(class)
end
if self.isSmall then
self:addClass(cfg.smallClass or 'mbox-small')
end
self:addClass(self.typeClass)
self:addClass(args.class)
self.style = args.style
self.attrs = args.attrs
self.textstyle = args.textstyle
self.imageRightClass = args.imagerightclass or args.imageclass
self.imageLeftClass = args.imageleftclass or args.imageclass
self.useCollapsibleTextFields = cfg.useCollapsibleTextFields
if self.useCollapsibleTextFields or (cfg.templateCategory and cfg.templateCategoryRequireName) 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
templateName = 'Template:' .. templateName
self.templateTitle = getTitleObject(templateName)
end
self.isTemplatePage = self.templateTitle and mw.title.equals(self.title, self.templateTitle)
end
if self.useCollapsibleTextFields then
if self.isSmall and args.smalltext then
self.issue = args.smalltext
else
local sect
if args.sect == '' then
sect = 'This ' .. (cfg.sectionDefault or 'page')
elseif type(args.sect) == 'string' then
sect = 'This ' .. args.sect
end
local issue = args.issue
issue = type(issue) == 'string' and issue ~= '' and issue or nil
local text = args.text
text = type(text) == 'string' and text or nil
local issues = {}
table.insert(issues, sect)
table.insert(issues, issue)
table.insert(issues, text)
self.issue = table.concat(issues, ' ')
end
local talk = args.talk
if talk == ''
and self.templateTitle
and (
mw.title.equals(self.templateTitle, self.title)
or self.title:isSubpageOf(self.templateTitle)
)
then
talk = '#'
elseif talk == '' then
talk = nil
end
if talk then
local talkTitle = getTitleObject(talk)
local talkArgIsTalkPage = true
if not talkTitle or not talkTitle.isTalkPage then
talkArgIsTalkPage = false
talkTitle = getTitleObject(
self.title.text,
mw.site.namespaces[self.title.namespace].talk.id
)
end
if talkTitle and talkTitle.exists then
local talkText
if self.isSmall then
local talkLink = talkArgIsTalkPage and talk or (talkTitle.prefixedText .. (talk == '#' and '' or '#') .. talk)
talkText = string.format('([[%s|talk]])', talkLink)
else
talkText = 'Relevant discussion may be found on'
if talkArgIsTalkPage then
talkText = string.format('%s [[%s|%s]].', talkText, talk, talkTitle.prefixedText)
else
talkText = string.format('%s the [[%s' .. (talk == '#' and '' or '#') .. '%s|talk page]].', talkText, talkTitle.prefixedText, talk)
end
end
self.talk = talkText
end
end
self.fix = args.fix ~= '' and args.fix or nil
local date
if args.date and args.date ~= '' then
date = args.date
elseif args.date == '' and self.isTemplatePage then
date = lang:formatDate('F Y')
end
if date then
self.date = string.format(" <span class='date-container'><i>(<span class='date'>%s</span>)</i></span>", date)
end
self.info = args.info
if yesno(args.removalnotice) then
self.removalNotice = cfg.removalNotice
end
end
if self.isSmall then
self.text = args.smalltext or args.text
else
self.text = args.text
end
self.below = args.below
self.page = args.page
return self
end
function MessageBox:getArgs()
return self.args
end
function MessageBox:export()
local root = mw.html.create('div')
root
:addClass('mbox')
:addClass(table.concat(self.classes, ' '))
:attr('id', self.id)
:attr('style', self.style)
:attr('aria-label', self.cfg.ariaLabel)
:attr('role', 'region')
:attr('tabindex', 0)
:attr('lang', self.cfg.lang or lang:getCode())
-- Removed all dynamic templatestyles loading here to rely solely on MediaWiki:Common.css
local content = mw.html.create('div')
content:addClass('mbox-text')
if self.textstyle then
content:cssText(self.textstyle)
end
content:wikitext(self.text or '')
root:node(content)
if self.below and self.below ~= '' then
root:wikitext(self.below)
end
if self.hasCategories then
for ns, cats in pairs(self.categories) do
for _, cat in ipairs(cats) do
root:wikitext(cat)
end
end
end
return tostring(root)
end
--------------------------------------------------------------------------------
-- Module entry point
--------------------------------------------------------------------------------
local function main(frame)
local args = getArgs and getArgs(frame) or {}
local cfg = mw.loadData(CONFIG_MODULE)
local boxType = args.type or cfg.default
local box = MessageBox.new(boxType, args, cfg)
box:setParameters()
return box:export()
end
getArgs = function(frame)
return frame:getParent().args or frame.args or {}
end
return {
main = main,
}