Diff: Module:Format link
Comparing revision #1 (2022-10-04 13:37:11) with revision #2 (2023-02-04 10:26:37).
| Old | New |
|---|---|
-------------------------------------------------------------------------------- |
-------------------------------------------------------------------------------- |
-- Format link |
-- Format link |
-- |
-- |
-- Makes a wikilink from the given link and display values. Links are escaped |
-- Makes a wikilink from the given link and display values. Links are escaped |
-- with colons if necessary, and links to sections are detected and displayed |
-- with colons if necessary, and links to sections are detected and displayed |
-- with " § " as a separator rather than the standard MediaWiki "#". Used in |
-- with " § " as a separator rather than the standard MediaWiki "#". Used in |
-- the {{format link}} template. |
-- the {{format link}} template. |
-------------------------------------------------------------------------------- |
-------------------------------------------------------------------------------- |
local libraryUtil = require('libraryUtil') |
local libraryUtil = require('libraryUtil') |
local checkType = libraryUtil.checkType |
local checkType = libraryUtil.checkType |
local checkTypeForNamedArg = libraryUtil.checkTypeForNamedArg |
local checkTypeForNamedArg = libraryUtil.checkTypeForNamedArg |
local mArguments -- lazily initialise [[Module:Arguments]] |
local mArguments -- lazily initialise [[Module:Arguments]] |
local mError -- lazily initialise [[Module:Error]] |
local mError -- lazily initialise [[Module:Error]] |
local yesno -- lazily initialise [[Module:Yesno]] |
local yesno -- lazily initialise [[Module:Yesno]] |
local p = {} |
local p = {} |
-------------------------------------------------------------------------------- |
-------------------------------------------------------------------------------- |
-- Helper functions |
-- Helper functions |
-------------------------------------------------------------------------------- |
-------------------------------------------------------------------------------- |
local function getArgs(frame) |
local function getArgs(frame) |
-- Fetches the arguments from the parent frame. Whitespace is trimmed and |
-- Fetches the arguments from the parent frame. Whitespace is trimmed and |
-- blanks are removed. |
-- blanks are removed. |
mArguments = require('Module:Arguments') |
mArguments = require('Module:Arguments') |
return mArguments.getArgs(frame, {parentOnly = true}) |
return mArguments.getArgs(frame, {parentOnly = true}) |
end |
end |
local function removeInitialColon(s) |
local function removeInitialColon(s) |
-- Removes the initial colon from a string, if present. |
-- Removes the initial colon from a string, if present. |
return s:match('^:?(.*)') |
return s:match('^:?(.*)') |
end |
end |
local function maybeItalicize(s, shouldItalicize) |
local function maybeItalicize(s, shouldItalicize) |
-- Italicize s if s is a string and the shouldItalicize parameter is true. |
-- Italicize s if s is a string and the shouldItalicize parameter is true. |
if s and shouldItalicize then |
if s and shouldItalicize then |
return '<i>' .. s .. '</i>' |
return '<i>' .. s .. '</i>' |
else |
else |
return s |
return s |
end |
end |
end |
end |
local function parseLink(link) |
local function parseLink(link) |
-- Parse a link and return a table with the link's components. |
-- Parse a link and return a table with the link's components. |
-- These components are: |
-- These components are: |
-- - link: the link, stripped of any initial colon (always present) |
-- - link: the link, stripped of any initial colon (always present) |
-- - page: the page name (always present) |
-- - page: the page name (always present) |
-- - section: the page name (may be nil) |
-- - section: the page name (may be nil) |
-- - display: the display text, if manually entered after a pipe (may be nil) |
-- - display: the display text, if manually entered after a pipe (may be nil) |
link = removeInitialColon(link) |
link = removeInitialColon(link) |
-- Find whether a faux display value has been added with the {{!}} magic |
-- Find whether a faux display value has been added with the {{!}} magic |
-- word. |
-- word. |
local prePipe, display = link:match('^(.-)|(.*)$') |
local prePipe, display = link:match('^(.-)|(.*)$') |
link = prePipe or link |
link = prePipe or link |
-- Find the page, if it exists. |
-- Find the page, if it exists. |
-- For links like [[#Bar]], the page will be nil. |
-- For links like [[#Bar]], the page will be nil. |
local preHash, postHash = link:match('^(.-)#(.*)$') |
local preHash, postHash = link:match('^(.-)#(.*)$') |
local page |
local page |
if not preHash then |
if not preHash then |
-- We have a link like [[Foo]]. |
-- We have a link like [[Foo]]. |
page = link |
page = link |
elseif preHash ~= '' then |
elseif preHash ~= '' then |
-- We have a link like [[Foo#Bar]]. |
-- We have a link like [[Foo#Bar]]. |
page = preHash |
page = preHash |
end |
end |
-- Find the section, if it exists. |
-- Find the section, if it exists. |
local section |
local section |
if postHash and postHash ~= '' then |
if postHash and postHash ~= '' then |
section = postHash |
section = postHash |
end |
end |
return { |
return { |
link = link, |
link = link, |
page = page, |
page = page, |
section = section, |
section = section, |
display = display, |
display = display, |
} |
} |
end |
end |
local function formatDisplay(parsed, options) |
local function formatDisplay(parsed, options) |
-- Formats a display string based on a parsed link table (matching the |
-- Formats a display string based on a parsed link table (matching the |
-- output of parseLink) and an options table (matching the input options for |
-- output of parseLink) and an options table (matching the input options for |
-- _formatLink). |
-- _formatLink). |
local page = maybeItalicize(parsed.page, options.italicizePage) |
local page = maybeItalicize(parsed.page, options.italicizePage) |
local section = maybeItalicize(parsed.section, options.italicizeSection) |
local section = maybeItalicize(parsed.section, options.italicizeSection) |
if (not section) then |
if (not section) then |
return page |
return page |
elseif (not page) then |
elseif (not page) then |
return mw.ustring.format('§ %s', section) |
return mw.ustring.format('§ %s', section) |
else |
else |
return mw.ustring.format('%s § %s', page, section) |
return mw.ustring.format('%s § %s', page, section) |
end |
end |
end |
end |
local function missingArgError(target) |
local function missingArgError(target) |
mError = require('Module:Error') |
mError = require('Module:Error') |
return mError.error{message = |
return mError.error{message = |
'Error: no link or target specified! ([[' .. target .. '#Errors|help]])' |
'Error: no link or target specified! ([[' .. target .. '#Errors|help]])' |
} |
} |
end |
end |
-------------------------------------------------------------------------------- |
-------------------------------------------------------------------------------- |
-- Main functions |
-- Main functions |
-------------------------------------------------------------------------------- |
-------------------------------------------------------------------------------- |
function p.formatLink(frame) |
function p.formatLink(frame) |
-- The formatLink export function, for use in templates. |
-- The formatLink export function, for use in templates. |
yesno = require('Module:Yesno') |
yesno = require('Module:Yesno') |
local args = getArgs(frame) |
local args = getArgs(frame) |
local link = args[1] or args.link |
local link = args[1] or args.link |
local target = args[3] or args.target |
local target = args[3] or args.target |
if not (link or target) then |
if not (link or target) then |
return missingArgError('Template:Format link') |
return missingArgError('Template:Format link') |
end |
end |
return p._formatLink{ |
return p._formatLink{ |
link = link, |
link = link, |
display = args[2] or args.display, |
display = args[2] or args.display, |
target = target, |
target = target, |
italicizePage = yesno(args.italicizepage), |
italicizePage = yesno(args.italicizepage), |
italicizeSection = yesno(args.italicizesection), |
italicizeSection = yesno(args.italicizesection), |
categorizeMissing = args.categorizemissing |
categorizeMissing = args.categorizemissing |
} |
} |
end |
end |
function p._formatLink(options) |
function p._formatLink(options) |
-- The formatLink export function, for use in modules. |
-- The formatLink export function, for use in modules. |
checkType('_formatLink', 1, options, 'table') |
checkType('_formatLink', 1, options, 'table') |
local function check(key, expectedType) --for brevity |
local function check(key, expectedType) --for brevity |
checkTypeForNamedArg( |
checkTypeForNamedArg( |
'_formatLink', key, options[key], expectedType or 'string', true |
'_formatLink', key, options[key], expectedType or 'string', true |
) |
) |
end |
end |
check('link') |
check('link') |
check('display') |
check('display') |
check('target') |
check('target') |
check('italicizePage', 'boolean') |
check('italicizePage', 'boolean') |
check('italicizeSection', 'boolean') |
check('italicizeSection', 'boolean') |
check('categorizeMissing') |
check('categorizeMissing') |
-- Normalize link and target and check that at least one is present |
-- Normalize link and target and check that at least one is present |
if options.link == '' then options.link = nil end |
if options.link == '' then options.link = nil end |
if options.target == '' then options.target = nil end |
if options.target == '' then options.target = nil end |
if not (options.link or options.target) then |
if not (options.link or options.target) then |
return missingArgError('Module:Format link') |
return missingArgError('Module:Format link') |
end |
end |
local parsed = parseLink(options.link) |
local parsed = parseLink(options.link) |
local display = options.display or parsed.display |
local display = options.display or parsed.display |
local catMissing = options.categorizeMissing |
local catMissing = options.categorizeMissing |
local category = '' |
local category = '' |
-- Find the display text |
-- Find the display text |
if not display then display = formatDisplay(parsed, options) end |
if not display then display = formatDisplay(parsed, options) end |
-- Handle the target option if present |
-- Handle the target option if present |
if options.target then |
if options.target then |
local parsedTarget = parseLink(options.target) |
local parsedTarget = parseLink(options.target) |
parsed.link = parsedTarget.link |
parsed.link = parsedTarget.link |
parsed.page = parsedTarget.page |
parsed.page = parsedTarget.page |
end |
end |
-- Test if page exists if a diagnostic category is specified |
-- Test if page exists if a diagnostic category is specified |
if catMissing and (mw.ustring.len(catMissing) > 0) then |
if catMissing and (mw.ustring.len(catMissing) > 0) then |
local title = nil |
local title = nil |
if parsed.page then title = mw.title.new(parsed.page) end |
if parsed.page then title = mw.title.new(parsed.page) end |
if title and (not title.isExternal) then |
if title and (not title.isExternal) then |
local success, exists = pcall(function() return title.exists end) |
local success, exists = pcall(function() return title.exists end) |
if success and not exists then |
if success and not exists then |
category = mw.ustring.format('[[Category:%s]]', catMissing) |
category = mw.ustring.format('[[Category:%s]]', catMissing) |
end |
end |
end |
end |
end |
end |
-- Format the result as a link |
-- Format the result as a link |
if parsed.link == display then |
if parsed.link == display then |
return mw.ustring.format('[[:%s]]%s', parsed.link, category) |
return mw.ustring.format('[[:%s]]%s', parsed.link, category) |
else |
else |
return mw.ustring.format('[[:%s|%s]]%s', parsed.link, display, category) |
return mw.ustring.format('[[:%s|%s]]%s', parsed.link, display, category) |
end |
end |
end |
end |
-------------------------------------------------------------------------------- |
-------------------------------------------------------------------------------- |
-- Derived convenience functions |
-- Derived convenience functions |
-------------------------------------------------------------------------------- |
-------------------------------------------------------------------------------- |
function p.formatPages(options, pages) |
function p.formatPages(options, pages) |
-- Formats an array of pages using formatLink and the given options table, |
-- Formats an array of pages using formatLink and the given options table, |
-- and returns it as an array. Nil values are not allowed. |
-- and returns it as an array. Nil values are not allowed. |
local ret = {} |
local ret = {} |
for i, page in ipairs(pages) do |
for i, page in ipairs(pages) do |
ret[i] = p._formatLink{ |
ret[i] = p._formatLink{ |
link = page, |
link = page, |
categorizeMissing = options.categorizeMissing, |
categorizeMissing = options.categorizeMissing, |
italicizePage = options.italicizePage, |
italicizePage = options.italicizePage, |
italicizeSection = options.italicizeSection |
italicizeSection = options.italicizeSection |
} |
} |
end |
end |
return ret |
return ret |
end |
end |
return p |
return p |