Module:Sidebar/sandbox
Appearance
From Wikipedia, the free encyclopedia
Warning This Lua module is used on 413,000+ pages .
To avoid major disruption and server load, any changes should be tested in the module's /sandbox or /testcases subpages, or in your own module sandbox. The tested changes can be added to this page in a single edit. Consider discussing changes on the talk page before implementing them.
To avoid major disruption and server load, any changes should be tested in the module's /sandbox or /testcases subpages, or in your own module sandbox. The tested changes can be added to this page in a single edit. Consider discussing changes on the talk page before implementing them.
This module is rated as ready for general use. It has reached a mature state, is considered relatively stable and bug-free, and may be used wherever appropriate. It can be mentioned on help pages and other Wikipedia resources as an option for new users. To minimise server load and avoid disruptive output, improvements should be developed through sandbox testing rather than repeated trial-and-error editing.
This module employs intricate features of the Lua scripting language whose syntax is different from that of templates.
It is recommended you first familiarise yourself with Lua by reading the reference manual and other resources before editing it.
You can conduct experiments, and should test all major changes, in either this modules's sandbox , your own user sandbox, or the general module sandbox which has a convenient template sandbox tool, before changing anything.
You can conduct experiments, and should test all major changes, in either this modules's sandbox , your own user sandbox, or the general module sandbox which has a convenient template sandbox tool, before changing anything.
This module depends on the following other modules:
CSS This module uses TemplateStyles:
This module implements the templates {{sidebar }} and {{sidebar with collapsible lists }}. See the individual template pages for documentation.
The above documentation is transcluded from Module:Sidebar/doc. (edit | history)
Editors can experiment in this module's sandbox (edit | diff) and testcases (create) pages.
Add categories to the /doc subpage. Subpages of this module.
Editors can experiment in this module's sandbox (edit | diff) and testcases (create) pages.
Add categories to the /doc subpage. Subpages of this module.
require('strict') localcfg=mw.loadData('Module:Sidebar/configuration/sandbox') localp={} localgetArgs=require('Module:Arguments').getArgs --[[ Categorizes calling templates and modules with a 'style' parameter of any sort for tracking to convert to TemplateStyles. TODO after a long cleanup: Catch sidebars in other namespaces than Template and Module. TODO would probably want to remove /log and /archive as CS1 does ]] localfunctioncategorizeTemplatesWithInlineStyles(args) localtitle=mw.title.getCurrentTitle() iftitle.namespace~=10andtitle.namespace~=828thenreturn''end for_,patterninipairs(cfg.i18n.pattern.uncategorized_conversion_titles)do iftitle.text:match(pattern)thenreturn''end end forkey,_inpairs(args)do ifmw.ustring.find(key,cfg.i18n.pattern.style_conversion)orkey=='width'then returncfg.i18n.category.conversion end end end --[[ For compatibility with the original {{sidebar with collapsible lists}} implementation, which passed some parameters through {{#if}} to trim their whitespace. This also triggered the automatic newline behavior. ]] -- See ([[meta:Help:Newlines and spaces#Automatic newline]]) localfunctiontrimAndAddAutomaticNewline(s) s=mw.ustring.gsub(s,"^%s*(.-)%s*$","%1") ifmw.ustring.find(s,'^[#*:;]')ormw.ustring.find(s,'^{|')then return'\n'..s else returns end end --[[ Finds whether a sidebar has a subgroup sidebar. ]] localfunctionhasSubgroup(s) ifmw.ustring.find(s,cfg.i18n.pattern.subgroup)then returntrue else returnfalse end end localfunctionhas_navbar(navbar_mode,sidebar_name) returnnavbar_mode~=cfg.i18n.navbar_noneand navbar_mode~=cfg.i18n.navbar_offand ( sidebar_nameor mw.getCurrentFrame():getParent():getTitle():gsub(cfg.i18n.pattern.sandbox,'')~= cfg.i18n.title_not_to_add_navbar ) end localfunctionhas_list_class(args,htmlclass) localpatterns={ '^'..htmlclass..'$', '%s'..htmlclass..'$', '^'..htmlclass..'%s', '%s'..htmlclass..'%s' } forarg,valueinpairs(args)do iftype(arg)=='string'andmw.ustring.find(arg,'class')then for_,patterninipairs(patterns)do ifmw.ustring.find(args[arg]or'',pattern)then returntrue end end end end returnfalse end -- there are a lot of list classes in the wild, so we add their TemplateStyles localfunctionadd_list_styles(args) localframe=mw.getCurrentFrame() localfunctionadd_list_templatestyles(htmlclass,templatestyles) ifhas_list_class(args,htmlclass)then returnframe:extensionTag{ name='templatestyles',args={src=templatestyles} } else return'' end end localplainlist_styles=add_list_templatestyles('plainlist',cfg.i18n.plainlist_templatestyles) localhlist_styles=add_list_templatestyles('hlist',cfg.i18n.hlist_templatestyles) -- a second workaround for [[phab:T303378]] -- when that issue is fixed, we can actually use has_navbar not to emit the -- tag here if we want ifhas_navbar(args.navbar,args.name)andhlist_styles==''then hlist_styles=frame:extensionTag{ name='templatestyles',args={src=cfg.i18n.hlist_templatestyles} } end -- hlist -> plainlist is best-effort to preserve old Common.css ordering. [hlist_note] returnhlist_styles..plainlist_styles end -- work around [[phab:T303378]] -- for each arg: find all the templatestyles strip markers, insert them into a -- table. then remove all templatestyles markers from the arg localfunctionmove_hiding_templatestyles(args) localgfind=string.gfind localgsub=string.gsub localtemplatestyles_markers={} localstrip_marker_pattern='(127円[^127円]*UNIQ%-%-templatestyles%-%x+%-QINU[^127円]*127円)' fork,arginpairs(args)do formarkeringfind(arg,strip_marker_pattern)do table.insert(templatestyles_markers,marker) end args[k]=gsub(arg,strip_marker_pattern,'') end returntemplatestyles_markers end localfunctionadd_notpageimage_class(image_arg) ifstring.match(image_arg,'^%[%[File:')orstring.match(image_arg,'^%[%[Image:')then image_arg=mw.text.trim(image_arg) ifimage_arg:find('class=')then image_arg=image_arg:gsub('class=','class=notpageimage ') else image_arg=image_arg:sub(1,-3)..'|class=notpageimage]]' end returnimage_arg end end --[[ Main sidebar function. Takes the frame, args, and an optional collapsibleClass. The collapsibleClass is and should be used only for sidebars with collapsible lists, as in p.collapsible. ]] functionp.sidebar(frame,args,collapsibleClass) ifnotargsthen args=getArgs(frame) end localhiding_templatestyles=table.concat(move_hiding_templatestyles(args)) localroot=mw.html.create() localchild=args.childandmw.text.trim(args.child)==cfg.i18n.child_yes root=root:tag('table') ifnotchildthen root :addClass(cfg.i18n.class.sidebar) -- force collapsibleclass to be sidebar-collapse otherwise output nothing :addClass(collapsibleClass==cfg.i18n.class.collapseandcfg.i18n.class.collapseornil) :addClass('nomobile') :addClass(args.float==cfg.i18n.float_noneandcfg.i18n.class.float_noneornil) :addClass(args.float==cfg.i18n.float_leftandcfg.i18n.class.float_leftornil) :addClass(args.wraplinks~=cfg.i18n.wrap_trueandcfg.i18n.class.wraplinksornil) :addClass(args.bodyclassorargs.class) :attr('role','navigation') :css('width',args.widthornil) :cssText(args.bodystyleorargs.style) ifargs.outertitlethen root :tag('caption') :addClass(cfg.i18n.class.outer_title) :addClass(args.outertitleclass) :cssText(args.outertitlestyle) :wikitext(args.outertitle) end ifargs.topimagethen localimageCell=root:tag('tr'):tag('td') imageCell :addClass(cfg.i18n.class.top_image) :addClass(args.topimageclass) :cssText(args.topimagestyle) :wikitext(add_notpageimage_class(args.topimage)) ifargs.topcaptionthen imageCell :tag('div') :addClass(cfg.i18n.class.top_caption) :cssText(args.topcaptionstyle) :wikitext(args.topcaption) end end ifargs.pretitlethen root :tag('tr') :tag('td') :addClass(args.topimageandcfg.i18n.class.pretitle_with_top_image orcfg.i18n.class.pretitle) :addClass(args.pretitleclass) :cssText(args.basestyle) :cssText(args.pretitlestyle) :wikitext(args.pretitle) end else root :addClass(cfg.i18n.class.subgroup) :addClass(args.bodyclassorargs.class) :cssText(args.bodystyleorargs.style) end ifargs.titlethen ifchildthen root :wikitext(args.title) else root :tag('tr') :tag('th') :addClass(args.pretitleandcfg.i18n.class.title_with_pretitle orcfg.i18n.class.title) :addClass(args.titleclass) :cssText(args.basestyle) :cssText(args.titlestyle) :wikitext(args.title) end end ifargs.imagethen localimageCell=root:tag('tr'):tag('td') imageCell :addClass(cfg.i18n.class.image) :addClass(args.imageclass) :cssText(args.imagestyle) :wikitext(add_notpageimage_class(args.image)) ifargs.captionthen imageCell :tag('div') :addClass(cfg.i18n.class.caption) :cssText(args.captionstyle) :wikitext(args.caption) end end ifargs.abovethen root :tag('tr') :tag('td') :addClass(cfg.i18n.class.above) :addClass(args.aboveclass) :cssText(args.abovestyle) :newline()-- newline required for bullet-points to work :wikitext(args.above) end localrowNums={} fork,vinpairs(args)do k=''..k localnum=k:match('^heading(%d+)$')ork:match('^content(%d+)$') ifnumthentable.insert(rowNums,tonumber(num))end end table.sort(rowNums) -- remove duplicates from the list (e.g. 3 will be duplicated if both heading3 -- and content3 are specified) fori=#rowNums,1,-1do ifrowNums[i]==rowNums[i-1]then table.remove(rowNums,i) end end fori,numinipairs(rowNums)do localheading=args['heading'..num] ifheadingthen root :tag('tr') :tag('th') :addClass(cfg.i18n.class.heading) :addClass(args.headingclass) :addClass(args['heading'..num..'class']) :cssText(args.basestyle) :cssText(args.headingstyle) :cssText(args['heading'..num..'style']) :newline() :wikitext(heading) end localcontent=args['content'..num] ifcontentthen root :tag('tr') :tag('td') :addClass(hasSubgroup(content)andcfg.i18n.class.content_with_subgroup orcfg.i18n.class.content) :addClass(args.contentclass) :addClass(args['content'..num..'class']) :cssText(args.contentstyle) :cssText(args['content'..num..'style']) :newline() :wikitext(content) :done() -- Without a linebreak after the </td>, a nested list like -- "* {{hlist| ...}}" doesn't parse correctly. :newline() end end ifargs.belowthen root :tag('tr') :tag('td') :addClass(cfg.i18n.class.below) :addClass(args.belowclass) :cssText(args.belowstyle) :newline() :wikitext(args.below) end ifnotchildandhas_navbar(args.navbar,args.name)then root :tag('tr') :tag('td') :addClass(cfg.i18n.class.navbar) :cssText(args.navbarstyle) :wikitext(require('Module:Navbar')._navbar{ args.name, mini=1, fontstyle=args.navbarfontstyle }) end localbase_templatestyles=frame:extensionTag{ name='templatestyles',args={src=cfg.i18n.templatestyles} } localtemplatestyles='' ifargs['templatestyles']andargs['templatestyles']~=''then templatestyles=frame:extensionTag{ name='templatestyles',args={src=args['templatestyles']} } end localchild_templatestyles='' ifargs['child templatestyles']andargs['child templatestyles']~=''then child_templatestyles=frame:extensionTag{ name='templatestyles',args={src=args['child templatestyles']} } end localgrandchild_templatestyles='' ifargs['grandchild templatestyles']andargs['grandchild templatestyles']~=''then grandchild_templatestyles=frame:extensionTag{ name='templatestyles',args={src=args['grandchild templatestyles']} } end returntable.concat({ add_list_styles(args),-- see [hlist_note] above about ordering base_templatestyles, templatestyles, child_templatestyles, grandchild_templatestyles, hiding_templatestyles, tostring(root), (childandcfg.i18n.category.childor''), categorizeTemplatesWithInlineStyles(args) }) end localfunctionlist_title(args,is_centered_list_titles,num) localtitle_text=trimAndAddAutomaticNewline(args['list'..num..'title'] orcfg.i18n.default_list_title) localtitle ifis_centered_list_titlesthen -- collapsible can be finicky, so provide some CSS/HTML to support title=mw.html.create('div') :addClass(cfg.i18n.class.list_title_centered) :wikitext(title_text) else title=mw.html.create() :wikitext(title_text) end localtitle_container=mw.html.create('div') :addClass(cfg.i18n.class.list_title) -- don't /need/ a listnumtitleclass because you can do -- .templateclass .listnumclass .sidebar-list-title :addClass(args.listtitleclass) :cssText(args.basestyle) :cssText(args.listtitlestyle) :cssText('color: var(--color-base)') :cssText(args['list'..num..'titlestyle']) :node(title) :done() returntitle_container end --[[ Main entry point for sidebar with collapsible lists. Does the work of creating the collapsible lists themselves and including them into the args. ]] functionp.collapsible(frame) localargs=getArgs(frame) ifnotargs.nameand frame:getParent():getTitle():gsub(cfg.i18n.pattern.collapse_sandbox,'')== cfg.i18n.collapse_title_not_to_add_navbarthen args.navbar=cfg.i18n.navbar_none end localcontentArgs={} localis_centered_list_titles=false ifargs['centered list titles']andargs['centered list titles']~=''then is_centered_list_titles=true end fork,vinpairs(args)do localnum=string.match(k,'^list(%d+)$') ifnumthen localexpand=args.expandedand (args.expanded=='all'orargs.expanded==args['list'..num..'name']) localrow=mw.html.create('div') row :addClass(cfg.i18n.class.list) :addClass('mw-collapsible') :addClass((notexpand)and'mw-collapsed'ornil) :addClass(args['list'..num..'class']) :cssText(args.listframestyle) :cssText(args['list'..num..'framestyle']) :node(list_title(args,is_centered_list_titles,num)) :tag('div') :addClass(cfg.i18n.class.list_content) :addClass('mw-collapsible-content') -- don't /need/ a listnumstyleclass because you can do -- .templatename .listnumclass .sidebar-list :addClass(args.listclass) :cssText(args.liststyle) :cssText(args['list'..num..'style']) :wikitext(trimAndAddAutomaticNewline(args['list'..num])) contentArgs['content'..num]=tostring(row) end end fork,vinpairs(contentArgs)do args[k]=v end returnp.sidebar(frame,args,cfg.i18n.class.collapse) end returnp