require
(
'strict'
)
local
cfg
=
mw
.
loadData
(
'Module:Sidebar/configuration'
)
local
p
=
{}
local
getArgs
=
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
]]
local
function
categorizeTemplatesWithInlineStyles
(
args
)
local
title
=
mw
.
title
.
getCurrentTitle
()
if
title
.
namespace
~=
10
and
title
.
namespace
~=
828
then
return
''
end
for
_
,
pattern
in
ipairs
(
cfg
.
i18n
.
pattern
.
uncategorized_conversion_titles
)
do
if
title
.
text
:
match
(
pattern
)
then
return
''
end
end
for
key
,
_
in
pairs
(
args
)
do
if
mw
.
ustring
.
find
(
key
,
cfg
.
i18n
.
pattern
.
style_conversion
)
or
key
==
'width'
then
return
cfg
.
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]])
local
function
trimAndAddAutomaticNewline
(
s
)
s
=
mw
.
ustring
.
gsub
(
s
,
"^%s*(.-)%s*$"
,
"%1"
)
if
mw
.
ustring
.
find
(
s
,
'^[#*:;]'
)
or
mw
.
ustring
.
find
(
s
,
'^{|'
)
then
return
'
\n
'
..
s
else
return
s
end
end
--[[
Finds whether a sidebar has a subgroup sidebar.
]]
local
function
hasSubgroup
(
s
)
if
mw
.
ustring
.
find
(
s
,
cfg
.
i18n
.
pattern
.
subgroup
)
then
return
true
else
return
false
end
end
local
function
has_navbar
(
navbar_mode
,
sidebar_name
)
return
navbar_mode
~=
cfg
.
i18n
.
navbar_none
and
navbar_mode
~=
cfg
.
i18n
.
navbar_off
and
(
sidebar_name
or
mw
.
getCurrentFrame
():
getParent
():
getTitle
():
gsub
(
cfg
.
i18n
.
pattern
.
sandbox
,
''
)
~=
cfg
.
i18n
.
title_not_to_add_navbar
)
end
local
function
has_list_class
(
args
,
htmlclass
)
local
patterns
=
{
'^'
..
htmlclass
..
'$'
,
'%s'
..
htmlclass
..
'$'
,
'^'
..
htmlclass
..
'%s'
,
'%s'
..
htmlclass
..
'%s'
}
for
arg
,
value
in
pairs
(
args
)
do
if
type
(
arg
)
==
'string'
and
mw
.
ustring
.
find
(
arg
,
'class'
)
then
for
_
,
pattern
in
ipairs
(
patterns
)
do
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]
return
hlist_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
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
--[[
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.
]]
function
p
.
sidebar
(
frame
,
args
,
collapsibleClass
)
if
not
args
then
args
=
getArgs
(
frame
)
end
local
hiding_templatestyles
=
table.concat
(
move_hiding_templatestyles
(
args
))
local
root
=
mw
.
html
.
create
()
local
child
=
args
.
child
and
mw
.
text
.
trim
(
args
.
child
)
==
cfg
.
i18n
.
child_yes
root
=
root
:
tag
(
'table'
)
if
not
child
then
root
:
addClass
(
cfg
.
i18n
.
class
.
sidebar
)
-- force collapsibleclass to be sidebar-collapse otherwise output nothing
:
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
--[[
Main entry point for sidebar with collapsible lists.
Does the work of creating the collapsible lists themselves and including them
into the args.
]]
function
p
.
collapsible
(
frame
)
local
args
=
getArgs
(
frame
)
if
not
args
.
name
and
frame
:
getParent
():
getTitle
():
gsub
(
cfg
.
i18n
.
pattern
.
collapse_sandbox
,
''
)
==
cfg
.
i18n
.
collapse_title_not_to_add_navbar
then
args
.
navbar
=
cfg
.
i18n
.
navbar_none
end
local
contentArgs
=
{}
local
is_centered_list_titles
=
false
if
args
[
'centered list titles'
]
and
args
[
'centered list titles'
]
~=
''
then
is_centered_list_titles
=
true
end
for
k
,
v
in
pairs
(
args
)
do
local
num
=
string.match
(
k
,
'^list(%d+)$'
)
if
num
then
local
expand
=
args
.
expanded
and
(
args
.
expanded
==
'all'
or
args
.
expanded
==
args
[
'list'
..
num
..
'name'
])
local
row
=
mw
.
html
.
create
(
'div'
)
row
:
addClass
(
cfg
.
i18n
.
class
.
list
)
:
addClass
(
'mw-collapsible'
)
:
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
return
p