Difference between revisions of "Module:Reply to/sandbox"

From blackwiki
Jump to navigation Jump to search
blackwiki>Mr. Stradivarius
(make sure that only args[1] can have a label of args.label)
blackwiki>Ahecht
(sync)
Line 1: Line 1:
-- This module implements {{reply to}}.
 
 
 
local p = {}
 
local p = {}
  
-- The maximum number of users that can receive notifications in one edit
+
function p.replyto(frame)
local MAX_USERS = 50
+
local origArgs = frame:getParent().args
 
+
local args = {}
-- Make an HTML error from the supplied error message.
+
local maxArg = 1
local function makeHTMLError(msg)
+
local usernames = 0
msg = string.format(
+
for k, v in pairs(origArgs) do
'Error in [[Template:Reply to]]: %s.',
 
msg
 
)
 
return require('Module:Error').error{msg}
 
end
 
 
 
-- Make a title object for the given user's user page. If the username contains
 
-- invalid characters, returns nil. Usernames can be given as 'Foo' or
 
-- 'User:Foo'. If a user subpage is supplied, the title for the root user page
 
-- is returned.
 
local function makeUserTitle(user)
 
local title = mw.title.new(user, 2)
 
if title then
 
return title.rootPageTitle
 
else
 
return nil
 
end
 
end
 
 
 
-- Make a wikilink with the given page and display text.
 
local function makeWikilink(page, display)
 
return string.format('[[%s|%s]]', page, display)
 
end
 
 
 
-- Return an array of numbers for all specified positional arguments.
 
local function findArgNums(args)
 
local ret = {}
 
for k in pairs(args) do
 
 
if type(k) == 'number' then
 
if type(k) == 'number' then
table.insert(ret, k)
+
if mw.ustring.match(v,'%S') then
 +
if k > maxArg then maxArg = k end
 +
usernames = usernames + 1
 +
local title = mw.title.new(v)
 +
if not title then return '<strong class="error">Error in [[Template:Reply to]]: Input contains forbidden characters.</strong>' end
 +
args[k] = title.rootText
 +
end
 +
elseif v == '' and k:sub(0,5) == 'label' then
 +
args[k] = '&#x200B;'
 +
else
 +
args[k] = v
 
end
 
end
 
end
 
end
table.sort(ret)
 
return ret
 
end
 
  
-- Validate the number of users. Returns true if the number is valid, and
+
if usernames > (tonumber(frame.args.max) or 50) then
-- returns false and an error message if invalid.
+
return string.format(
local function validateArgNums(nums)
+
'<strong class="error">Error in [[Template:Reply to]]: More than %s names specified.</strong>',
local nUsers = #nums
+
tostring(frame.args.max or 50)
if nUsers < 1 then
 
return false, 'No usernames given'
 
elseif nUsers > MAX_USERS then
 
return false, string.format('More than %d names specified', MAX_USERS)
 
end
 
return true
 
end
 
 
 
-- Make a single user link from a username and a display. If there was an error,
 
-- return false and an error message.
 
local function makeUserLink(username, display)
 
local userTitle = makeUserTitle(username)
 
if not userTitle then
 
return false, string.format(
 
"'%s' is not a valid username or user page",
 
username
 
 
)
 
)
end
+
else
return makeWikilink(userTitle.prefixedText, display)
+
if usernames < 1 then
end
+
if frame.args.example then args[1] = frame.args.example else return '<strong class="error">Error in [[Template:Reply to]]: Username not given.</strong>' end
 
 
-- Make a table of user links from the arg nums and the args table. Returns
 
-- true plus the table of user links if everything went well; returns false and
 
-- an error message if there were any errors.
 
local function makeUserLinks(nums, args)
 
local links = {}
 
do
 
-- Special case for the first link. If the first username is in args[1]
 
-- (which it usually is) then the label can be either args.label1 or
 
-- args.label.
 
local num = nums[1]
 
local username = args[num]
 
local numKey = 'label' .. tostring(num)
 
local display
 
if args[numKey] then
 
display = args[numKey]
 
elseif num == 1 and args.label then
 
display = args.label
 
else
 
display = username
 
 
end
 
