Module:Sidebar
Jump to navigation
Jump to search
Documentation for this module may be created at Module:Sidebar/doc
--------------------------------------------------------------------------------
-- Module:Sidebar
-- Sidebar system for supplementary content and navigation.
--
-- INSTALLATION:
-- 1. Create page: Module:Sidebar
-- 2. Paste this entire file
-- 3. Create TemplateStyles page: Module:Sidebar/styles.css
--
-- USAGE:
-- {{#invoke:Sidebar|sidebar|name=Title|content=Content here}}
-- {{#invoke:Sidebar|portal|Portal Name}}
-- {{#invoke:Sidebar|collapsible|header=Title|content=...}}
--
-- @author Remilia Wiki
-- @license MIT
--------------------------------------------------------------------------------
local p = {}
--------------------------------------------------------------------------------
-- CONFIGURATION
--------------------------------------------------------------------------------
local MAX_SECTIONS = 20
--------------------------------------------------------------------------------
-- UTILITY FUNCTIONS
--------------------------------------------------------------------------------
local function trim(s)
if not s then return nil end
return tostring(s):match("^%s*(.-)%s*$")
end
local function isEmpty(s)
if s == nil then return true end
if type(s) == 'string' then
return trim(s) == ''
end
return false
end
local function hasValue(s)
return not isEmpty(s)
end
local function getArg(args, name, default)
local val = args[name]
if isEmpty(val) then return default end
return trim(val)
end
local function getFrameArgs(frame)
local args = {}
local parentArgs = frame:getParent() and frame:getParent().args or {}
local directArgs = frame.args or {}
for k, v in pairs(directArgs) do args[k] = v end
for k, v in pairs(parentArgs) do args[k] = v end
return args
end
--------------------------------------------------------------------------------
-- BASIC SIDEBAR
--------------------------------------------------------------------------------
function p.sidebar(frame)
local args = getFrameArgs(frame)
local name = getArg(args, 'name') or getArg(args, 'title')
local image = getArg(args, 'image')
local imageSize = getArg(args, 'image_size', '200px')
local caption = getArg(args, 'caption')
local content = getArg(args, 'content') or getArg(args, 1)
local below = getArg(args, 'below')
local above = getArg(args, 'above')
local bodyclass = getArg(args, 'bodyclass')
local position = getArg(args, 'position', 'right')
-- Build the sidebar
local container = mw.html.create('div')
:addClass('sidebar')
if position == 'left' then
container:addClass('sidebar-left')
end
if hasValue(bodyclass) then
container:addClass(bodyclass)
end
-- Title
if hasValue(name) then
container:tag('div')
:addClass('sidebar-title')
:wikitext(name)
end
-- Above
if hasValue(above) then
container:tag('div')
:addClass('sidebar-above')
:wikitext(above)
end
-- Image
if hasValue(image) then
local imageDiv = container:tag('div')
:addClass('sidebar-image')
imageDiv:wikitext('[[File:' .. image .. '|' .. imageSize .. ']]')
if hasValue(caption) then
imageDiv:tag('div')
:addClass('sidebar-caption')
:wikitext(caption)
end
end
-- Content
if hasValue(content) then
container:tag('div')
:addClass('sidebar-content')
:wikitext(content)
end
-- Numbered sections (heading1/content1, heading2/content2, etc.)
for i = 1, MAX_SECTIONS do
local heading = getArg(args, 'heading' .. i)
local sectionContent = getArg(args, 'content' .. i)
if hasValue(heading) or hasValue(sectionContent) then
if hasValue(heading) then
container:tag('div')
:addClass('sidebar-heading')
:wikitext(heading)
end
if hasValue(sectionContent) then
container:tag('div')
:addClass('sidebar-content')
:wikitext(sectionContent)
end
end
end
-- Below
if hasValue(below) then
container:tag('div')
:addClass('sidebar-below')
:wikitext(below)
end
return tostring(container)
end
--------------------------------------------------------------------------------
-- COLLAPSIBLE SIDEBAR
--------------------------------------------------------------------------------
function p.collapsible(frame)
local args = getFrameArgs(frame)
local title = getArg(args, 'title') or getArg(args, 'name')
local state = getArg(args, 'state', 'autocollapse')
local bodyclass = getArg(args, 'bodyclass')
local position = getArg(args, 'position', 'right')
if isEmpty(title) then
return '<span class="error">Error: Sidebar title required</span>'
end
-- Build the sidebar
local container = mw.html.create('div')
:addClass('sidebar')
:addClass('sidebar-collapsible')
:addClass('mw-collapsible')
if state == 'collapsed' then
container:addClass('mw-collapsed')
end
if position == 'left' then
container:addClass('sidebar-left')
end
if hasValue(bodyclass) then
container:addClass(bodyclass)
end
-- Title (clickable header)
container:tag('div')
:addClass('sidebar-title')
:addClass('mw-collapsible-toggle')
:wikitext(title)
-- Content container
local contentContainer = container:tag('div')
:addClass('mw-collapsible-content')
-- Numbered sections
for i = 1, MAX_SECTIONS do
local heading = getArg(args, 'heading' .. i)
local sectionContent = getArg(args, 'content' .. i) or getArg(args, 'list' .. i)
if hasValue(heading) or hasValue(sectionContent) then
if hasValue(heading) then
contentContainer:tag('div')
:addClass('sidebar-heading')
:wikitext(heading)
end
if hasValue(sectionContent) then
contentContainer:tag('div')
:addClass('sidebar-content')
:wikitext(sectionContent)
end
end
end
-- General content
local content = getArg(args, 'content')
if hasValue(content) then
contentContainer:tag('div')
:addClass('sidebar-content')
:wikitext(content)
end
-- Below
local below = getArg(args, 'below')
if hasValue(below) then
contentContainer:tag('div')
:addClass('sidebar-below')
:wikitext(below)
end
return tostring(container)
end
--------------------------------------------------------------------------------
-- PORTAL SIDEBAR
--------------------------------------------------------------------------------
function p.portal(frame)
local args = getFrameArgs(frame)
local name = getArg(args, 1) or getArg(args, 'name')
if isEmpty(name) then
return '<span class="error">Error: Portal name required</span>'
end
local image = getArg(args, 'image')
local imageSize = getArg(args, 'image_size', '32px')
-- Build the portal box
local container = mw.html.create('div')
:addClass('sidebar')
:addClass('sidebar-portal')
local content = container:tag('div')
:addClass('sidebar-content')
:addClass('portal-content')
-- Icon
if hasValue(image) then
content:wikitext('[[File:' .. image .. '|' .. imageSize .. '|link=Portal:' .. name .. ']] ')
end
-- Link
content:wikitext('[[Portal:' .. name .. '|' .. name .. ' portal]]')
return tostring(container)
end
--------------------------------------------------------------------------------
-- TOCLIMIT (Table of contents limiter)
--------------------------------------------------------------------------------
function p.toclimit(frame)
local args = getFrameArgs(frame)
local limit = getArg(args, 1) or getArg(args, 'limit', '2')
-- Generate CSS to hide TOC levels
local css = mw.html.create('style')
:wikitext('.toclevel-' .. (tonumber(limit) + 1) .. ', ' ..
'.toclevel-' .. (tonumber(limit) + 2) .. ', ' ..
'.toclevel-' .. (tonumber(limit) + 3) .. ', ' ..
'.toclevel-' .. (tonumber(limit) + 4) .. ', ' ..
'.toclevel-' .. (tonumber(limit) + 5) .. ', ' ..
'.toclevel-' .. (tonumber(limit) + 6) .. ' { display: none; }')
return tostring(css)
end
return p