Jump to content

Editing Module:Sidebar

Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.

Latest revision Your text
Line 1: Line 1:
require('strict')
--
local cfg = mw.loadData('Module:Sidebar/configuration')
-- This module implements {{Sidebar}}
 
--
local p = {}
local p = {}
local HtmlBuilder = require('Module:HtmlBuilder')
local Navbar = require('Module:Navbar')
local function _sidebar(args)
    local root = HtmlBuilder.create('table')
   
    root
        .addClass('vertical-navbox')
        .addClass(args.wraplinks ~= 'true' and 'nowraplinks')
        .addClass(args.bodyclass or args.class)
        .attr('cellspacing', args.cellspacing or 5)
        .attr('cellpadding', args.cellpadding or 0)
        .css('float', args.float or 'right')
        .css('clear', (args.float == 'none' and 'both') or args.float or 'right')
        .css('width', args.width or '22.0em')
        .css('margin', args.float == 'left' and '0 1.0em 1.0em 0' or '0 0 1.0em 1.0em')
        .css('background', '#f9f9f9')
        .css('border', '1px solid #aaa')
        .css('padding', '0.2em')
        .css('border-spacing', '0.4em 0')
        .css('text-align', 'center')
        .css('line-height', '1.4em')
        .css('font-size', '88%')
        .cssText(args.bodystyle or args.style)


local getArgs = require('Module:Arguments').getArgs
    if args.outertitle then
        root
            .tag('caption')
                .addClass(args.outertitleclass)
                .css('padding-bottom', '0.2em')
                .css('font-size', '125%')
                .css('line-height', '1.2em')
                .css('font-weight', 'bold')
                .cssText(args.outertitlestyle)
                .wikitext(args.outertitle)
    end


--[[
    if args.topimage then
Categorizes calling templates and modules with a 'style' parameter of any sort
        local imageCell = root.tag('tr').tag('td')
for tracking to convert to TemplateStyles.
       
        imageCell
            .addClass(args.topimageclass)
            .css('padding', '0.4em 0')
            .cssText(args.topimagestyle)
            .wikitext(args.topimage)
       
        if args.topcaption then
            imageCell
                .tag('div')
                    .css('padding-top', '0.2em')
                    .css('line-height', '1.2em')
                    .cssText(args.topcaptionstyle)
                    .wikitext(args.topcaption)
        end
    end
   
    if args.pretitle then
        root
            .tag('tr')
                .tag('td')
                    .addClass(args.pretitleclass)
                    .cssText(args.basestyle)
                    .css('padding-top', args.topimage and '0.2em' or '0.4em')
                    .css('line-height', '1.2em')
                    .cssText(args.pretitlestyle)
                    .wikitext(args.pretitle)
    end


TODO after a long cleanup: Catch sidebars in other namespaces than Template and Module.
    if args.title then
TODO would probably want to remove /log and /archive as CS1 does
        root
]]
            .tag('tr')
local function categorizeTemplatesWithInlineStyles(args)
                .tag('th')
local title = mw.title.getCurrentTitle()
                    .addClass(args.titleclass)
if title.namespace ~= 10 and title.namespace ~= 828 then return '' end
                    .cssText(args.basestyle)
for _, pattern in ipairs (cfg.i18n.pattern.uncategorized_conversion_titles) do
                    .css('padding', '0.2em 0.4em 0.2em')
if title.text:match(pattern) then return '' end
                    .css('padding-top', args.pretitle and 0)
end
                    .css('font-size', '145%')
                    .css('line-height', '1.2em')
for key, _ in pairs(args) do
                    .cssText(args.titlestyle)
if mw.ustring.find(key, cfg.i18n.pattern.style_conversion) or key == 'width' then
                    .wikitext(args.title)
return cfg.i18n.category.conversion
    end
end
end
end


