Difference between revisions of "Module:Automatic archive navigator/sandbox"

From blackwiki
Jump to navigation Jump to search
blackwiki>Mr. Stradivarius
(add blurb-making methods)
blackwiki>Mr. Stradivarius
(various tweaks, start a function to find the archive numbers to output)
Line 5: Line 5:
 
require('Module:No globals')
 
require('Module:No globals')
 
local checkType = require('libraryUtil').checkType
 
local checkType = require('libraryUtil').checkType
 
+
local yesno = require('Module:Yesno')
-------------------------------------------------------------------------------
 
-- Config
 
-------------------------------------------------------------------------------
 
 
 
local cfg = {
 
['blurb-period'] = "This is an '''[[Help:Archiving a talk page|archive]]''' " ..
 
"of past discussions for the period '''$2'''. '''Do not edit the " ..
 
"contents of this page.''' If you wish to start a new discussion or " ..
 
"revive an old one, please do so on the $1.",
 
['blurb-noperiod'] = "This is an '''[[Help:Archiving a talk page|archive]]''' " ..
 
"of past discussions. '''Do not edit the contents of this page.''' If " ..
 
"you wish to start a new discussion or revive an old one, please do so " ..
 
"on the $1.",
 
['blurb-talk-link-display'] = 'current talk page',
 
['default-icon'] = 'Replacement filing cabinet.svg',
 
['image-size'] = '40x40px'
 
}
 
  
 
-------------------------------------------------------------------------------
 
-------------------------------------------------------------------------------
Line 30: Line 13:
 
local function makeWikilink(page, display)
 
local function makeWikilink(page, display)
 
return string.format('[[%s|%s]]', page, display)
 
return string.format('[[%s|%s]]', page, display)
 +
end
 +
 +
local function escapePattern(s)
 +
-- Escape punctuation in a string so it can be used in a Lua pattern.
 +
pattern = pattern:gsub('%p', '%%%0')
 +
return pattern
 
end
 
end
  
Line 50: Line 39:
 
function Archive:makeLink(current)
 
function Archive:makeLink(current)
 
local subpage = self.prefix .. tostring(self.num)
 
local subpage = self.prefix .. tostring(self.num)
local page = self.basePageName .. subpage
+
local link = makeWikilink('/' .. subpage, subpage)
local link = makeWikilink(page, subpage)
 
 
if current and self.num == current then
 
if current and self.num == current then
 
link = string.format('<span style="font-size:115%;">%s</span>', link)
 
link = string.format('<span style="font-size:115%;">%s</span>', link)
Line 66: Line 54:
  
 
function Navigator.new(args, cfg, currentTitle)
 
function Navigator.new(args, cfg, currentTitle)
local obj = {}
+
local obj = setmetatable({}, Navigator)
setmetatable(obj, Navigator)
 
 
 
-- Set inputs.
+
-- Set inputs
 
obj.args = args
 
obj.args = args
 
obj.cfg = cfg
 
obj.cfg = cfg
 
obj.currentTitle = currentTitle
 
obj.currentTitle = currentTitle
  
-- Define object structure.
+
-- Define object structure
 
obj.links = {}
 
obj.links = {}
 +
 +
-- Archive prefix
 +
-- Decode HTML entities so users can enter things like "Archive&#32;" from
 +
-- wikitext.
 +
obj.archivePrefix = obj.args.prefix or self:message('archive-prefix')
 +
obj.archivePrefix = mw.text.decode(obj.archivePrefix)
 +
 +
-- Current archive number
 +
do
 +
local pattern = string.format(
 +
'^%s([1-9][0-9]*)$',
 +
escapePattern(obj.archivePrefix)
 +
)
 +
obj.currentArchiveNum = obj.currentTitle.subpageText:match(pattern)
 +
obj.currentArchiveNum = tostring(obj.currentArchiveNum)
 +
end
 +
 +
-- Highest archive number
 +
obj.highestArchiveNumber = require('Module:Highest archive number')._main(
 +
obj.currentTitle.baseText .. obj.archivePrefix
 +
)
  
 
return obj
 
return obj
Line 99: Line 107:
 
ret = ret .. args.text
 
ret = ret .. args.text
 
else
 
else
local basePage = self.currentTitle.basePageTitle.prefixedText
 
 
local talkLink = makeWikilink(
 
local talkLink = makeWikilink(
basePage,
+
self.currentTitle.nsText .. ':' .. self.currentTitle.baseText,
 
self:message('blurb-talk-link-display')
 
self:message('blurb-talk-link-display')
 
)
 
)
local key = args.period and 'blurb-period' or 'blurb-noperiod'
+
if args.period then
ret = ret .. self:message(key, talkLink, args.period or '')
+
ret = ret .. self:message('blurb-period', talkLink, args.period)
 +
