Difference between revisions of "Module:Format link"
wiki_crypto>Nihiltres (An extra layer of nil check) |
m (1 revision imported) |
||
(2 intermediate revisions by 2 users not shown) | |||
Line 11: | Line 11: | ||
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 yesno -- lazily initialise [[Module:Yesno]] | local yesno -- lazily initialise [[Module:Yesno]] | ||
Line 29: | Line 30: | ||
-- 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. | ||
if s and shouldItalicize then | if s and shouldItalicize then | ||
return | return '<i>' .. s .. '</i>' | ||
else | else | ||
return s | return s | ||
Line 82: | Line 78: | ||
section = section, | section = section, | ||
display = display, | display = display, | ||
} | |||
end | |||
local function formatDisplay(parsed, options) | |||
-- Formats a display string based on a parsed link table (matching the | |||
-- output of parseLink) and an options table (matching the input options for | |||
-- _formatLink). | |||
local page = maybeItalicize(parsed.page, options.italicizePage) | |||
local section = maybeItalicize(parsed.section, options.italicizeSection) | |||
if (not section) then | |||
return page | |||
elseif (not page) then | |||
return mw.ustring.format('§ %s', section) | |||
else | |||
return mw.ustring.format('%s § %s', page, section) | |||
end | |||
end | |||
local function missingArgError(target) | |||
mError = require('Module:Error') | |||
return mError.error{message = | |||
'Error: no link or target specified! ([[' .. target .. '#Errors|help]])' | |||
} | } | ||
end | end | ||
Line 93: | Line 111: | ||
yesno = require('Module:Yesno') | yesno = require('Module:Yesno') | ||
local args = getArgs(frame) | local args = getArgs(frame) | ||
local link = args[1] | local link = args[1] or args.link | ||
if not link then | local target = args[3] or args.target | ||
return | if not (link or target) then | ||
return missingArgError('Template:Format link') | |||
end | end | ||
return p._formatLink{ | return p._formatLink{ | ||
link = link, | link = link, | ||
display = args[2], | display = args[2] or args.display, | ||
target = target, | |||
italicizePage = yesno(args.italicizepage), | italicizePage = yesno(args.italicizepage), | ||
italicizeSection = yesno(args.italicizesection), | italicizeSection = yesno(args.italicizesection), | ||
Line 112: | Line 130: | ||
-- 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') | ||
checkTypeForNamedArg('_formatLink', | local function check(key, expectedType) --for brevity | ||
checkTypeForNamedArg( | |||
'_formatLink', key, options[key], expectedType or 'string', true | |||
) | |||
end | |||
check('link') | |||
check('display') | |||
check('target') | |||
check('italicizePage', 'boolean') | |||
check('italicizeSection', 'boolean') | |||
check('categorizeMissing') | |||
-- Normalize link and target and check that at least one is present | |||
if options.link == '' then options.link = nil end | |||
if options.target == '' then options.target = nil end | |||
if not (options.link or options.target) then | |||
return missingArgError('Module:Format link') | |||
end | |||
' | |||
local parsed = parseLink(options.link) | local parsed = parseLink(options.link) | ||
Line 147: | Line 154: | ||
local category = '' | local category = '' | ||
--Test if page exists if a diagnostic category is specified | -- Find the display text | ||
if not display then display = formatDisplay(parsed, options) end | |||
-- Handle the target option if present | |||
if options.target then | |||
local parsedTarget = parseLink(options.target) | |||
parsed.link = parsedTarget.link | |||
parsed.page = parsedTarget.page | |||
end | |||
-- 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 | ||
Line 155: | Line 172: | ||
end | end | ||
end | end | ||
-- | -- Format the result as a link | ||
if | if parsed.link == display then | ||
return mw.ustring.format('[[:%s]]%s', parsed.link, category) | return mw.ustring.format('[[:%s]]%s', parsed.link, category) | ||
else | |||
return mw.ustring.format('[[:%s|%s]]%s', parsed.link, display, category) | |||
end | end | ||
end | end | ||
Latest revision as of 13:14, 19 February 2022
This Lua module is used on approximately 160,000 pages. To avoid major disruption and server load, any changes should be tested in the module's /sandbox or /testcases subpages, or in your own module sandbox. The tested changes can be added to this page in a single edit. Consider discussing changes on the talk page before implementing them. |
This module, migrated from origins in Module:Hatnote, provides functionality for formatting links for display, including that powering the {{format link}} template.
It can pretty-format section links with the section symbol ("§") and appropriate whitespace, it automatically escapes category and file names with the colon trick, and includes functionality for italicizing the page or section name, and for detecting and categorizing results that produce red links.
Use from wikitext
The functions in this module cannot be used directly from #invoke, and must be used through templates instead. Please see Template:Format link for documentation on usage of that template.
Use from other Lua modules
To load this module from another Lua module, use the following code:
<syntaxhighlight lang="lua"> local mFormatLink = require('Module:Format link') </syntaxhighlight>
You can then use the functions as documented below.
_formatLink
<syntaxhighlight lang="lua"> mFormatLink._formatLink{
link = link, display = display, italicizePage = true, italicizeSection = true, categorizeMissing = 'Pages using formatted red links'
} </syntaxhighlight>
Formats link as a wikilink, with optional display value display. Categories and files are automatically escaped with the colon trick, and links to sections are automatically formatted as page § section, rather than the MediaWiki default of page#section. If manual piping is present in link, then the "manual" display value will be overridden by the display value if present.
If italicizePage is true then the page portion of the link is italicized, and if italicizeSection is true then the section portion of the link is italicized. If categorizeMissing is a string, then that value is used as a category name, and that category will be applied if the target of the link doesn't exist.
- Examples
- <syntaxhighlight lang="lua" inline>mFormatLink._formatLink{link = 'Foo#Bar'}</syntaxhighlight> → [[:Foo#Bar|Foo § Bar]] → Foo § Bar
- <syntaxhighlight lang="lua" inline>mFormatLink._formatLink{link = 'Baz', display = 'Qux'}</syntaxhighlight> → [[:Baz|Qux]] → Qux
- <syntaxhighlight lang="lua" inline>mFormatLink._formatLink{link = 'Foo|Bar', display = 'Baz'}</syntaxhighlight> → [[:Foo|Baz]] → Baz
- <syntaxhighlight lang="lua" inline>mFormatLink._formatLink{link = 'Nonexistent page', categorizeMissing = 'Example'}</syntaxhighlight> → [[:Nonexistent page]][[Category:Example]] → Nonexistent page
- <syntaxhighlight lang="lua" inline>mFormatLink._formatLink{link = 'Existing', categorizeMissing = 'Example'}</syntaxhighlight> → [[:Existing]] → Existing
- <syntaxhighlight lang="lua" inline>mFormatLink._formatLink{link = 'The Lord of the Rings#Plot', italicizePage = true}</syntaxhighlight> → [[:The Lord of the Rings#Plot|''The Lord of the Rings'' § Plot]] → The Lord of the Rings § Plot
- <syntaxhighlight lang="lua" inline>mFormatLink._formatLink{link = 'Cybercrime Prevention Act of 2012#Disini v. Secretary of Justice', italicizeSection = true}</syntaxhighlight> → [[:Cybercrime Prevention Act of 2012#Disini v. Secretary of Justice|Cybercrime Prevention Act of 2012 § ''Disini v. Secretary of Justice'']] → Cybercrime Prevention Act of 2012 § Disini v. Secretary of Justice
formatPages
<syntaxhighlight lang="lua"> mFormatLink.formatPages(options, pages) </syntaxhighlight>
This derived function is useful for lists that format many links. It formats an array of pages using the _formatLink function, and returns the result as an array. Options in the options table are applied, and use the same names as the options for _formatLink.
- Example
- <syntaxhighlight lang="lua" class="" id="" style="" inline="1">mFormatLink.formatPages({categorizeMissing = 'Example'}, {'Foo#Bar', 'Nonexistent page'})</syntaxhighlight> → <syntaxhighlight lang="lua" class="" id="" style="" inline="1">{'[[:Foo#Bar|Foo § Bar]]', '[[:Nonexistent page]][[Category:Example]]'}</syntaxhighlight>
-------------------------------------------------------------------------------- -- Format link -- -- 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 " § " as a separator rather than the standard MediaWiki "#". Used in -- the {{format link}} template. -------------------------------------------------------------------------------- local libraryUtil = require('libraryUtil') local checkType = libraryUtil.checkType local checkTypeForNamedArg = libraryUtil.checkTypeForNamedArg local mArguments -- lazily initialise [[Module:Arguments]] local mError -- lazily initialise [[Module:Error]] local yesno -- lazily initialise [[Module:Yesno]] local p = {} -------------------------------------------------------------------------------- -- Helper functions -------------------------------------------------------------------------------- local function getArgs(frame) -- Fetches the arguments from the parent frame. Whitespace is trimmed and -- blanks are removed. mArguments = require('Module:Arguments') return mArguments.getArgs(frame, {parentOnly = true}) end local function removeInitialColon(s) -- Removes the initial colon from a string, if present. return s:match('^:?(.*)') end local function maybeItalicize(s, shouldItalicize) -- Italicize s if s is a string and the shouldItalicize parameter is true. if s and shouldItalicize then return '<i>' .. s .. '</i>' else return s end end local function parseLink(link) -- Parse a link and return a table with the link's components. -- These components are: -- - link: the link, stripped of any initial colon (always present) -- - page: the page name (always present) -- - section: the page name (may be nil) -- - display: the display text, if manually entered after a pipe (may be nil) link = removeInitialColon(link) -- Find whether a faux display value has been added with the {{!}} magic -- word. local prePipe, display = link:match('^(.-)|(.*)$') link = prePipe or link -- Find the page, if it exists. -- For links like [[#Bar]], the page will be nil. local preHash, postHash = link:match('^(.-)#(.*)$') local page if not preHash then -- We have a link like [[Foo]]. page = link elseif preHash ~= '' then -- We have a link like [[Foo#Bar]]. page = preHash end -- Find the section, if it exists. local section if postHash and postHash ~= '' then section = postHash end return { link = link, page = page, section = section, display = display, } end local function formatDisplay(parsed, options) -- Formats a display string based on a parsed link table (matching the -- output of parseLink) and an options table (matching the input options for -- _formatLink). local page = maybeItalicize(parsed.page, options.italicizePage) local section = maybeItalicize(parsed.section, options.italicizeSection) if (not section) then return page elseif (not page) then return mw.ustring.format('§ %s', section) else return mw.ustring.format('%s § %s', page, section) end end local function missingArgError(target) mError = require('Module:Error') return mError.error{message = 'Error: no link or target specified! ([[' .. target .. '#Errors|help]])' } end -------------------------------------------------------------------------------- -- Main functions -------------------------------------------------------------------------------- function p.formatLink(frame) -- The formatLink export function, for use in templates. yesno = require('Module:Yesno') local args = getArgs(frame) local link = args[1] or args.link local target = args[3] or args.target if not (link or target) then return missingArgError('Template:Format link') end return p._formatLink{ link = link, display = args[2] or args.display, target = target, italicizePage = yesno(args.italicizepage), italicizeSection = yesno(args.italicizesection), categorizeMissing = args.categorizemissing } end function p._formatLink(options) -- The formatLink export function, for use in modules. checkType('_formatLink', 1, options, 'table') local function check(key, expectedType) --for brevity checkTypeForNamedArg( '_formatLink', key, options[key], expectedType or 'string', true ) end check('link') check('display') check('target') check('italicizePage', 'boolean') check('italicizeSection', 'boolean') check('categorizeMissing') -- Normalize link and target and check that at least one is present if options.link == '' then options.link = nil end if options.target == '' then options.target = nil end if not (options.link or options.target) then return missingArgError('Module:Format link') end local parsed = parseLink(options.link) local display = options.display or parsed.display local catMissing = options.categorizeMissing local category = '' -- Find the display text if not display then display = formatDisplay(parsed, options) end -- Handle the target option if present if options.target then local parsedTarget = parseLink(options.target) parsed.link = parsedTarget.link parsed.page = parsedTarget.page end -- Test if page exists if a diagnostic category is specified if catMissing and (mw.ustring.len(catMissing) > 0) then local title = nil if parsed.page then title = mw.title.new(parsed.page) end if title and (not title.isExternal) and (not title.exists) then category = mw.ustring.format('[[Category:%s]]', catMissing) end end -- Format the result as a link if parsed.link == display then return mw.ustring.format('[[:%s]]%s', parsed.link, category) else return mw.ustring.format('[[:%s|%s]]%s', parsed.link, display, category) end end -------------------------------------------------------------------------------- -- Derived convenience functions -------------------------------------------------------------------------------- function p.formatPages(options, pages) -- Formats an array of pages using formatLink and the given options table, -- and returns it as an array. Nil values are not allowed. local ret = {} for i, page in ipairs(pages) do ret[i] = p._formatLink{ link = page, categorizeMissing = options.categorizeMissing, italicizePage = options.italicizePage, italicizeSection = options.italicizeSection } end return ret end return p