--[[
    if args.image then
For compatibility with the original {{sidebar with collapsible lists}}
        local imageCell = root.tag('tr').tag('td')
implementation, which passed some parameters through {{#if}} to trim their
       
whitespace. This also triggered the automatic newline behavior.
        imageCell
]]
            .addClass(args.imageclass)
-- See ([[meta:Help:Newlines and spaces#Automatic newline]])
            .css('padding', '0.2em 0 0.4em')
local function trimAndAddAutomaticNewline(s)
            .cssText(args.imagestyle)
s = mw.ustring.gsub(s, "^%s*(.-)%s*$", "%1")
            .wikitext(args.image)
if mw.ustring.find(s, '^[#*:;]') or mw.ustring.find(s, '^{|') then
           
return '\n' .. s
        if args.caption then
else
            imageCell
return s
                .tag('div')
end
                    .css('padding-top', '0.2em')
end
                    .css('line-height', '1.2em')
                    .cssText(args.captionstyle)
                    .wikitext(args.caption)
        end
    end
   
    if args.above then
        root
            .tag('tr')
                .tag('td')
                    .addClass(args.aboveclass)
                    .css('padding', '0.3em 0.4em 0.3em')
                    .css('font-weight', 'bold')
                    .cssText(args.abovestyle)
                    .newline()      -- newline required for bullet-points to work
                    .wikitext(args.above)
    end


--[[
    local rowNums = {}
Finds whether a sidebar has a subgroup sidebar.
    for k, v in pairs(args) do
]]
        k = '' .. k
local function hasSubgroup(s)
        local num = k:match('^heading(%d+)$') or k:match('^content(%d+)$')
if mw.ustring.find(s, cfg.i18n.pattern.subgroup) then
        if num then table.insert(rowNums, tonumber(num)) end
return true
    end
else
    table.sort(rowNums)
return false
    -- remove duplicates from the list (e.g. 3 will be duplicated if both heading3 and content3 are specified)
end
    for i = #rowNums, 1, -1 do
end
        if rowNums[i] == rowNums[i - 1] then
            table.remove(rowNums, i)
        end
    end


local function has_navbar(navbar_mode, sidebar_name)
    for i, num in ipairs(rowNums) do
return navbar_mode ~= cfg.i18n.navbar_none and
        local heading = args['heading' .. num]
navbar_mode ~= cfg.i18n.navbar_off and
        if heading then
(
            root
sidebar_name or
                .tag('tr')
mw.getCurrentFrame():getParent():getTitle():gsub(cfg.i18n.pattern.sandbox, '') ~=
                    .tag('th')
cfg.i18n.title_not_to_add_navbar
                        .addClass(args.headingclass)
)
                        .css('padding', '0.1em')
end
                        .cssText(args.basestyle)
                        .cssText(args.headingstyle)
                        .cssText(args['heading' .. num .. 'style'])
                        .wikitext(heading)
        end
       
        local content = args['content' .. num]
        if content then
            root
                .tag('tr')
                    .tag('td')
                        .addClass(args.contentclass)
                        .css('padding', '0 0.1em 0.4em')
                        .cssText(args.contentstyle)
                        .cssText(args['content' .. num .. 'style'])
                        .newline()
                        .wikitext(content)
                        .done()
                    .newline() -- Without a linebreak after the </td>, a nested list like "* {{hlist| ...}}" doesn't parse correctly.
        end
    end


local function has_list_class(args, htmlclass)
    if args.below then
local patterns = {
        root
'^' .. htmlclass .. '$',
            .tag('tr')
'%s' .. htmlclass .. '$',
                .tag('td')
'^' .. htmlclass .. '%s',
                    .addClass(args.belowclass)
'%s' .. htmlclass .. '%s'
                    .css('padding', '0.3em 0.4em 0.3em')
}
                    .css('font-weight', 'bold')
                    .cssText(args.belowstyle)
for arg, value in pairs(args) do
                    .newline()
if type(arg) == 'string' and mw.ustring.find(arg, 'class') then
                    .wikitext(args.below)
for _, pattern in ipairs(patterns) do
    end
if mw.ustring.find(args[arg] or '', pattern) then
return true
end
end
end
end
return false
end
 
-- there are a lot of list classes in the wild, so we add their TemplateStyles
local function add_list_styles(args)
local frame = mw.getCurrentFrame()
local function add_list_templatestyles(htmlclass, templatestyles)
if has_list_class(args, htmlclass) then
return frame:extensionTag{
name = 'templatestyles', args = { src = templatestyles }
}
else
return ''
end
end
local plainlist_styles = add_list_templatestyles('plainlist', cfg.i18n.plainlist_templatestyles)
local hlist_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
if has_navbar(args.navbar, args.name) and hlist_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]
    local navbarArg = args.navbar or args.tnavbar
return hlist_styles .. plainlist_styles
    if navbarArg ~= 'none' and navbarArg ~= 'off' then
end
        root
            .tag('tr')
                .tag('td')
                    .css('text-align', 'right')
                    .css('font-size', '115%')
                    .cssText(args.navbarstyle or args.tnavbarstyle)
                    .wikitext(Navbar.navbar({
                        args.name or mw.title.getCurrentTitle().fullText,
                        mini = 1,
                        fontstyle = args.navbarfontstyle or args.tnavbarfontstyle
                    }))
    end  


-- work around [[phab:T303378]]
    return tostring(root)
-- for each arg: find all the templatestyles strip markers, insert them into a
-- table. then remove all templatestyles markers from the arg
local function move_hiding_templatestyles(args)
local gfind = string.gfind
local gsub = string.gsub
local templatestyles_markers = {}
local strip_marker_pattern = '(\127[^\127]*UNIQ%-%-templatestyles%-%x+%-QINU[^\127]*\127)'
for k, arg in pairs(args) do
for marker in gfind(arg, strip_marker_pattern) do
table.insert(templatestyles_markers, marker)
end
args[k] = gsub(arg, strip_marker_pattern, '')
end
return templatestyles_markers
end
end


--[[
function _collapsibleSidebar(args)
Main sidebar function. Takes the frame, args, and an optional collapsibleClass.
    args.abovestyle = 'border-top: 1px solid #aaa; border-bottom: 1px solid #aaa;' .. (args.abovestyle or '')
The collapsibleClass is and should be used only for sidebars with collapsible
    args.belowstyle = 'border-top: 1px solid #aaa; border-bottom: 1px solid #aaa;' .. (args.belowstyle or '')
lists, as in p.collapsible.
    args.navbarstyle = 'padding-top: 0.6em;' .. (args.navbarstyle or args.tnavbarstyle or '')
]]
   
function p.sidebar(frame, args, collapsibleClass)
    local contentArgs = {}
if not args then
   
args = getArgs(frame)
    for k, v in pairs(args) do
end
        local num = ('' .. k):match('^list(%d+)$')
local hiding_templatestyles = table.concat(move_hiding_templatestyles(args))
        if num then
local root = mw.html.create()
            local expand = args.expanded and (args.expanded == 'all' or args.expanded == args['list' .. num .. 'name'])
local child = args.child and mw.text.trim(args.child) == cfg.i18n.child_yes
           
            local row = HtmlBuilder.create('div')
            row
                .addClass('NavFrame')
                .addClass((not expand) and 'collapsed')
                .css('border', 'none')
                .css('padding', 0)
                .cssText(args.listframestyle)
                .cssText(args['list' .. num .. 'framestyle'])
                .tag('div')
                    .addClass('NavHead')
                    .addClass(args.listtitleclass)
                    .css('font-size', '105%')
                    .css('background', 'transparent')
                    .css('text-align', 'left')
                    .cssText(args.basestyle)
                    .cssText(args.listtitlestyle)
                    .cssText(args['list' .. num .. 'titlestyle'])
                    .wikitext(args['list' .. num .. 'title'] or 'List')
                    .done()
                .tag('div')
                    .addClass('NavContent')
                    .addClass(args.listclass)
                    .addClass(args['list' .. num .. 'class'])
                    .css('font-size', '105%')
                    .css('padding', '0.2em 0 0.4em')
                    .css('text-align', 'center')
                    .cssText(args.liststyle)
                    .cssText(args['list' .. num .. 'style'])
                    .newline()
                    .wikitext(args['list' .. num])
                   
            contentArgs['content' .. num] = tostring(row)
        end
    end


root = root:tag('table')
    for k, v in pairs(contentArgs) do
if not child then
        args[k] = v
root
    end
:addClass(cfg.i18n.class.sidebar)
   
-- force collapsibleclass to be sidebar-collapse otherwise output nothing
    return _sidebar(args)
:addClass(collapsibleClass == cfg.i18n.class.collapse and cfg.i18n.class.collapse or nil)
:addClass('nomobile')
:addClass(args.float == cfg.i18n.float_none and cfg.i18n.class.float_none or nil)
:addClass(args.float == cfg.i18n.float_left and cfg.i18n.class.float_left or nil)
:addClass(args.wraplinks ~= cfg.i18n.wrap_true and cfg.i18n.class.wraplinks or nil)
:addClass(args.bodyclass or args.class)
:css('width', args.width or nil)
:cssText(args.bodystyle or args.style)
 
if args.outertitle then
root
:tag('caption')
:addClass(cfg.i18n.class.outer_title)
:addClass(args.outertitleclass)
:cssText(args.outertitlestyle)
:wikitext(args.outertitle)
end
 
if args.topimage then
local imageCell = root:tag('tr'):tag('td')
 
imageCell
:addClass(cfg.i18n.class.top_image)
:addClass(args.topimageclass)
:cssText(args.topimagestyle)
:wikitext(args.topimage)
 
if args.topcaption then
imageCell
:tag('div')
:addClass(cfg.i18n.class.top_caption)
:cssText(args.topcaptionstyle)
:wikitext(args.topcaption)
end
end
 
if args.pretitle then
root
:tag('tr')
:tag('td')
:addClass(args.topimage and cfg.i18n.class.pretitle_with_top_image
or cfg.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.bodyclass or args.class)
:cssText(args.bodystyle or args.style)
end
 
if args.title then
if child then
root
:wikitext(args.title)
else
root
:tag('tr')
:tag('th')
:addClass(args.pretitle and cfg.i18n.class.title_with_pretitle
or cfg.i18n.class.title)
:addClass(args.titleclass)
:cssText(args.basestyle)
:cssText(args.titlestyle)
:wikitext(args.title)
end
end
 
if args.image then
local imageCell = root:tag('tr'):tag('td')
 
imageCell
:addClass(cfg.i18n.class.image)
:addClass(args.imageclass)
:cssText(args.imagestyle)
:wikitext(args.image)
 
if args.caption then
imageCell
:tag('div')
:addClass(cfg.i18n.class.caption)
:cssText(args.captionstyle)
:wikitext(args.caption)
end
end
 
if args.above then
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
 
local rowNums = {}
for k, v in pairs(args) do
k = '' .. k
local num = k:match('^heading(%d+)$') or k:match('^content(%d+)$')
if num then table.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)
for i = #rowNums, 1, -1 do
if rowNums[i] == rowNums[i - 1] then
table.remove(rowNums, i)
end
end
 
for i, num in ipairs(rowNums) do
local heading = args['heading' .. num]
if heading then
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
 
local content = args['content' .. num]
if content then
root
:tag('tr')
:tag('td')
:addClass(hasSubgroup(content) and cfg.i18n.class.content_with_subgroup
or cfg.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
 
if args.below then
root
:tag('tr')
:tag('td')
:addClass(cfg.i18n.class.below)
:addClass(args.belowclass)
:cssText(args.belowstyle)
:newline()
:wikitext(args.below)
end
 
if not child and has_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
local base_templatestyles = frame:extensionTag{
name = 'templatestyles', args = { src = cfg.i18n.templatestyles }
}
local templatestyles = ''
if args['templatestyles'] and args['templatestyles'] ~= '' then
templatestyles = frame:extensionTag{
name = 'templatestyles', args = { src = args['templatestyles'] }
}
end
local child_templatestyles = ''
if args['child templatestyles'] and args['child templatestyles'] ~= '' then
child_templatestyles = frame:extensionTag{
name = 'templatestyles', args = { src = args['child templatestyles'] }
}
end
local grandchild_templatestyles = ''
if args['grandchild templatestyles'] and args['grandchild templatestyles'] ~= '' then
grandchild_templatestyles = frame:extensionTag{
name = 'templatestyles', args = { src = args['grandchild templatestyles'] }
}
end
 
return table.concat({
add_list_styles(args), -- see [hlist_note] above about ordering
base_templatestyles,
templatestyles,
child_templatestyles,
grandchild_templatestyles,
hiding_templatestyles,
tostring(root),
(child and cfg.i18n.category.child or ''),
categorizeTemplatesWithInlineStyles(args)
})
end
 
local function list_title(args, is_centered_list_titles, num)
local title_text = trimAndAddAutomaticNewline(args['list' .. num .. 'title']
or cfg.i18n.default_list_title)
 
local title
if is_centered_list_titles then
-- 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
local title_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()
return title_container
end
end
 
                     
--[[
function makeWrapper(func)
Main entry point for sidebar with collapsible lists.
    return function(frame)
Does the work of creating the collapsible lists themselves and including them
        local origArgs
into the args.
        if frame == mw.getCurrentFrame() then
]]
            -- We're being called via #invoke. If the invoking template passed any args, use
function p.collapsible(frame)
            -- them. Otherwise, use the args that were passed into the template.
local args = getArgs(frame)
            origArgs = frame:getParent().args
if not args.name and
            for k, v in pairs(frame.args) do
frame:getParent():getTitle():gsub(cfg.i18n.pattern.collapse_sandbox, '') ==
                origArgs = frame.args
cfg.i18n.collapse_title_not_to_add_navbar then
                break
args.navbar = cfg.i18n.navbar_none
            end
end
        else
 
            -- We're being called from another module or from the debug console, so assume
local contentArgs = {}
            -- the args are passed in directly.
            origArgs = frame
local is_centered_list_titles = false
        end
if args['centered list titles'] and args['centered list titles'] ~= '' then
   
is_centered_list_titles = true
        -- ParserFunctions considers the empty string to be false, so to preserve the previous
end
        -- behavior of the template, change any empty arguments to nil, so Lua will consider
 
        -- them false too.
for k, v in pairs(args) do
        local args = {}
local num = string.match(k, '^list(%d+)$')
        for k, v in pairs(origArgs) do
if num then
            if v ~= '' then
local expand = args.expanded and
                args[k] = v
(args.expanded == 'all' or args.expanded == args['list' .. num .. 'name'])
            end
local row = mw.html.create('div')
        end
row
   
:addClass(cfg.i18n.class.list)
        return func(args)
:addClass('mw-collapsible')
    end
:addClass((not expand) and 'mw-collapsed' or nil)
: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
 
for k, v in pairs(contentArgs) do
args[k] = v
end
 
return p.sidebar(frame, args, cfg.i18n.class.collapse)
end
end


return p
return {
    sidebar = makeWrapper(_sidebar),
    collapsible = makeWrapper(_collapsibleSidebar)
}
Please note that all contributions to OrangDev Labs Wiki may be edited, altered, or removed by other contributors. If you do not want your writing to be edited mercilessly, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource (see OrangDev Labs Wiki:Copyrights for details). Do not submit copyrighted work without permission!
Cancel Editing help (opens in new window)
Preview page with this template

Template used on this page: