Module:UserLinks: Difference between revisions

From the Croc Wiki, the Croc encyclopedia
Jump to navigationJump to search
Complete rewrite of the module, updated from sandbox. Now supports adding new link functions on Module:UserLinks/extra, and is configurable at Module:UserLinks/config.
(update count link per protected edit request by User:Frietjes)
(Complete rewrite of the module, updated from sandbox. Now supports adding new link functions on Module:UserLinks/extra, and is configurable at Module:UserLinks/config.)
Line 1:
--------------------------------------------------------------------------------
local ToolbarBuilder = require('Module:Toolbar')
-- UserLinks --
local interwikiTable = mw.loadData("Module:InterwikiTable")
-- This module creates a list of links about a given user. It can be used on --
-- its own or from a template. See the /doc page for more documentation. --
--------------------------------------------------------------------------------
 
-- Require necessary modules
local u = {} -- Table for user-data helper strings.
local yesno = require('Module:Yesno')
local trackingCategories = {} -- Table for storing the tracking categories.
local demo
 
-- Lazily initialise modules that we might or might not need
-- Define a custom error message for this module.
local mExtra -- [[Module:UserLinks/extra]]
local function err(msg, section)
local mArguments -- [[Module:Arguments]]
local help
local mToolbar -- [[Module:Toolbar]]
if section then
local mCategoryHandler -- [[Module:Category handler]]
help = ' ([[Template:User-multi#' .. section .. '|help]])'
local mTableTools -- [[Module:TableTools]]
else
local interwikiTable -- [[Module:InterwikiTable]], loaded with mw.loadData
help = ''
end
local cat
if demo == 'yes' then
cat = ''
else
cat = '[[Category:UserLinks transclusions with errors]]'
end
return '<span class="error">[[Template:User-multi|User-multi]] error: ' .. msg
.. help .. '.</span>' .. cat
end
 
-- Load shared helper functions
----------------------------------------------------------------------------------------------
local mShared = require('Module:UserLinks/shared')
-- To add more link types, write a function that produces an individual link, and put --
local raiseError = mShared.raiseError
-- it at the bottom of the list below. Then, add a link code for your function to the --
local maybeLoadModule = mShared.maybeLoadModule
-- "linktypes" table. Try and make the code three letters or less. There are a number --
local makeWikitextError = mShared.makeWikitextError
-- of helper strings available for writing the functions: --
local makeWikilink = mShared.makeWikilink
-- --
local makeUrlLink = mShared.makeUrlLink
-- u.username The plain username. If the username is not present then the --
local makeFullUrlLink = mShared.makeFullUrlLink
-- module returns an error. --
local message = mShared.message
-- u.usernameHtml The username html-encoded. Spaces are encoded with plus signs. --
-- u.project The project name. Nil if not specified. --
-- u.lang The language code. Nil if not specified. --
-- u.interwiki The interwiki prefix, consisting of the project and language --
-- values, separated by colons, e.g. ":wikt:es:". If no project --
-- or language values are found, this is the blank string, "". --
-- u.projectCode If a valid project is specified, this is the code for that --
-- project in [[Module:InterwikiTable]]. Otherwise this is nil. --
-- u.projectLong The long project name, e.g. "wikipedia" or "wikibooks". If --
-- not specified the default is "wikipedia". --
-- u.toolLang The language code for use with toolserver or labs tools. The --
-- default is "en". --
-- --
-- If you want more helper strings, you can define them in the generateUserDataStrings --
-- function below. --
----------------------------------------------------------------------------------------------
 
local p = {}
----------------------------------------------------------------------------------------------
-- LINK FUNCTIONS START --
----------------------------------------------------------------------------------------------
 
--------------------------------------------------------------------------------
local function makeUserLink()
-- Link table
return '[[' .. u.interwiki .. 'User:' .. u.username .. '|' .. u.username .. ']]'
--------------------------------------------------------------------------------
end
 
local function makeTalkLinkp.getLinks(snippets)
--[=[
return '[[' .. u.interwiki .. 'User talk:' .. u.username .. '|talk]]'
-- Get a table of links that can be indexed with link codes. The table
end
-- returned is blank, but links are added to it on demand when it is
-- indexed. This is made possible by the metatable and by the various link
-- functions, some of which are defined here, and some of which are defined
-- at [[Module:UserLinks/extra]].
--]=]
local links, linkFunctions = {}, {}
 
