Module:Message box/div
Appearance
From Wikipedia, the free encyclopedia
This module is rated as alpha. It is ready for limited use and third-party feedback. It may be used on a small number of pages, but should be monitored closely. Suggestions for new features or adjustments to input and output are welcome.
This is basically currently a sandbox of Module:Message box (the /div pages are not). It is intended to get things to be at parity with the main module before deploying to a lot of pages.
Plan
[edit ]Diffs
[edit ]Written
[edit ]Plan is something like the following:
(削除) Resync the couple changes from the live modules (削除ここまで)(削除) Merge tested /div version but not CSS into main (削除ここまで)- Check for main namespace use in Special:Search for stuff that isn't ambox
- Add /div/*mbox.css support for each box and set the relevant configuration in Module:Message box/div/configuration
- imbox
- Tests:
- File:World of Warcraft.png (entirely local): no foreign copy
- File:Information.svg (entirely local but shadows foreign): no issues with foreign copy
- File:India roadway map.svg (local description, foreign file)
- File:Cat playing with a lizard.jpg (foreign description and file)
- Uses of mbox which is the imbox analog at Commons
- Tests:
- ambox (most reader visible)
- At least one pain point phab:T402969
- Consider in general lines like
.ambox div
[1] - Learn more ends up in a weird place
- ensure
imageCellDiv
is incorporated into the CSS somehow.
- ombox
- tmbox
- major coordination
- tmbox min-widths, instituted with this discussion
- imbox
- Merge relevant configuration into Module:Message box/configuration/sandbox (namely, set div_structure to true)
- Enable boxes of each kind one by one.
- Move CSS from Module:Message box/div/*mbox.css to Module:Message box/div/*mbox.css
- Merge Module:Message box/configuration from sandbox
- Fix bugs that are identified
- Delete the /div CSS (I won't be too sad)
- Remove main support for table versions from module, rename some things
- Remove references to imageEmptyCell cross modules
Done
[edit ]- cmbox
- fmbox
Messaging
[edit ]New section on Module talk:Message box:
== cmbox migration == A change is planned to occur sometime starting in the next day or two in how {{tl|cmbox}} is implemented. It should help improve display at mobile resolutions now, and accessibility later. cmbox was chosen because it has lower reader-facing impact than most other message box types and it's fairly self-contained. The change to cmbox will likely pave the way for other message boxes ({{tl|fmbox}} or {{tl|imbox}} is probably next). (There is some other planning information in [[#CSS instead of tables]].) You can expect some difference in styling from previous for a small period due to the [[WP:Job queue|job queue]], after which it should return to "normal". You should be able to correct it manually if you want with one of the usual steps ([[WP:PURGE|purge]], [[WP:NULL|null edit]], or [[Help:Dummy edit|dummy edit]]). If an issue with display persists, leave a comment here (this scenario may be possible with some unexpected setup cmboxes).
Advertised at least at WP:VPT and MediaWiki talk:Common.css:
A change to how {{tl|cmbox}} is implemented to support mobile resolutions better is occurring soon. It may cause some temporary display weirdness. Further information is available at {{slink|Module talk:Message box|cmbox migration}}.
The above documentation is transcluded from Module:Message box/div/doc. (edit | history)
Editors can experiment in this module's sandbox (create | mirror) and testcases (create) pages.
Subpages of this module.
Editors can experiment in this module's sandbox (create | mirror) and testcases (create) pages.
Subpages of this module.
require('strict') localgetArgs localyesno=require('Module:Yesno') locallang=mw.language.getContentLanguage() localCONFIG_MODULE='Module:Message box/div/configuration' localDEMOSPACES={talk='tmbox',image='imbox',file='imbox',category='cmbox',article='ambox',main='ambox'} -------------------------------------------------------------------------------- -- Helper functions -------------------------------------------------------------------------------- localfunctiongetTitleObject(...) -- Get the title object, passing the function through pcall -- in case we are over the expensive function count limit. localsuccess,title=pcall(mw.title.new,...) ifsuccessthen returntitle end end localfunctionunion(t1,t2) -- Returns the union of two arrays. localvals={} fori,vinipairs(t1)do vals[v]=true end fori,vinipairs(t2)do vals[v]=true end localret={} forkinpairs(vals)do table.insert(ret,k) end table.sort(ret) returnret end localfunctiongetArgNums(args,prefix) localnums={} fork,vinpairs(args)do localnum=mw.ustring.match(tostring(k),'^'..prefix..'([1-9]%d*)$') ifnumthen table.insert(nums,tonumber(num)) end end table.sort(nums) returnnums end -------------------------------------------------------------------------------- -- Box class definition -------------------------------------------------------------------------------- localMessageBox={} MessageBox.__index=MessageBox functionMessageBox.new(boxType,args,cfg) args=argsor{} localobj={} -- Set the title object and the namespace. obj.title=getTitleObject(args.page)ormw.title.getCurrentTitle() -- Set the config for our box type. obj.cfg=cfg[boxType] ifnotobj.cfgthen localns=obj.title.namespace -- boxType is "mbox" or invalid input ifargs.demospaceandargs.demospace~=''then -- implement demospace parameter of mbox localdemospace=string.lower(args.demospace) ifDEMOSPACES[demospace]then -- use template from DEMOSPACES obj.cfg=cfg[DEMOSPACES[demospace]] elseifstring.find(demospace,'talk')then -- demo as a talk page obj.cfg=cfg.tmbox else -- default to ombox obj.cfg=cfg.ombox end elseifns==0then obj.cfg=cfg.ambox-- main namespace elseifns==6then obj.cfg=cfg.imbox-- file namespace elseifns==14then obj.cfg=cfg.cmbox-- category namespace else localnsTable=mw.site.namespaces[ns] ifnsTableandnsTable.isTalkthen obj.cfg=cfg.tmbox-- any talk namespace else obj.cfg=cfg.ombox-- other namespaces or invalid input end end end -- Set the arguments, and remove all blank arguments except for the ones -- listed in cfg.allowBlankParams. do localnewArgs={} fork,vinpairs(args)do ifv~=''then newArgs[k]=v end end fori,paraminipairs(obj.cfg.allowBlankParamsor{})do newArgs[param]=args[param] end obj.args=newArgs end -- Define internal data structure. obj.categories={} obj.classes={} -- For lazy loading of [[Module:Category handler]]. obj.hasCategories=false returnsetmetatable(obj,MessageBox) end functionMessageBox:addCat(ns,cat,sort) ifnotcatthen returnnil end ifsortthen 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 functionMessageBox:addClass(class) ifnotclassthen returnnil end table.insert(self.classes,class) end functionMessageBox:setParameters() localargs=self.args localcfg=self.cfg -- Get type data. self.type=args.type localtypeData=cfg.types[self.type] self.invalidTypeError=cfg.showInvalidTypeError andself.type andnottypeData typeData=typeDataorcfg.types[cfg.default] self.typeClass=typeData.class self.typeImage=typeData.image self.typeImageNeedsLink=typeData.imageNeedsLink -- Find if the box has been wrongly substituted. self.isSubstituted=cfg.substCheckandargs.subst=='SUBST' -- Find whether we are using a small message box. self.isSmall=cfg.allowSmalland( cfg.smallParamandargs.small==cfg.smallParam ornotcfg.smallParamandyesno(args.small) ) -- Set the below row. self.below=cfg.belowandargs.below -- Add attributes, classes and styles. self.id=args.id self.name=args.name ifself.namethen self:addClass('box-'..string.gsub(self.name,' ','_')) end ifyesno(args.plainlinks)~=falsethen self:addClass('plainlinks') end ifself.belowthen self:addClass('mbox-with-below') end for_,classinipairs(cfg.classesor{})do self:addClass(class) end ifself.isSmallthen self:addClass(cfg.smallClassor'mbox-small') end self:addClass(self.typeClass) self:addClass(args.class) self.style=args.style self.attrs=args.attrs -- Set text style. self.textstyle=args.textstyle -- Set image classes. self.imageRightClass=args.imagerightclassorargs.imageclass self.imageLeftClass=args.imageleftclassorargs.imageclass -- Find if we are on the template page or not. This functionality is only -- used if useCollapsibleTextFields is set, or if both cfg.templateCategory -- and cfg.templateCategoryRequireName are set. self.useCollapsibleTextFields=cfg.useCollapsibleTextFields ifself.useCollapsibleTextFields orcfg.templateCategory andcfg.templateCategoryRequireName then ifself.namethen localtemplateName=mw.ustring.match( self.name, '^[tT][eE][mM][pP][lL][aA][tT][eE][%s_]*:[%s_]*(.*)$' )orself.name templateName='Template:'..templateName self.templateTitle=getTitleObject(templateName) end self.isTemplatePage=self.templateTitle andmw.title.equals(self.title,self.templateTitle) end -- Process data for collapsible text fields. At the moment these are only -- used in {{ambox}}. ifself.useCollapsibleTextFieldsthen -- Get the self.issue value. ifself.isSmallandargs.smalltextthen self.issue=args.smalltext else localsect ifargs.sect==''then sect='This '..(cfg.sectionDefaultor'page') elseiftype(args.sect)=='string'then sect='This '..args.sect end localissue=args.issue issue=type(issue)=='string'andissue~=''andissueornil localtext=args.text text=type(text)=='string'andtextornil localissues={} table.insert(issues,sect) table.insert(issues,issue) table.insert(issues,text) self.issue=table.concat(issues,' ') end -- Get the self.talk value. localtalk=args.talk -- Show talk links on the template page or template subpages if the talk -- parameter is blank. iftalk=='' andself.templateTitle and( mw.title.equals(self.templateTitle,self.title) orself.title:isSubpageOf(self.templateTitle) ) then talk='#' elseiftalk==''then talk=nil end iftalkthen -- If the talk value is a talk page, make a link to that page. Else -- assume that it's a section heading, and make a link to the talk -- page of the current page with that section heading. localtalkTitle=getTitleObject(talk) localtalkArgIsTalkPage=true ifnottalkTitleornottalkTitle.isTalkPagethen talkArgIsTalkPage=false talkTitle=getTitleObject( self.title.text, mw.site.namespaces[self.title.namespace].talk.id ) end iftalkTitleandtalkTitle.existsthen localtalkText ifself.isSmallthen localtalkLink=talkArgIsTalkPageandtalkor(talkTitle.prefixedText..(talk=='#'and''or'#')..talk) talkText=string.format('([[%s|talk]])',talkLink) else talkText='Relevant discussion may be found on' iftalkArgIsTalkPagethen 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 -- Get other values. self.fix=args.fix~=''andargs.fixornil localdate ifargs.dateandargs.date~=''then date=args.date elseifargs.date==''andself.isTemplatePagethen date=lang:formatDate('F Y') end ifdatethen self.date=string.format(" <span class='date-container'><i>(<span class='date'>%s</span>)</i></span>",date) end self.info=args.info ifyesno(args.removalnotice)then self.removalNotice=cfg.removalNotice end end -- Set the non-collapsible text field. At the moment this is used by all box -- types other than ambox, and also by ambox when small=yes. ifself.isSmallthen self.text=args.smalltextorargs.text else self.text=args.text end -- General image settings. self.imageCellDiv=notself.isSmallandcfg.imageCellDiv self.imageEmptyCell=cfg.imageEmptyCell -- Left image settings. localimageLeft=self.isSmallandargs.smallimageorargs.image ifcfg.imageCheckBlankandimageLeft~='blank'andimageLeft~='none' ornotcfg.imageCheckBlankandimageLeft~='none' then self.imageLeft=imageLeft ifnotimageLeftthen localimageSize=self.isSmall and(cfg.imageSmallSizeor'30x30px') or'40x40px' self.imageLeft=string.format('[[File:%s|%s%s|alt=]]',self.typeImage or'Information icon4.svg',imageSize,self.typeImageNeedsLinkand""or"|link=") end end -- Right image settings. localimageRight=self.isSmallandargs.smallimagerightorargs.imageright ifnot(cfg.imageRightNoneandimageRight=='none')then self.imageRight=imageRight end -- set templatestyles -- DIV MIGRATION CONDITIONAL ifcfg.div_templatestylesthen self.base_templatestyles=cfg.div_templatestyles else self.base_templatestyles=cfg.templatestyles end -- END DIV MIGRATION CONDITIONAL self.templatestyles=args.templatestyles end functionMessageBox:setMainspaceCategories() localargs=self.args localcfg=self.cfg ifnotcfg.allowMainspaceCategoriesthen returnnil end localnums={} for_,prefixinipairs{'cat','category','all'}do args[prefix..'1']=args[prefix] nums=union(nums,getArgNums(args,prefix)) end -- The following is roughly equivalent to the old {{Ambox/category}}. localdate=args.date date=type(date)=='string'anddate localpreposition='from' for_,numinipairs(nums)do localmainCat=args['cat'..tostring(num)] orargs['category'..tostring(num)] localallCat=args['all'..tostring(num)] mainCat=type(mainCat)=='string'andmainCat allCat=type(allCat)=='string'andallCat ifmainCatanddateanddate~=''then localcatTitle=string.format('%s %s %s',mainCat,preposition,date) self:addCat(0,catTitle) catTitle=getTitleObject('Category:'..catTitle) ifnotcatTitleornotcatTitle.existsthen self:addCat(0,'Articles with invalid date parameter in template') end elseifmainCatand(notdateordate=='')then self:addCat(0,mainCat) end ifallCatthen self:addCat(0,allCat) end end end functionMessageBox:setTemplateCategories() localargs=self.args localcfg=self.cfg -- Add template categories. ifcfg.templateCategorythen ifcfg.templateCategoryRequireNamethen ifself.isTemplatePagethen self:addCat(10,cfg.templateCategory) end elseifnotself.title.isSubpagethen self:addCat(10,cfg.templateCategory) end end -- Add template error categories. ifcfg.templateErrorCategorythen localtemplateErrorCategory=cfg.templateErrorCategory localtemplateCat,templateSort ifnotself.nameandnotself.title.isSubpagethen templateCat=templateErrorCategory elseifself.isTemplatePagethen localparamsToCheck=cfg.templateErrorParamsToCheckor{} localcount=0 fori,paraminipairs(paramsToCheck)do ifnotargs[param]then count=count+1 end end ifcount>0then templateCat=templateErrorCategory templateSort=tostring(count) end ifself.categoryNumsand#self.categoryNums>0then templateCat=templateErrorCategory templateSort='C' end end self:addCat(10,templateCat,templateSort) end end functionMessageBox:setAllNamespaceCategories() -- Set categories for all namespaces. ifself.invalidTypeErrorthen localallSort=(self.title.namespace==0and'Main:'or'')..self.title.prefixedText self:addCat('all','Wikipedia message box parameter needs fixing',allSort) end ifself.isSubstitutedthen self:addCat('all','Pages with incorrectly substituted templates') end end functionMessageBox:setCategories() ifself.title.namespace==0then self:setMainspaceCategories() elseifself.title.namespace==10then self:setTemplateCategories() end self:setAllNamespaceCategories() end functionMessageBox:renderCategories() ifnotself.hasCategoriesthen -- No categories added, no need to pass them to Category handler so, -- if it was invoked, it would return the empty string. -- So we shortcut and return the empty string. return"" end -- Convert category tables to strings and pass them through -- [[Module:Category handler]]. returnrequire('Module:Category handler')._main{ main=table.concat(self.categories[0]or{}), template=table.concat(self.categories[10]or{}), all=table.concat(self.categories.allor{}), nocat=self.args.nocat, page=self.args.page } end functionMessageBox:exportDiv() localroot=mw.html.create() -- Add the subst check error. ifself.isSubstitutedandself.namethen 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 localframe=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 ifself.templatestylesthen root:wikitext(frame:extensionTag{ name='templatestyles', args={src=self.templatestyles}, }) end -- Create the box. localmbox=root:tag('div') mbox:attr('id',self.idornil) fori,classinipairs(self.classesor{})do mbox:addClass(classornil) end mbox :cssText(self.styleornil) ifself.attrsthen mbox:attr(self.attrs) end localflex_container ifself.belowthen -- 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 flex_container as root node -- can be just a regular old table (basically) flex_container=mw.html.create() end -- Add the left-hand image. ifself.imageLeftthen localimageLeftCell=flex_container:tag('div'):addClass('mbox-image') imageLeftCell :addClass(self.imageLeftClass) :wikitext(self.imageLeftornil) end -- Add the text. localtextCell=flex_container:tag('div'):addClass('mbox-text') ifself.useCollapsibleTextFieldsthen -- The message box uses advanced text parameters that allow things to be -- collapsible. At the moment, only ambox uses this. textCell:cssText(self.textstyleornil) localtextCellDiv=textCell:tag('div') textCellDiv :addClass('mbox-text-span') :wikitext(self.issueornil) if(self.talkorself.fix)then textCellDiv:tag('span') :addClass('hide-when-compact') :wikitext(self.talkand(' '..self.talk)ornil) :wikitext(self.fixand(' '..self.fix)ornil) end textCellDiv:wikitext(self.dateand(' '..self.date)ornil) ifself.infoandnotself.isSmallthen textCellDiv :tag('span') :addClass('hide-when-compact') :wikitext(self.infoand(' '..self.info)ornil) end ifself.removalNoticethen 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.textstyleornil) :wikitext(self.textornil) end -- Add the right-hand image. ifself.imageRightthen localimageRightCell=flex_container:tag('div'):addClass('mbox-imageright') imageRightCell :addClass(self.imageRightClass) :wikitext(self.imageRightornil) end mbox:node(flex_container) -- Add the below row. ifself.belowthen mbox:tag('div') :addClass('mbox-text mbox-below') :cssText(self.textstyleornil) :wikitext(self.belowornil) end -- Add error message for invalid type parameters. ifself.invalidTypeErrorthen root:tag('div') :addClass('mbox-invalid-type') :wikitext(string.format( 'This message box is using an invalid "type=%s" parameter and needs fixing.', self.typeor'' )) end -- Add categories. root:wikitext(self:renderCategories()ornil) returntostring(root) end functionMessageBox:export() localroot=mw.html.create() -- Add the subst check error. ifself.isSubstitutedandself.namethen 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 localframe=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 ifself.templatestylesthen root:wikitext(frame:extensionTag{ name='templatestyles', args={src=self.templatestyles}, }) end -- Create the box table. localboxTable=root:tag('table') boxTable:attr('id',self.idornil) fori,classinipairs(self.classesor{})do boxTable:addClass(classornil) end boxTable :cssText(self.styleornil) :attr('role','presentation') ifself.attrsthen boxTable:attr(self.attrs) end -- Add the left-hand image. localrow=boxTable:tag('tr') ifself.imageLeftthen localimageLeftCell=row:tag('td'):addClass('mbox-image') ifself.imageCellDivthen -- If we are using a div, redefine imageLeftCell so that the image -- is inside it. Divs use style="width: 52px;", which limits the -- 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. imageLeftCell=imageLeftCell:tag('div'):addClass('mbox-image-div') end imageLeftCell :addClass(self.imageLeftClass) :wikitext(self.imageLeftornil) elseifself.imageEmptyCellthen -- Some message boxes define an empty cell if no image is specified, and -- some don't. The old template code in templates where empty cells are -- specified gives the following hint: "No image. Cell with some width -- or padding necessary for text cell to have 100% width." row:tag('td') :addClass('mbox-empty-cell') end -- Add the text. localtextCell=row:tag('td'):addClass('mbox-text') ifself.useCollapsibleTextFieldsthen -- The message box uses advanced text parameters that allow things to be -- collapsible. At the moment, only ambox uses this. textCell:cssText(self.textstyleornil) localtextCellDiv=textCell:tag('div') textCellDiv :addClass('mbox-text-span') :wikitext(self.issueornil) if(self.talkorself.fix)then textCellDiv:tag('span') :addClass('hide-when-compact') :wikitext(self.talkand(' '..self.talk)ornil) :wikitext(self.fixand(' '..self.fix)ornil) end textCellDiv:wikitext(self.dateand(' '..self.date)ornil) ifself.infoandnotself.isSmallthen textCellDiv :tag('span') :addClass('hide-when-compact') :wikitext(self.infoand(' '..self.info)ornil) end ifself.removalNoticethen 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.textstyleornil) :wikitext(self.textornil) end -- Add the right-hand image. ifself.imageRightthen localimageRightCell=row:tag('td'):addClass('mbox-imageright') ifself.imageCellDivthen -- If we are using a div, redefine imageRightCell so that the image -- is inside it. imageRightCell=imageRightCell:tag('div'):addClass('mbox-image-div') end imageRightCell :addClass(self.imageRightClass) :wikitext(self.imageRightornil) end -- Add the below row. ifself.belowthen boxTable:tag('tr') :tag('td') :attr('colspan',self.imageRightand'3'or'2') :addClass('mbox-text') :cssText(self.textstyleornil) :wikitext(self.belowornil) end -- Add error message for invalid type parameters. ifself.invalidTypeErrorthen root:tag('div') :addClass('mbox-invalid-type') :wikitext(string.format( 'This message box is using an invalid "type=%s" parameter and needs fixing.', self.typeor'' )) end -- Add categories. root:wikitext(self:renderCategories()ornil) returntostring(root) end -------------------------------------------------------------------------------- -- Exports -------------------------------------------------------------------------------- localp,mt={},{} functionp._exportClasses() -- For testing. return{ MessageBox=MessageBox } end functionp.main(boxType,args,cfgTables) localbox=MessageBox.new(boxType,args,cfgTablesormw.loadData(CONFIG_MODULE)) box:setParameters() box:setCategories() -- DIV MIGRATION CONDITIONAL ifbox.cfg.div_structurethen returnbox:exportDiv() end -- END DIV MIGRATION CONDITIONAL returnbox:export() end functionmt.__index(t,k) returnfunction(frame) ifnotgetArgsthen getArgs=require('Module:Arguments').getArgs end returnt.main(k,getArgs(frame,{trim=false,removeBlanks=false})) end end returnsetmetatable(p,mt)