Mô đun:UserLinks/shared

-- This module stores functions that are shared between Mô đun:UserLinks
-- and Mô đun:UserLinks/extra.

-- Load data and define often-used variables
local cfg = mw.loadData('Mô đun:UserLinks/config')
local namespaces = mw.site.namespaces

-- Lazily initialise modules that we may or may not need
local mCategoryHandler

-- Define namespaces for which links need to be escaped with the colon trick.
-- See w:en:Help:Colon trick.
local colonNamespaces = {
[6] = true, -- Tập tin
[14] = true, -- Thể loại
}

local p = {}

function p.maybeLoadModule(s)
-- Attempts to load the module s. If it succeeds, returns the module;
-- otherwise, returns false.
local success, mdl = pcall(require, s)
if success then
return mdl
else
return false
end
end

function p.raiseError(message, section, level)
-- Raises an error using the Lua error function. The error message is
-- designed to be caught with pcall and then passed to p.makeWikitextError.
-- The section, if specified, is the section name on a help page that gives
-- help to users about that particular error.
if section then
message = message .. '|' .. section
end
if not level or level == 0 then
level = 0
else
level = level + 1
end
error(message, level)
end

local localBlacklist = {
'/[sS]andbox$', -- Don't categorise sandboxes
'/[tT]est ?cases$', -- Don't categorise test case pages
}

local function currentTitleMatchesLocalBlacklist()
-- Return true if the current title matches any of the patterns in the
-- local blacklist table. Otherwise return false.
local title = mw.title.getCurrentTitle().prefixedText
for i, pattern in ipairs(localBlacklist) do
if title:find(pattern) then
return true
end
end
return false
end

function p.makeWikitextError(encodedMessage, demo)
local errorMessage, section = mw.ustring.match(encodedMessage, '^(.-)|(.)$')
errorMessage = errorMessage or encodedMessage

-- If not a demo, get the error category link and pass it through
-- Mô đun:Category handler's blacklist.
local category
if not demo then
category = string.format(
'%s:%s',
namespaces[14].name,
p.message('error-config-category')
)
mCategoryHandler = p.maybeLoadModule('Mô đun:Category handler')
if mCategoryHandler then
-- Categorise all namespaces, but not blacklisted pages.
category = mCategoryHandler.main{all = category}
end
if category and currentTitleMatchesLocalBlacklist() then
category = nil
end
end
category = category or

-- Format the error message and the section link.
local formattedError
if section then
formattedError = p.message(
'error-config-message-help',
errorMessage,
section
)
else
formattedError = p.message(
'error-config-message-nohelp',
errorMessage
)
end

-- Return the error message and the category inside html error tags.
return string.format(
'%s%s',
formattedError,
category
)
end

local function formatPage(interwiki, namespace, page)
-- Formats an interwiki, a namespace and a page into a wikilink-ready
-- string. The interwiki and namespace are optional. If a namespace is
-- specified, it should be a valid key to mw.site.namespaces. The page
-- parameter is required.
local ret = {}
interwiki = interwiki or
if interwiki ~= or colonNamespaces[namespace] then
ret[ret + 1] = ':'
end
ret[ret + 1] = interwiki
if interwiki ~= then
ret[ret + 1] = ':'
end
if namespace then
local nsTable = namespaces[namespace]
if not nsTable then
error('"' .. tostring(namespace) .. '" is not a valid namespace key', 2)
end
ret[ret + 1] = nsTable.name
if namespace ~= 0 then
ret[ret + 1] = ':'
end
end
ret[ret + 1] = page
return table.concat(ret)
end

local function formatDisplay(s)
-- Replaces spaces in a string with "&nbsp;" to make sure they don't wrap.
-- Don't replace anything if we are substing, as we generally don't want
-- to use "&nbsp;" in that case.
if mw.isSubsting() then
return s
else
return s:gsub(' ', '&nbsp;')
end
end

function p.mainWikiLink(interwiki, namespace, page, display, shouldFormat)
-- Creates a wikilink. The interwiki, namespace and display parameters are
-- optional. If a namespace parameter is specified it must be a valid key
-- to mw.site.namespaces.
local formattedPage = formatPage(interwiki, namespace, page)
if display then
display = shouldFormat == true and formatDisplay(display) or display
return string.format('%s', formattedPage, display)
else
return string.format('%s', formattedPage)
end
end

function p.makeWikilink(interwiki, namespace, page, display)
return p.mainWikiLink(interwiki, namespace, page, display, true)
end

local function formatUrlLink(url, display)
-- Formats a URL link with an optional display parameter.
if display then
display = formatDisplay(display)
return string.format('[%s %s]', url, display)
else
return string.format('[%s]', url)
end
end

function p.makeUrlLink(s, display)
-- Makes a URL link with an optional display parameter. The first input
-- may be any valid input to mw.uri.new.
local url = mw.uri.new(s)
url = tostring(url)
return formatUrlLink(url, display)
end

function p.makeFullUrlLink(interwiki, namespace, page, query, display)
-- Makes a link to the full URL of a page. The interwiki, namespace, query
-- and display parameters are optional. If a namespace parameter is
-- specified it must be a valid key to mw.site.namespaces. The query
-- parameter can be a string or a table as specified in the mw.uri library.
local formattedPage = formatPage(interwiki, namespace, page)
local url = mw.uri.fullUrl(formattedPage, query)
url = tostring(url)
return formatUrlLink(url, display)
end

function p.message(key, ...)
-- Returns the message with the given key from Mô đun:UserLinks/config.
-- Extra parameters are substituted in the message for keys $1, $2, $3, etc.
local msg = cfg[key]
if not msg then
p.raiseError(
'No message found with key "' .. tostring(key) .. '"',
'No message found',
2
)
end
local noArgs = select('', ...)
if noArgs < 1 then
return msg
else
local msg = mw.message.newRawMessage(msg, ...)
return msg:plain()
end
end

function p.makeWikilinkRaw(interwiki, namespace, page, display)
return p.mainWikiLink(interwiki, namespace, page, display, false)
end

return p