end
local link, message = makeUserLink(username, display)
+
local isfirst = true
if not link then
+
local outStr = ''
return false, message
+
for i = 1, maxArg do
end
+
if args[i] then
table.insert(links, link)
+
if isfirst then
end
+
outStr = string.format(
for i = 2, #nums do
+
'<span class="template-ping">%s[[User:%s|%s]]',
-- Make the second and subsequent links.
+
args['prefix'] or '@',
local num = nums[i]
+
args[i],
local username = args[num]
+
(args['label1'] or args['label']) or args[i]
local display = args['label' .. tostring(num)] or username
+
)
local link, message = makeUserLink(username, display)
+
isfirst = false
if not link then
+
else
return false, message
+
if ( (usernames > 2) or ((usernames == 2) and (args['c'] == '')) ) then outStr = outStr..',' end
end
+
if i == maxArg then outStr = outStr..' '..(args['c'] or 'and') end
table.insert(links, link)
+
outStr = string.format(
end
+
'%s [[User:%s|%s]]',
return true, links
+
outStr,
end
+
args[i],
 
+
args['label'..tostring(i)] or args[i]
-- Assemble the output string from the table of links and from the arguments.
+
)
-- Returns the output string.
+
end
local function makeOutputString(links, args)
 
local prefix = args.prefix or '@'
 
local separator = ', '
 
local conjunction
 
if args.c == '' then
 
conjunction = separator
 
elseif args.c then
 
conjunction = ', ' .. args.c .. ' '
 
elseif #links == 2 then
 
conjunction = ' and '
 
else
 
conjunction = ', and '
 
end
 
local punctuation = args.p or ':'
 
return string.format(
 
'<span class="template-ping">%s%s%s</span>',
 
prefix,
 
mw.text.listToText(links, separator, conjunction),
 
punctuation
 
)
 
end
 
 
 
-- The entry point from other Lua modules.
 
function p._replyto(args)
 
-- Find the numbers of positional arguments that have been specified, and
 
-- check that they are valid.
 
local nums = findArgNums(args)
 
local numsAreValid, message = validateArgNums(nums)
 
if not numsAreValid then
 
return makeHTMLError(message)
 
end
 
 
-- Assemble the links
 
local linksAreValid, links = makeUserLinks(nums, args)
 
if not linksAreValid then
 
return makeHTMLError(links)
 
end
 
 
 
-- Assemble the output
 
return makeOutputString(links, args)
 
end
 
 
 
-- The entry point from #invoke.
 
function p.replyto(frame)
 
local parentArgs = frame:getParent().args
 
-- Trim and remove blanks for positional args, but leave named args as is.
 
-- (Note that named args are trimmed by MediaWiki, so we don't need to do it
 
-- again.)
 
local args = {}
 
for k, v in pairs(parentArgs) do
 
if type(k) == 'number' then
 
-- This is a positional arg
 
v = v:match('^%s*(.-)%s*$') -- Trim whitespace
 
if v ~= '' then
 
args[k] = v
 
 
end
 
end
else
 
-- This is a named arg
 
args[k] = v
 
 
end
 
end
 +
outStr = outStr..(args['p'] or ':')..'</span>'
 +
return outStr
 
end
 
end
return p._replyto(args)
 
 
end
 
end
  
 
return p
 
return p

Revision as of 00:44, 4 July 2018

Documentation for this module may be created at Module:Reply to/sandbox/doc

local p = {}

function p.replyto(frame)
	local origArgs = frame:getParent().args
	local args = {}
	local maxArg = 1
	local usernames = 0
	for k, v in pairs(origArgs) do
		if type(k) == 'number' then
			if mw.ustring.match(v,'%S') then
				if k > maxArg then maxArg = k end
				usernames = usernames + 1
				local title = mw.title.new(v)
				if not title then return '<strong class="error">Error in [[Template:Reply to]]: Input contains forbidden characters.</strong>' end
				args[k] = title.rootText
			end
		elseif v == '' and k:sub(0,5) == 'label' then
			args[k] = '&#x200B;'
		else
			args[k] = v
		end
	end

	if usernames > (tonumber(frame.args.max) or 50) then
		return string.format(
			'<strong class="error">Error in [[Template:Reply to]]: More than %s names specified.</strong>',
			tostring(frame.args.max or 50)
		)
	else
		if usernames < 1 then
			if frame.args.example then args[1] = frame.args.example else return '<strong class="error">Error in [[Template:Reply to]]: Username not given.</strong>' end
		end
		local isfirst = true
		local outStr = ''
		for i = 1, maxArg do
			if args[i] then
				if isfirst then
					outStr = string.format(
						'<span class="template-ping">%s[[User:%s|%s]]',
						args['prefix'] or '@',
						args[i],
						(args['label1'] or args['label']) or args[i]
					)
 					isfirst = false
				else
					if ( (usernames > 2) or ((usernames == 2) and (args['c'] == '')) ) then outStr = outStr..',' end
					if i == maxArg then outStr = outStr..' '..(args['c'] or 'and') end
					outStr = string.format(
						'%s [[User:%s|%s]]',
						outStr,
						args[i],
						args['label'..tostring(i)] or args[i]
					)
				end
			end
		end
		outStr = outStr..(args['p'] or ':')..'</span>'
		return outStr
	end
end

return p