else
 +
ret = ret .. self:message('blurb-noperiod', talkLink)
 +
end
 
end
 
end
 
return ret
 
return ret
Line 134: Line 144:
 
})
 
})
  
return mbox
+
return mbox .. '__NONEWSECTIONLINK__ __NOEDITSECTION__'
 +
end
 +
 
 +
function Navigator:getArchiveNums()
 +
-- Returns an array of the archive numbers to format.
 +
local noArchives = tonumber(self.args.links) or self:message('default-link-count')
 +
noArchives = math.floor(noArchives)
 +
local allowRedLinks = not yesno(self.args.noredlinks)
 +
local current = self.currentArchiveNum
 +
local highest = self.highestArchiveNum
 +
if allowRedLinks then
 +
-- Allow exactly one red link.
 +
highest = highest + 1
 +
end
 +
 
 +
if not current or not highest or noArchives < 1 then
 +
return {}
 +
elseif noArchives == 1 then
 +
return {current}
 +
end
 +
 +
local function getArchiveOffset(i, current)
 +
-- Gets the positive offset for an archive given i, the position in the
 +
-- array away from the current archive, and the current archive number.
 +
if i <= 2 then
 +
return i
 +
elseif i <= 3 then
 +
-- TODO
 +
else
 +
-- TODO
 +
end
 +
end
 +
 +
local iArchive = 0
 +
-- Archives below the current one.
 +
for i = 1, math.floor((noArchives - 1) / 2) do
 +
end
 
end
 
end
  
Line 140: Line 186:
 
-- Makes a single-row wikitable from an array of links
 
-- Makes a single-row wikitable from an array of links
 
local ret = {}
 
local ret = {}
ret[#ret + 1] = '{| style="width: 32em; background: transparent; margin: 0 auto 0.5em; text-align: center"'
+
ret[#ret + 1] = '{| style="width:32em;background:transparent;' ..
 +
'margin:0 auto 0.5em;text-align:center"'
 
for _, link in ipairs(self.links) do
 
for _, link in ipairs(self.links) do
 
ret[#ret + 1] = '\n| '
 
ret[#ret + 1] = '\n| '
Line 149: Line 196:
 
end
 
end
  
-------------------------------------------------------------------------------
+
function Navigator:__tostring()
-- Exports
+
return self:makeMessageBox()
-------------------------------------------------------------------------------
+
end
 
 
local p = {}
 
  
 
local function getSubpageLink(offset, currentTitle)
 
local function getSubpageLink(offset, currentTitle)
Line 176: Line 221:
 
return nil
 
return nil
 
end
 
end
end
 
 
local function getArchiveNums(current, highest, noLinks, allowRedLinks)
 
-- Returns an array of the archive numbers to format.
 
if not current or not highest then
 
return {}
 
end
 
noLinks = noLinks or 7
 
 
local nums = {}
 
if noLinks >= highest then
 
local lim
 
if allowRedLinks then
 
lim = noLinks
 
else
 
lim = highest
 
end
 
for i = 1, lim do
 
nums[i] = i
 
end
 
end
 
end
 
 
local function foo(prefix)
 
local highestArchive = require('Module:Highest archive number')._main(prefix)
 
 
end
 
end
  
Line 270: Line 290:
 
end
 
end
  
function p._aan(args, currentTitle)
+
-------------------------------------------------------------------------------
currentTitle = currentTitle or mw.title.getCurrentTitle()
+
-- Exports
 +
-------------------------------------------------------------------------------
  
local image = args.image
+
local p = {}
if not image then
 
image = '[[File:' .. (args.icon or 'Replacement filing cabinet.svg') .. '|40x40px|alt=|link=]]'
 
end
 
  
local mbox = require('Module:Message box').main('tmbox', {
+
function p._aan(args, cfg, currentTitle)
image = image,
+
cfg = cfg or require('Module:AutomaticArchiveNavigator/config')
imageright = args.imageright,
+
currentTitle = currentTitle or mw.title.getCurrentTitle()
style = args.style or 'width:80%;margin-left:auto;margin-right:auto;',
+
local aan = Navigator.new(args, cfg, currentTitle)
textstyle = args.textstyle or 'text-align:center;',
+
return tostring(aan)
text = getLinksText(args, currentTitle) .. '\n' .. getMessage(args, currentTitle)
 
})
 
 
 
return mbox .. '__NONEWSECTIONLINK__ __NOEDITSECTION__'
 
 
end
 
end
  
Line 293: Line 307:
 
args.noredlinks = args.noredlinks or false
 
args.noredlinks = args.noredlinks or false
 
return p._aan(args)
 
return p._aan(args)
 +
end
 +
 +
function p._exportClasses()
 +
return {
 +
Archive = Archive,
 +
Navigator = Navigator
 +
}
 
end
 
end
  
Line 306: Line 327:
 
end
 
end
 
end})
 
end})
 
