Module:Talk archive
Jump to navigation
Jump to search
Implements {{Talk archive}}.
The above documentation is transcluded from Module:Talk archive/doc.
Editors can experiment in this module's sandbox and testcases pages.
Subpages of this module.
Editors can experiment in this module's sandbox and testcases pages.
Subpages of this module.
-------------------------------------------------------------------------------
--
-- Module:Talk archive
--
-- This module implements Template:Talk archive.
-------------------------------------------------------------------------------
require('Module:No globals')
local m_util = require('Module:Util')
local f_exp_search = require('Module:Exponential search')
-- Should we use the sandbox version of our submodules?
local use_sandbox = m_util.misc.maybe_sandbox('Talk archive')
-- The cfg table contains all localisable strings and configuration, to make it
-- easier to port this module to another wiki.
local cfg = use_sandbox and mw.loadData('Module:Talk archive/config/sandbox') or mw.loadData('Module:Talk archive/config')
local i18n = cfg.i18n
-- ----------------------------------------------------------------------------
-- Helper functions
-- ----------------------------------------------------------------------------
local h = {}
function h.escape_pattern(s)
-- Escape punctuation in a string so it can be used in a Lua pattern.
s = s:gsub('%p', '%%%0')
return s
end
-- Checks whether a page exists, going through pcall
-- in case we are over the expensive function limit.
function h.check_page_exists(page)
local success, exists = pcall(function()
return mw.title.new(page).exists
end)
return success and exists
end
-- Return the highest archive number, using exponential search
-- algorithm.
function h.get_highest_archive_number(prefix, start)
return f_exp_search(function (i)
return h.check_page_exists(prefix .. tostring(i))
end, start)
end
-- ----------------------------------------------------------------------------
-- Banner_Nav class
-- ----------------------------------------------------------------------------
local Banner_Nav = {}
Banner_Nav.__index = Banner_Nav
function Banner_Nav.new(args)
-- Create a new Banner_Nav object
local obj = setmetatable({}, Banner_Nav)
obj.args = args
obj.current_title = obj.args.page
-- Decode HTML entities of user supplied prefix so that users can enter
-- things like "Archive " from wikicode. The encoding is needed because
-- trailing spaces are trimmed from template args.
obj.prefix = obj.args.prefix and mw.text.decode(obj.args.prefix) or i18n.archive_prefix
-- Get the current archive page number
local pattern = string.format(
'^%s([1-9][0-9]*)$',
h.escape_pattern(obj.prefix)
)
obj.current_page = tonumber(obj.current_title.subpageText:match(pattern))
-- Find the highest archive page number
obj.highest_page = h.get_highest_archive_number(string.format(
'%s:%s/%s',
obj.current_title.nsText,
obj.current_title.baseText,
obj.prefix
))
return obj
end
function Banner_Nav:message_box()
local title
if self.args.period then
title = string.format(i18n.Banner_Nav.title_blurb_period, self.args.period)
else
title = i18n.Banner_Nav.title_blurb_noperiod
end
local talk_page = string.format('%s:%s', self.current_title.nsText, self.current_title.baseText)
local text = string.format(i18n.Banner_Nav.text_blurb, talk_page)
return mw.getCurrentFrame():expandTemplate{
title = i18n.templates.message_box,
args = {
type = 'lock',
image = i18n.archive_image,
title = title,
text = text,
}
}
end
function Banner_Nav:get_pages()
-- Returns an array of archive page numbers
if not self.current_page then
return {}
end
local range = self.args.range and tonumber(self.args.range) or cfg.nav_link_range
range = math.floor(range)
if range < 1 then
return {self.current_page}
end
local pages = {}
-- Pages numbered lower than current page
for i = -range, -1 do
local page = self.current_page + i
if page >= 1 then
table.insert(pages, page)
end
end
-- Current page
table.insert(pages, self.current_page)
-- Pages numbered higher than current page
for i = 1, range do
local page = self.current_page + i
if page <= self.highest_page then
table.insert(pages, page)
end
end
return pages
end
function Banner_Nav:navigation()
local pages = self:get_pages()
if #pages < 1 then
return ''
end
local html = mw.html.create('div')
:cssText('text-align:center;')
local list = html:tag('ul')
:addClass('hlist')
:newline()
for i, p in ipairs(pages) do
local list_item = list:tag('li')
if p then
local subpage = self.prefix .. tostring(p)
local display = p == self.current_page and string.format(i18n.Banner_Nav.link_text, p) or tostring(p)
local link = m_util.html.wikilink('../' .. subpage, display)
if i == 1 and p ~= self.current_page then
list_item:wikitext(string.format(i18n.Banner_Nav.before_fmt, link))
elseif i == #pages and p ~= self.current_page then
list_item:wikitext(string.format(i18n.Banner_Nav.after_fmt, link))
else
list_item:wikitext(link)
end
end
list:newline()
end
return tostring(html)
end
function Banner_Nav:__tostring()
return table.concat({
self:message_box(),
'\n',
self:navigation(),
' __NONEWSECTIONLINK__ __NOEDITSECTION__',
})
end
-- ----------------------------------------------------------------------------
-- Main functions
-- ----------------------------------------------------------------------------
local function _talk_archive(args)
args.page = args.page and mw.title.new(args.page) or mw.title.getCurrentTitle()
local t = Banner_Nav.new(args)
return tostring(t)
end
-- ----------------------------------------------------------------------------
-- Exported functions
-- ----------------------------------------------------------------------------
local p = {}
--
-- Template:Talk archive
--
p.talk_archive = m_util.misc.invoker_factory(_talk_archive, {
wrappers = cfg.wrappers.talk_archive,
})
return p