----------------------------------------------------------------------------
local function makeContribsLink()
-- Link functions
return '[[' .. u.interwiki .. 'Special:Contributions/' .. u.username .. '|contribs]]'
--
end
-- The following functions make the links from the link codes and the user
-- data snippets. New link functions should be added below the existing
-- functions.
--
-- For documentation on how to add new link functions, please see
-- [[Module:UserLinks#Adding new links]].
----------------------------------------------------------------------------
 
local function makeCountLinklinkFunctions.u(snippets)
-- User page
return '[//tools.wmflabs.org/supercount/index.php?user=' .. u.usernameHtml
return makeWikilink(
.. '&project=' .. u.toolLang .. '.' .. u.projectLong
snippets.interwiki,
.. ' count]'
2,
end
snippets.username,
snippets.username
)
end
 
local function makeMovesLinklinkFunctions.t(snippets)
-- User talk page
return '[[' .. u.interwiki .. 'Special:Log/move/' .. u.username .. '|page&nbsp;moves]]'
return makeWikilink(
end
snippets.interwiki,
3,
snippets.username,
message('display-talk')
)
end
 
local function makeLogsLinklinkFunctions.c(snippets)
-- Contributions
return '[[' .. u.interwiki .. 'Special:Log/' .. u.username .. '|logs]]'
return makeWikilink(
end
snippets.interwiki,
-1,
'Contributions/' .. snippets.username,
message('display-contributions')
)
end
 
local function makeBlockLogLinklinkFunctions.ct(snippets)
-- Edit count
local url = mw.uri.fullUrl(u.interwiki .. 'Special:Log/block', 'page=User:' .. u.usernameHtml)
return makeUrlLink(
return '[' .. tostring(url) .. ' block&nbsp;log]'
{
end
host = 'tools.wmflabs.org',
path = '/supercount/index.php',
query = {
user = snippets.username,
project = snippets.toolLang .. '.' .. snippets.projectLong
}
},
message('display-count')
)
end
 
local function makeBlocksLinklinkFunctions.m(snippets)
-- Page moves
return '[[' .. u.interwiki .. 'Special:Log/block/' .. u.username .. '|blocks]]'
return makeWikilink(
end
snippets.interwiki,
-1,
'Log/move/' .. snippets.username,
message('display-moves')
)
end
 
local function makeBlockUserLinklinkFunctions.l(snippets)
-- Logs
return '[[' .. u.interwiki .. 'Special:Block/' .. u.username .. '|block&nbsp;user]]'
return makeWikilink(
end
snippets.interwiki,
-1,
'Log/' .. snippets.username,
message('display-logs')
)
end
 
local function makeCentralAuthLinklinkFunctions.bl(snippets)
-- Block log
return '[[' .. u.interwiki .. 'Special:CentralAuth/' .. u.username .. '|central&nbsp;auth]]'
return makeFullUrlLink(
end
snippets.interwiki,
-1,
'Log/block',
{page = 'User:' .. snippets.username},
message('display-blocklog')
)
end
 
local function makeDeletedContribsLinklinkFunctions.bls(snippets)
-- Blocks
return '[[' .. u.interwiki .. 'Special:DeletedContributions/' .. u.username .. '|deleted&nbsp;contribs]]'
return makeWikilink(
end
snippets.interwiki,
-1,
'Log/block/' .. snippets.username,
message('display-blocks')
)
end
 
local function makeEmailLinklinkFunctions.bu(snippets)
-- Block user
return '[[' .. u.interwiki .. 'Special:Emailuser/' .. u.username .. '|email]]'
return makeWikilink(
end
snippets.interwiki,
-1,
'Block/' .. snippets.username,
message('display-blockuser')
)
end
 
local function makeEditSummariesLinklinkFunctions.ca(snippets)
-- Central auth
return '[http://tools.wmflabs.org/xtools/editsummary/index.php?name=' .. u.usernameHtml
return makeWikilink(
.. '&lang=' .. u.toolLang
snippets.interwiki,
.. '&wiki=' .. u.projectLong
-1,
.. ' edit&nbsp;summaries]'
'CentralAuth/' .. snippets.username,
end
message('display-centralauth')
)
end
 
local function makeDeletionsLinklinkFunctions.dc(snippets)
-- Deleted contribs
return '[[' .. u.interwiki .. 'Special:Log/delete/' .. u.username .. '|deletions]]'
return makeWikilink(
end
snippets.interwiki,
-1,
'DeletedContributions/' .. snippets.username,
message('display-deletedcontributions')
)
end
 
local function makeListUserLinklinkFunctions.e(snippets)
-- Email
local url = mw.uri.fullUrl(u.interwiki .. 'Special:ListUsers', 'limit=1&username=' .. u.usernameHtml)
return makeWikilink(
return '[' .. tostring(url) .. ' list&nbsp;user]'
snippets.interwiki,
end
-1,
'EmailUser/' .. snippets.username,
message('display-email')
)
end
 
local function makeSulLinklinkFunctions.es(snippets)
-- Edit summaries
return '[[sulutil:' .. u.username .. '|global&nbsp;contribs]]'
return makeUrlLink(
end
{
host = 'tools.wmflabs.org',
path = '/xtools/editsummary/index.php',
query = {
name = snippets.username,
lang = snippets.toolLang,
wiki = snippets.projectLong
}
},
message('display-editsummaries')
)
end
 
local function makeTargetLogsLinklinkFunctions.del(snippets)
-- Deletions
local url = mw.uri.fullUrl(u.interwiki .. 'Special:Log', 'page=User:' .. u.usernameHtml)
return makeWikilink(
return '[' .. tostring(url) .. ' target&nbsp;logs]'
snippets.interwiki,
end
-1,
'Log/delete/' .. snippets.username,
message('display-deletions')
)
end
 
local function makeEditFilterLogLinklinkFunctions.lu(snippets)
-- List user
local url = mw.uri.fullUrl(u.interwiki .. 'Special:AbuseLog', 'wpSearchUser=' .. u.usernameHtml)
return makeFullUrlLink(
return '[' .. tostring(url) .. ' edit&nbsp;filter&nbsp;log]'
snippets.interwiki,
end
-1,
'ListUsers',
{limit = 1, user = snippets.username},
message('display-listuser')
)
end
 
local function makeProtectionsLinklinkFunctions.sul(snippets)
-- SUL
return '[[' .. u.interwiki .. 'Special:Log/protect/' .. u.username .. '|protections]]'
return makeWikilink(
end
nil,
nil,
'sulutil:' .. snippets.username,
message('display-sul')
)
end
 
local function makeRightsLinklinkFunctions.tl(snippets)
-- Target logs
return '[[' .. u.interwiki .. 'Special:Log/rights/' .. u.username .. '|rights]]'
return makeFullUrlLink(
end
snippets.interwiki,
-1,
'Log',
{page = mw.site.namespaces[2].name .. ':' .. snippets.username},
message('display-targetlogs')
)
end
 
local function makeRenamesLinklinkFunctions.efl(snippets)
-- Edit filter log
return '[[' .. u.interwiki .. 'Special:Log/renameuser/' .. u.username .. '|renames]]'
return makeFullUrlLink(
end
snippets.interwiki,
-1,
'AbuseLog',
{wpSearchUser = snippets.username},
message('display-abuselog')
)
end
 
local function makeRfaLinklinkFunctions.pr(snippets)
-- Protections
if u.project or u.lang then
return makeWikilink(
table.insert( trackingCategories, '[[Category:UserLinks transclusions with unresolvable interwiki links]]' )
snippets.interwiki,
end
-1,
return '[[Special:PrefixIndex/Wikipedia:Requests for adminship/' .. u.username .. '|RfA]]'
'Log/protect/' .. snippets.username,
end
message('display-protections')
)
end
 
local function makeApiLinklinkFunctions.rl(snippets)
-- User rights
-- Find the full domain, as the API can't be accessed through the interwiki system.
return makeWikilink(
local fulldomain
snippets.interwiki,
local lang = u.lang or 'en'
-1,
if u.projectCode then
'Log/rights/' .. snippets.username,
local domain = interwikiTable[u.projectCode].domain
message('display-rights')
local takesLangPrefix = interwikiTable[u.projectCode].takes_lang_prefix
)
if not takesLangPrefix then
end
fulldomain = domain
else
fulldomain = lang .. '.' .. domain
end
else
fulldomain = lang .. '.wikipedia.org'
end
-- Return the API link
return '[//' .. fulldomain .. '/w/api.php?action=query&list=users&usprop=editcount&ususers=' .. u.usernameHtml .. ' api]'
end
 
local function makeUploadsLinklinkFunctions.ren(snippets)
-- Renames
return '[[' .. u.interwiki .. 'Special:ListFiles/' .. u.username .. '|uploads]]'
return makeWikilink(
end
snippets.interwiki,
-1,
'Log/renameuser/' .. snippets.username,
message('display-renames')
)
end
 
function linkFunctions.rfa(snippets)
----------------------------------------------------------------------------------------------
-- Requests for adminship
-- LINK FUNCTIONS END --
return makeWikilink(
-- To enable new link functions, add the code to the "linktypes" table directly below. --
nil,
----------------------------------------------------------------------------------------------
-1,
'PrefixIndex/' .. message('page-rfa') .. '/' .. snippets.username,
message('display-rfa')
)
end
 
function linkFunctions.api(snippets)
local linktypes = {
-- API user data
{'t' , makeTalkLink},
return makeUrlLink(
{'c' , makeContribsLink},
{
{'ct' , makeCountLink},
host = snippets.fullDomain,
{'m' , makeMovesLink},
path = '/w/api.php',
{'l' , makeLogsLink},
query = {
{'bl' , makeBlockLogLink},
action = 'query',
{'bls' , makeBlocksLink},
list = 'users',
{'bu' , makeBlockUserLink},
usprop = 'editcount',
{'ca' , makeCentralAuthLink},
ususers = snippets.username
{'dc' , makeDeletedContribsLink},
}
{'e' , makeEmailLink},
},
{'es' , makeEditSummariesLink},
message('display-api')
{'del' , makeDeletionsLink},
)
{'lu' , makeListUserLink},
end
{'sul' , makeSulLink},
{'tl' , makeTargetLogsLink},
{'efl' , makeEditFilterLogLink},
{'pr' , makeProtectionsLink},
{'rl' , makeRightsLink},
{'ren' , makeRenamesLink},
{'rfa' , makeRfaLink},
{'api' , makeApiLink},
{'up' , makeUploadsLink}
}
 
local function getLinklinkFunctions.up(linktypesnippets)
-- Uploads
local linkNumber
return makeWikilink(
for i, value in ipairs(linktypes) do
snippets.interwiki,
if value[1] == linktype then
-1,
linkNumber = i
'ListFiles/' .. snippets.username,
break
message('display-uploads')
end
)
end
end
if not linkNumber then
return err('"' .. linktype .. '" is not a valid link code', 'Not a valid link code')
----------------------------------------------------------------------------
end
-- End of link functions
local result = linktypes[linkNumber][2]()
----------------------------------------------------------------------------
if type(result) ~= 'string' then
 
return err(
-- Define the metatable that memoizes the link functions, and fetches link
'the function for code "' .. linktype .. '" did not return a string value',
-- functions from [[Module:UserLinks/extra]] if necessary.
'Function did not return a string value'
 
)
-- Lazily initialise the extraLinkFunctions table. We only want to load
end
-- [[Module:UserLinks/extra]] as necessary, so it has a low transclusion
return result
-- count.
end
local extraLinkFunctions
 
-- Define functions for shared code in the metatable.
local function makeToolbar(args)
local function validateCode(code)
local targs = {}
-- Checks whether code is a valid link code - i.e. checks that it is a
local numArgsExist = false
-- string and that it is not the blank string. Returns the code if
for k, v in pairs(args) do
-- the check passes, and nil if not.
if type(k) == 'number' then
if type(code) == 'string' and code ~= '' then
numArgsExist = true
return code
targs[k] = getLink(v)
else
end
return nil
end
end
targs.style = args.small and 'font-size: 90%;'
end
targs.separator = args.separator or 'dot'
 
local function getExtraLinkFunctions()
if numArgsExist == false then
-- Loads the table of extra link functions from the /extra module.
return nil -- Don't return a toolbar if no numeric arguments exist.
-- If there is a problem with loading it, return false. We use the
else
-- distinction between false and nil to record whether we have already
return ToolbarBuilder.main(targs)
-- tried to load it.
end
if extraLinkFunctions ~= nil then
return extraLinkFunctions
end
if mExtra == nil then
-- If loading the module fails, maybeLoadModule returns false.
-- Here we use the distinction between false and nil to record
-- whether we have already tried to load the /extra module.
mExtra = maybeLoadModule('Module:UserLinks/extra')
end
if type(mExtra) == 'table'
and type(mExtra.linkFunctions) == 'table'
then
extraLinkFunctions = mExtra.linkFunctions
else
extraLinkFunctions = false
end
return extraLinkFunctions
end
 
local function memoizeExtraLink(code, func)
local success, link = pcall(func, snippets)
if success and type(link) == 'string' then
links[code] = link
return link
end
return nil
end
 
-- Define the metatable.
setmetatable(links, {
__index = function (t, key)
local code = validateCode(key)
if not code then
raiseError(
message('error-malformedlinkcode'),
message('error-malformedlinkcode-section')
)
end
local linkFunction = linkFunctions[code]
local link
if linkFunction then
link = linkFunction(snippets)
links[code] = link
else
extraLinkFunctions = getExtraLinkFunctions()
if extraLinkFunctions then
local extraLinkFunction = extraLinkFunctions[code]
if type(extraLinkFunction) == 'function' then
link = memoizeExtraLink(code, extraLinkFunction)
end
end
end
if link then
return link
else
raiseError(
message('error-invalidlinkcode', code),
message('error-invalidlinkcode-section')
)
end
end,
__pairs = function ()
extraLinkFunctions = getExtraLinkFunctions()
if extraLinkFunctions then
for code, func in pairs(extraLinkFunctions) do
if validateCode(code) and type(func) == 'function' then
memoizeExtraLink(code, func)
end
end
end
-- Allow built-in functions to overwrite extra functions.
for code, func in pairs(linkFunctions) do
local link = func(snippets)
links[code] = link
end
return function (t, key)
return next(links, key)
end
end
})
return links
end
 
--------------------------------------------------------------------------------
-- This function finds whether a string is a valid interwiki project prefix.
-- User data snippets
-- If the string is valid, the function outputs two values: true, and the site code
--------------------------------------------------------------------------------
-- used in [[Module:InterwikiTable]]. If the string is valid, the function outputs
 
-- false and nil.
local function isKnownProjectp.getSnippets(prefixargs)
--[=[
for projectCode, projectVal in pairs(interwikiTable) do
-- This function gets user data snippets from the arguments, and from
for _, iwCode in ipairs(projectVal.iw_prefix) do
-- [[Module:InterwikiTable]]. The data is loaded as necessary and memoized
if iwCode == prefix then
-- in the snippets table for performance.
return true, projectCode
--
-- Snippets default to the blank string, '', so they can be used in
-- concatenation operations without coders having to worry about raising
-- errors. Because of this, the local functions snippetExists and
-- getSnippet have been written to aid people writing new snippets. These
-- functions treat the blank string as false. It is not necessary to return
-- the blank string from a snippet function, as nil and false values are
-- automatically converted into the blank string by the metatable.
--
-- If you add a new snippet, please document it at
-- [[Module:UserLinks#Adding new links]].
--]=]
local snippets, snippetFunctions = {}, {}
setmetatable(snippets, {
__index = function (t, key)
local snippetFunction = snippetFunctions[key]
if snippetFunction then
snippets[key] = snippetFunction() or ''
return snippets[key]
else
raiseError(
message('error-nosnippet', key),
message('error-nosnippet-section')
)
end
end
})
 
-- Define helper functions for writting the snippet functions.
local function snippetExists(key)
-- We have set the metatable up to make snippets default to '', so we
-- don't have to test for false or nil.
return snippets[key] ~= ''
end
 
local function getSnippet(key)
local ret = snippets[key]
if ret == '' then
return nil
else
return ret
end
end
 
-- Start snippet functions.
 
function snippetFunctions.username()
-- The username.
local username = args.user or args.User
return username or raiseError(
message('error-nousername'),
message('error-nousername-section')
)
end
 
function snippetFunctions.usernameHtml()
-- The username html-encoded. Spaces are encoded as pluses.
return mw.uri.encode(snippets.username)
end
 
function snippetFunctions.project()
-- The project name.
-- Also does the work for snippetFunctions.interwikiTableKey, and adds
-- the project value to snippets.lang if it is a valid language code.
local project = args.Project or args.project
if not project then
return nil
end
local projectValidated, interwikiTableKey = p.validateProjectCode(project)
if not projectValidated then
if mw.language.isKnownLanguageTag(project) then
if not snippetExists('lang') then
snippets.lang = project
end
else
raiseError(
message('error-invalidproject', project),
message('error-invalidproject-section')
)
end
end
snippets.interwikiTableKey = interwikiTableKey
return project
end
 
function snippetFunctions.interwikiTableKey()
-- The key for the project in Module:InterwikiTable.
-- Relies on snippetFunctions.project to do the real work.
local temp = snippets.project -- required; puts key in snippets table
return rawget(snippets, 'interwikiTableKey')
end
 
function snippetFunctions.toolProject()
-- The short project code for use with toolserver or labs. It is always
-- present, even if the "project" argument is absent. The default value
-- is the "snippet-project-default" message.
local project = getSnippet('project')
if not project then
return message('snippet-project-default')
else
return project
end
end
 
function snippetFunctions.projectLong()
-- The long form of the project name, e.g. "wikipedia" or "wikibooks".
local key = getSnippet('interwikiTableKey')
if not key then
return message('snippet-projectlong-default')
end
interwikiTable = interwikiTable or mw.loadData('Module:InterwikiTable')
local prefixes = interwikiTable[key].iw_prefix
-- Using prefixes[2] is a bit of a hack, but should find the long name
-- most of the time.
return prefixes[2] or prefixes[1]
end
 
function snippetFunctions.lang()
-- The language code.
local lang = args.lang or args.Lang
if not lang then
return nil
end
if mw.language.isKnownLanguageTag(lang) then
return lang
else
raiseError(
message('error-invalidlanguage', lang),
message('error-invalidlanguage-section')
)
end
end
 
function snippetFunctions.toolLang()
-- The language code for use with toolserver or labs tools. It is always
-- present, even if the "lang" argument is absent. The default value is
-- the "snippet-lang-default" message.
return getSnippet('lang') or message('snippet-lang-default')
end
 
function snippetFunctions.interwiki()
-- The interwiki prefix, consisting of the project and language values,
-- separated by colons, e.g. ":wikt:es:".
local project = getSnippet('project')
local lang = getSnippet('lang')
if not project and not lang then
return nil
end
local ret = {}
ret[#ret + 1] = project
ret[#ret + 1] = lang
return table.concat(ret, ':')
end
 
function snippetFunctions.fullDomain()
-- The full domain name of the site, e.g. www.mediawiki.org,
-- en.wikpedia.org, or ja.wikibooks.org.
local fullDomain
local lang = getSnippet('toolLang')
local key = getSnippet('interwikiTableKey')
if key then
interwikiTable = interwikiTable or mw.loadData('Module:InterwikiTable')
local domain = interwikiTable[key].domain
local takesLangPrefix = interwikiTable[key].takes_lang_prefix
if takesLangPrefix then
fullDomain = lang .. '.' .. domain
else
fullDomain = domain
end
else
fullDomain = lang .. '.wikipedia.org'
end
return fullDomain
end
 
-- End snippet functions. If you add a new snippet function, please
-- document it at [[Module:UserLinks#Adding new links]].
 
return snippets
end
 
function p.validateProjectCode(s)
-- Validates a project code, by seeing whether it is present in
-- [[Module:InterwikiTable]]. If it is present, returns the code and the
-- InterwikiTable key for the corresponding site. If not present,
-- returns nil for both.
interwikiTable = interwikiTable or mw.loadData('Module:InterwikiTable')
for key, t in pairs(interwikiTable) do
for i, prefix in ipairs(t.iw_prefix) do
if s == prefix then
return s, key
end
end
end
return falsenil, nil
end
 
--------------------------------------------------------------------------------
local function generateUserDataStrings(args)
-- Main functions
-- If the username is absent or blank, return an error and a tracking category.
--------------------------------------------------------------------------------
if args.user == '' or (not args.user and (not args.User or args.User == '')) then
return err('no username detected', 'No username detected')
else
u.username = args.user or args.User
end
-- Get other basic user data strings.
u.project = args.Project or args.project
u.lang = args.lang or args.Lang
if u.lang then
if mw.language.isKnownLanguageTag(u.lang) then
table.insert(trackingCategories, '[[Category:UserLinks transclusions with language parameters]]')
else
return err('"' .. u.lang .. '" is not a valid language code', 'Not a valid language code')
end
end
-- Process the project value if it is present.
if u.project then
table.insert( trackingCategories, '[[Category:UserLinks transclusions with project parameters]]' )
-- If u.project is a known project, we only need to get the project code. If the project
-- isn't known, first check whether it is a valid language code, and if not then see if it's
-- an interwiki code separated by colons, e.g. "wikt:es".
local uprojectIsKnownProject, uprojectProjectCode = isKnownProject(u.project)
if uprojectIsKnownProject then
u.projectCode = uprojectProjectCode
else
if mw.language.isKnownLanguageTag(u.project) then
u.lang = u.project
u.project = nil
else
local pref1, pref2 = mw.ustring.match( u.project, '^(%w+):(%w+)$' )
if pref1 and pref2 then
local pref1IsKnownProject, pref1ProjectCode = isKnownProject(pref1)
local pref2IsKnownProject, pref2ProjectCode = isKnownProject(pref2)
if pref1IsKnownProject
and mw.language.isKnownLanguageTag(pref2)
and interwikiTable[pref1ProjectCode].takes_lang_prefix then
u.project = pref1
u.lang = pref2
u.projectCode = pref1ProjectCode
table.insert(
trackingCategories,
'[[Category:UserLinks transclusions with project parameters containing language codes]]'
)
elseif pref2IsKnownProject
and mw.language.isKnownLanguageTag(pref1)
and interwikiTable[pref2ProjectCode].takes_lang_prefix then
u.project = pref2
u.lang = pref1
u.projectCode = pref2ProjectCode
table.insert(
trackingCategories,
'[[Category:UserLinks transclusions with project parameters containing language codes]]'
)
else
return err(
'"' .. u.project .. '" is not a valid interwiki prefix',
'Not a valid interwiki prefix'
)
end
else
return err(
'"' .. u.project .. '" is not a valid interwiki prefix',
'Not a valid interwiki prefix'
)
end
end
end
end
-- Generate the interwiki prefix. This includes colons.
if u.project or u.lang then
u.interwiki = ''
if u.project then
u.interwiki = u.interwiki .. ':' .. u.project
end
if u.lang then
u.interwiki = u.interwiki .. ':' .. u.lang
end
u.interwiki = u.interwiki .. ':'
else
u.interwiki = ''
end
 
local function makeInvokeFunction(funcName)
-- Generate the other helper strings.
-- Makes a function that can be accessed from #invoke. This is only required
u.usernameHtml = mw.uri.encode(u.username) -- Html-encoded username. Spaces are encoded as pluses.
-- for functions that need to access arguments.
if u.project then
return function (frame)
local prefixes = interwikiTable[u.projectCode].iw_prefix
mArguments = require('Module:Arguments')
u.projectLong = prefixes[2] or prefixes[1] -- A bit of a hack, but should find the long prefix name most of the time.
local args = mArguments.getArgs(frame)
else
return p[funcName](args)
u.projectLong = 'wikipedia'
end
u.toolLang = u.lang or 'en' -- set the default language for tools on the toolserver or labs.
end
 
p.main = makeInvokeFunction('_main')
local function generateTrackingCategories()
 
if demo == 'yes' then
function p._main(args)
return ''
-- The main function. This is the one called from [[Template:User-multi]],
else
-- via p.main.
return table.concat(trackingCategories)
local options = p.getOptions(args)
end
local snippets = p.getSnippets(args)
local codes = p.getCodes(args)
local links = p.getLinks(snippets)
-- Overload the built-in Lua error function to generate wikitext errors
-- meant for end users to see. This makes things harder to debug when
-- real errors occur, but it is the only realistic way to show wikitext
-- errors and and still have sane code when using metatables, etc.
local success, result = pcall(p.export, codes, links, options)
if success then
return result
else
return makeWikitextError(result, options.isDemo)
end
end
 
function p.getOptions(args)
-- This function generates a table of all available link types, with their previews.
-- Gets the options from the args table, so that we don't have to pass
-- It is used in the module documentation.
-- around the whole args table all the time.
local function getLinkTable(args)
local options = {}
demo = args.demo -- Set the demo variable.
options.isDemo = yesno(args.demo) or false
-- Generate the user data strings and return any errors.
options.toolbarStyle = yesno(args.small) and 'font-size: 90%;' or nil
local dataStringError = generateUserDataStrings(args)
options.sup = yesno(args.sup, true)
if dataStringError then
options.separator = args.separator
return dataStringError
options.span = args.span
end
return options
-- Build a table of all of the links.
local result = '<table class="wikitable plainlinks sortable">'
.. '\n<tr><th>Code</th><th>Preview</th></tr>'
for i, value in ipairs(linktypes) do
local code = value[1]
result = result .. "\n<tr><td>'''" .. code .. "'''</td><td>" .. getLink(code) .. '</td></tr>'
end
result = result .. '\n</table>'
return result
end
 
local function getSingleLinkp.getCodes(args)
-- Gets the link codes from the arguments. The codes aren't validated
demo = args.demo -- Set the demo variable.
-- at this point.
-- Generate the user data strings and return any errors.
mTableTools = maybeLoadModule('Module:TableTools')
local dataStringError = generateUserDataStrings(args)
local codes
if dataStringError then
if mTableTools then
return dataStringError
codes = mTableTools.compressSparseArray(args)
end
else
codes = {}
local linktype = args[1]
for i, code in ipairs(args) do
if not linktype then
codes[i] = code
return err('no link type specified')
end
end
local result = getLink(linktype)
return codes
result = result .. generateTrackingCategories()
return result
end
 
local function getLinksp.export(argscodes, links, options)
demo = args.demo -- SetMake the demouser variablelink.
local userLink = links.u
-- Generate the user data strings and return any errors.
 
local dataStringError = generateUserDataStrings(args)
-- If we weren't passed any link codes, just return the user link.
if dataStringError then
if #codes < 1 then
return dataStringError
return userLink
end
end
 
-- Build the template output.
local result = makeToolbar(args) -- GetMake the toolbar contents.
mToolbar = require('Module:Toolbar')
if result then
local toolbarArgs = {}
if args.sup then
for i, code in ipairs(codes) do
result = '<sup>' .. result .. '</sup>'
local link = links[code]
end
toolbarArgs[#toolbarArgs + 1] = link
result = '&nbsp;' .. result
end
else
toolbarArgs.style = options.toolbarStyle
result = '' -- If there are no links specified, don't return the toolbar at all.
toolbarArgs.separator = options.separator or 'dot'
end
toolbarArgs.span = options.span
result = '<span>' .. makeUserLink() .. result .. '</span>'
local toolbar = mToolbar.main(toolbarArgs)
result = result .. generateTrackingCategories()
 
-- Apply the sup option and return the result.
if options.sup then
toolbar = '<sup>' .. toolbar .. '</sup>'
end
return userLink .. '&nbsp;' .. toolbar
end
 
--------------------------------------------------------------------------------
local function getExampleLinks(args)
-- Single link function
-- This function enables example output without having to specify any
--------------------------------------------------------------------------------
-- parameters to #invoke.
 
args.demo = 'yes'
p.single = makeInvokeFunction('_single')
args.user = 'Example'
 
args.User = nil
function return getLinksp._single(args)
-- Fetches a single link from the link table.
local options = p.getOptions(args)
local snippets = p.getSnippets(args)
local links = p.getLinks(snippets)
local code = args[1]
local success, link = pcall(p.exportSingle, links, code)
if success then
return link
else
return makeWikitextError(link, options.isDemo)
end
end
 
local function makeWrapperp.exportSingle(funclinks, code)
-- If any errors occur, they will probably occur here. This function
return function (frame)
-- exists purely so that all the errors that will occur in p._single can
-- If called via #invoke, use the args passed into the invoking template.
-- be handled using a single pcall.
-- Otherwise, for testing purposes, assume args are being passed directly in.
if not code then
local origArgs
raiseError(
if frame == mw.getCurrentFrame() then
message('error-nolinkcode'),
origArgs = frame:getParent().args
message('error-nolinkcode-section')
for k, v in pairs(frame.args) do
)
origArgs = frame.args
end
break
return links[code]
end
else
origArgs = frame
end
-- Strip whitespace, and treat blank arguments as nil.
-- 'user', 'User', and 'separator' have different behaviour depending on
-- whether they are blank or nil, so keep them as they are.
local args = {}
for k, v in pairs(origArgs) do
v = mw.text.trim(v)
if v ~= '' or k == 'user' or k == 'User' or k == 'separator' then
args[k] = v
end
end
return func(args)
end
end
 
--------------------------------------------------------------------------------
return {
-- Link table
main = makeWrapper(getLinks),
--------------------------------------------------------------------------------
single = makeWrapper(getSingleLink),
 
linktable = makeWrapper(getLinkTable),
function p.linktable()
example = makeWrapper(getExampleLinks)
-- Returns a wikitext table of link codes, with an example link for each
}
-- one. This function doesn't take any arguments, so it can be accessed
-- directly from wiki pages without using makeInvokeFunction.
local args = {user = 'Example'}
local snippets = p.getSnippets(args)
local links = p.getLinks(snippets)
 
-- Assemble the codes and links in order
local firstCodes = {'u', 't', 'c'}
local firstLinks, firstCodesKeys = {}, {}
for i, code in ipairs(firstCodes) do
firstCodesKeys[code] = true
firstLinks[#firstLinks + 1] = {code, links[code]}
end
local secondLinks = {}
for code, link in pairs(links) do
if not firstCodesKeys[code] then
secondLinks[#secondLinks + 1] = {code, link}
end
end
table.sort(secondLinks, function(t1, t2)
return t1[1] < t2[1]
end)
local links = {}
for i, t in ipairs(firstLinks) do
links[#links + 1] = t
end
for i, t in ipairs(secondLinks) do
links[#links + 1] = t
end
 
-- Output the code table in table format
local ret = {}
ret[#ret + 1] = '{| class="wikitable plainlinks sortable"'
ret[#ret + 1] = '|-'
ret[#ret + 1] = '! ' .. message('linktable-codeheader')
ret[#ret + 1] = '! ' .. message('linktable-previewheader')
for i, t in ipairs(links) do
local code = t[1]
local link = t[2]
ret[#ret + 1] = '|-'
ret[#ret + 1] = "| '''" .. code .. "'''"
ret[#ret + 1] = '| ' .. link
end
ret[#ret + 1] = '|}'
return table.concat(ret, '\n')
end
 
return p
Cookies help us deliver our services. By using our services, you agree to our use of cookies.

Navigation menu