p.Navigator = Navigator
 
p.cfg = cfg
 
  
 
return p
 
return p

Revision as of 06:44, 8 October 2014

Documentation for this module may be created at Module:Automatic archive navigator/sandbox/doc

--
-- This module implements {{Automatic archive navigator}}
--

require('Module:No globals')
local checkType = require('libraryUtil').checkType
local yesno = require('Module:Yesno')

-------------------------------------------------------------------------------
-- Helper functions
-------------------------------------------------------------------------------

local function makeWikilink(page, display)
	return string.format('[[%s|%s]]', page, display)
end

local function escapePattern(s)
	-- Escape punctuation in a string so it can be used in a Lua pattern.
	pattern = pattern:gsub('%p', '%%%0')
	return pattern
end

-------------------------------------------------------------------------------
-- Archive class
-------------------------------------------------------------------------------

local Archive = {}
Archive.__index = Archive

function Archive.new(basePageName, prefix, num)
	checkType('Archive.new', 1, num, 'number')
	local obj = setmetatable({}, Archive)
	obj.basePageName = basePageName
	obj.prefix = prefix
	obj.num = num
	return obj
end

function Archive:makeLink(current)
	local subpage = self.prefix .. tostring(self.num)
	local link = makeWikilink('/' .. subpage, subpage)
	if current and self.num == current then
		link = string.format('<span style="font-size:115%;">%s</span>', link)
	end
	return link
end

-------------------------------------------------------------------------------
-- Navigator class
-------------------------------------------------------------------------------

local Navigator = {}
Navigator.__index = Navigator

function Navigator.new(args, cfg, currentTitle)
	local obj = setmetatable({}, Navigator)
	
	-- Set inputs
	obj.args = args
	obj.cfg = cfg
	obj.currentTitle = currentTitle

	-- Define object structure
	obj.links = {}
	
	-- Archive prefix
	-- Decode HTML entities so users can enter things like "Archive&#32;" from
	-- wikitext.
	obj.archivePrefix = obj.args.prefix or self:message('archive-prefix')
	obj.archivePrefix = mw.text.decode(obj.archivePrefix)

	-- Current archive number
	do
		local pattern = string.format(
			'^%s([1-9][0-9]*)$',
			escapePattern(obj.archivePrefix)
		)
		obj.currentArchiveNum = obj.currentTitle.subpageText:match(pattern)
		obj.currentArchiveNum = tostring(obj.currentArchiveNum)
	end
	
	-- Highest archive number
	obj.highestArchiveNumber = require('Module:Highest archive number')._main(
		 obj.currentTitle.baseText .. obj.archivePrefix
	)

	return obj
end

function Navigator:message(key, ...)
	local msg = self.cfg[key]
	if select('#', ...) > 0 then
		return mw.message.newRawMessage(msg, ...):plain()
	else
		return msg
	end
end

function Navigator:makeBlurb()
	local args = self.args
	if args[1] == '1' then
		-- The old template used "|1" to suppress the blurb.
		return ''
	else
		local ret = '----\n'
		if args.text then
			ret = ret .. args.text
		else
			local talkLink = makeWikilink(
				self.currentTitle.nsText ..	':' .. self.currentTitle.baseText,
				self:message('blurb-talk-link-display')
			)
			if args.period then
				ret = ret .. self:message('blurb-period', talkLink, args.period)
			else
				ret = ret .. self:message('blurb-noperiod', talkLink)
			end
		end
		return ret
	end
end

function Navigator:makeMessageBox()
	local args = self.args
	
	local image
	if args.image then
		image = args.image
	else
		local icon = args.icon or self:message('default-icon')
		image = string.format(
			'[[File:%s|%s|alt=|link=]]',
			icon,
			self:message('image-size')
		)
	end

	local mbox = require('Module:Message box').main('tmbox', {
		image = image,
		imageright = args.imageright,
		style = args.style or 'width:80%;margin-left:auto;margin-right:auto',
		textstyle = args.textstyle or 'text-align:center',
		text = self:makeBlurb()
	})

	return mbox .. '__NONEWSECTIONLINK__ __NOEDITSECTION__'
end

function Navigator:getArchiveNums()
	-- Returns an array of the archive numbers to format.
	local noArchives = tonumber(self.args.links) or self:message('default-link-count')
	noArchives = math.floor(noArchives)
	local allowRedLinks = not yesno(self.args.noredlinks)
	local current = self.currentArchiveNum
	local highest = self.highestArchiveNum
	if allowRedLinks then
		-- Allow exactly one red link.
		highest = highest + 1
	end

	if not current or not highest or noArchives < 1 then
		return {}
	elseif noArchives == 1 then
		return {current}
	end
	
	local function getArchiveOffset(i, current)
		-- Gets the positive offset for an archive given i, the position in the
		-- array away from the current archive, and the current archive number.
		if i <= 2 then
			return i
		elseif i <= 3 then
			-- TODO
		else
			-- TODO
		end
	end
	
	local iArchive = 0
	-- Archives below the current one.
	for i = 1, math.floor((noArchives - 1) / 2) do
	end
end

function Navigator:makeLinksWikitable()
	-- Makes a single-row wikitable from an array of links
	local ret = {}
	ret[#ret + 1] = '{| style="width:32em;background:transparent;' ..
		'margin:0 auto 0.5em;text-align:center"'
	for _, link in ipairs(self.links) do
		ret[#ret + 1] = '\n| '
		ret[#ret + 1] = link
	end
	ret[#ret + 1] = '\n|}'
	return table.concat(ret)
end

function Navigator:__tostring()
	return self:makeMessageBox()
end

local function getSubpageLink(offset, currentTitle)
	-- Get a formatted link to the subpage a certain distance away, or nil
	-- if that subpage does not exist. e.g. If the current subpage is
	-- /Archive 27, then getSubpageLink(3, currentTitle) returns a link to Archive 30.
	local subpageName
	local archiveNum = currentTitle.subpageText:match('^Archive ([1-9][0-9]*)$')
	archiveNum = tonumber(archiveNum)
	if archiveNum then
		subpageName = 'Archive ' .. (archiveNum + offset)
	elseif tonumber(currentTitle.subpageText) then
		subpageName = currentTitle.subpageText + offset
	else
		return nil  -- Couldn't parse out a subpage number
	end

	local subpageTitle = mw.title.new(currentTitle.baseText .. '/' .. subpageName, currentTitle.namespace)
	if subpageTitle.exists then
		return makeWikilink('/' .. subpageName, subpageName)
	else
		return nil
	end
end

local function getLinksText(args, currentTitle)
	local nbsp = '&nbsp;'
	local arrowSpacer, linkSpacer
	if mw.ustring.len(currentTitle.subpageText) <= 4 then
		-- If page names are short, we want more space.
		arrowSpacer = nbsp:rep(5)
		linkSpacer = nbsp:rep(7)
	else
		arrowSpacer = nbsp:rep(2)
		linkSpacer = nbsp:rep(4)
	end

	local ret = {}

	for offset = -5, -3 do
		local link = getSubpageLink(offset, currentTitle)
		if link then
			if offset == -3 then
				ret[#ret + 1] = link
				ret[#ret + 1] = linkSpacer
			else
				ret[#ret + 1] = link
				ret[#ret + 1] = ' ←'
				ret[#ret + 1] = arrowSpacer
			end
			break
		end
	end

	for offset = -2, -1 do
		local link = getSubpageLink(offset, currentTitle)
		if link then
			ret[#ret + 1] = link
			ret[#ret + 1] = linkSpacer
		end
	end

	ret[#ret + 1] = '<span style="font-size:115%;">'
	ret[#ret + 1] = makeWikilink(currentTitle.prefixedText, currentTitle.subpageText)
	ret[#ret + 1] = '</span>'

	for offset = 1, 2 do
		local link = getSubpageLink(offset, currentTitle)
		if link then
			ret[#ret + 1] = linkSpacer
			ret[#ret + 1] = link
		end
	end

	for offset = 5, 3, -1 do
		local link = getSubpageLink(offset, currentTitle)
		if link then
			if offset == 3 then
				ret[#ret + 1] = linkSpacer
				ret[#ret + 1] = link
			else
				ret[#ret + 1] = arrowSpacer
				ret[#ret + 1] = '→ '
				ret[#ret + 1] = link
			end
			break
		end
	end

	return table.concat(ret)
end

-------------------------------------------------------------------------------
-- Exports
-------------------------------------------------------------------------------

local p = {}

function p._aan(args, cfg, currentTitle)
	cfg = cfg or require('Module:AutomaticArchiveNavigator/config')
	currentTitle = currentTitle or mw.title.getCurrentTitle()
	local aan = Navigator.new(args, cfg, currentTitle)
	return tostring(aan)
end

function p._tan(args)
	args.links = args.links or 3
	args.noredlinks = args.noredlinks or false
	return p._aan(args)
end

function p._exportClasses()
	return {
		Archive = Archive,
		Navigator = Navigator
	}
end

setmetatable(p, {__index = function(t, k)
	return function(frame)
		local args = require('Module:Arguments').getArgs(frame, {
			wrappers = {
				'Template:Automatic archive navigator',
				'Template:Talk archive navigation'
			}
		})
		return p['_' .. k](args)
	end
end})

return p