Module:Format link: Difference between revisions

From NvWiki
Jump to navigation Jump to search
Avoid Lua erroring when we run out of expensive parser function calls
 
Reverted 1 edit by 41.121.61.119 (talk): Irrelevant. WP:NOTFORUM
Line 1: Line 1:
--------------------------------------------------------------------------------
==+{{para|target}}==
-- Format link
{{edit template-protected|answered=yes}}
--
-- 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 = {}
I request the module be edited to reflect the changes in [[Special:PermaLink/1062625990]], which add a {{para|target}} parameter. The intention of this parameter is mostly for humor (to look like a fancy link to one thing but really be a link to another thing) in talk and project space. It also has some use in {{tl|format linkr}} as it can allow users to link to pages which would be URL-encoding converted right now. Tests were added in [[Special:PermaLink/1061891226]].


--------------------------------------------------------------------------------
{{small|1=FYI, {{u|Nihiltres}}, sorry I keep pinging you, I just have found a lot of issues with your recent update slowly at different times is all, otherwise I would've combined them, but you [https://en.wikipedia.org/w/index.php?title=Template:Format_link/sandbox&type=revision&diff=1062620489&oldid=1061136558&diffmode=source forgot to update the sandbox of <nowiki>{{format link}}</nowiki> to point to the sandbox(!)] when you updated the module's name, boy was that an annoying bug to track down while writing this diff, easily accounts for 75% of time spent. I'm not that bright, though, a sharper student would've gotten it quickly.}} {{=3|8}} [[User:Psiĥedelisto|Psiĥedelisto]] ([[User talk:Psiĥedelisto|talk]] • [[Special:Contributions/Psiĥedelisto|contribs]]) <sup>please ''always'' [[Help:Notifications|ping]]!</sup> 16:04, 29 December 2021 (UTC)
-- Helper functions
--------------------------------------------------------------------------------


local function getArgs(frame)
:I don't see the benefit of this change given that the first positional parameter ''already'' specifies the target, and the second already specifies the display. It seems like it complicates the code needlessly, especially as implemented (I'd override the ''output'' of <code>parseLink</code> rather than integrate a second parameter to it). That said, perhaps I'm not interpreting the use-case quite right. What does this add that the template/module can't already do? <span style="white-space:nowrap;">{&#123;[[User:Nihiltres|<span style="color:#233D7A;">Nihiltres</span>]]&#8202;&#124;[[User talk:Nihiltres|talk]]&#8202;&#124;[[Special:Contributions/Nihiltres|edits]]}&#125;</span> 18:21, 29 December 2021 (UTC)
-- Fetches the arguments from the parent frame. Whitespace is trimmed and
::{{re|Nihiltres}} I don't mind reimplementing, but we should probably agree it's useful before I bother. So, consider e.g. {{code|<nowiki>{{format linkr|:ja:%E5%A1%A9#原料||:ja:%E3%82%B3%E3%82%B7%E3%83%A7%E3%82%A6}}</nowiki>}} which would create {{format linkr/sandbox|:ja:%E5%A1%A9#原料||:ja:%E3%82%B3%E3%82%B7%E3%83%A7%E3%82%A6}}. It is intended mostly for use with {{tl|format linkr}}, mostly where you rely heavily on that template's auto-formatting to remove underscores, URL encoding, etc., and is useless when <code>display</code> is given. All three should never be given. [[User:Psiĥedelisto|Psiĥedelisto]] ([[User talk:Psiĥedelisto|talk]] • [[Special:Contributions/Psiĥedelisto|contribs]]) <sup>please ''always'' [[Help:Notifications|ping]]!</sup> 19:55, 30 December 2021 (UTC)
-- blanks are removed.
:::{{re|Psiĥedelisto}} I think I might still not understand—in particular, the double pipe in your example really complicates it (is it an error?)—but translating to a functional goal, my guess is that you essentially want the option of applying the link formatting to the ''display'', so that e.g. <code><nowiki>{{format link|Display#Section|target=Target}}</nowiki></code> would resolve to <code><nowiki>[[:Target|Display §&amp;nbsp;Section]]</nowiki></code>. Is that a reasonable interpretation? I'm concerned that it's over-specialized, but if it isn't awful to implement and doesn't introduce edge-cases to extant uses, I don't see why not. <span style="white-space:nowrap;">{&#123;[[User:Nihiltres|<span style="color:#233D7A;">Nihiltres</span>]]&#8202;&#124;[[User talk:Nihiltres|talk]]&#8202;&#124;[[Special:Contributions/Nihiltres|edits]]}&#125;</span> 21:27, 30 December 2021 (UTC)
mArguments = require('Module:Arguments')
::::{{re|Nihiltres}} Not an error. It skips {{para|display}}, which is also possible. Your example, byte for byte, already works with my sandbox version: {{format link/sandbox|Display#Section|target=Target}}. Now, whether or not this is marginal use is somewhat debatable…I think more people would use {{tl|format linkr}} if they knew about it, because it really speeds up section linking, ''especially'' on foreign-language wikis (I bet this is why it was so quickly copied to Vietnamese Wikipedia). URL encoding and underlines really slow me down. {{=3|8}} [[User:Psiĥedelisto|Psiĥedelisto]] ([[User talk:Psiĥedelisto|talk]] • [[Special:Contributions/Psiĥedelisto|contribs]]) <sup>please ''always'' [[Help:Notifications|ping]]!</sup> 22:24, 30 December 2021 (UTC)
return mArguments.getArgs(frame, {parentOnly = true})
::::{{re|Nihiltres}} I thought of another use for the feature, which I just used on [[Talk:Furry fandom]]—often I want to link to a section ''in the article'' but write it ''on talk''. So I subst'd the /sandbox form of {{tl|format linkr}} with args {{code|<nowiki>{{format linkr/sandbox|#BDSM||Furry fandom#BDSM}}</nowiki>}} to get [[:Furry fandom#BDSM|§&nbsp;BDSM]]. That's actually very useful in practice, so I hope you'll reconsider this feature's utility. [[User:Psiĥedelisto|Psiĥedelisto]] ([[User talk:Psiĥedelisto|talk]] • [[Special:Contributions/Psiĥedelisto|contribs]]) <sup>please ''always'' [[Help:Notifications|ping]]!</sup> 02:20, 31 December 2021 (UTC)
end


local function removeInitialColon(s)
{{undent}} {{re|Psiĥedelisto}} I think you've made the case for including the feature, but I'd like to see a sandbox version that doesn't pollute <var>parseLink</var>, so as to uphold the [[single-responsibility principle]]. I'll poke at making a version like that; the main annoyance is that I'll probably need to extract the functionality that does the <code><nowiki>formatting §nbsp;for display</nowiki></code> to separate it from the part that makes a <code><nowiki>[[:link]]</nowiki></code>. I'll probably work on that, oh, next year (remember the current date). ;) <span style="white-space:nowrap;">{&#123;[[User:Nihiltres|<span style="color:#233D7A;">Nihiltres</span>]]&#8202;&#124;[[User talk:Nihiltres|talk]]&#8202;&#124;[[Special:Contributions/Nihiltres|edits]]}&#125;</span> 20:31, 31 December 2021 (UTC)
-- Removes the initial colon from a string, if present.
: Deactivating edit request since I see no need for an uninvolved template editor to do anything here (Nihiltres is an admin and can make then change themselves once they are satisfied) [[User:Pppery|* Pppery *]] [[User talk:Pppery|<sub style="color:#800000">it has begun...</sub>]] 05:16, 1 January 2022 (UTC)
return s:match('^:?(.*)')
::{{small|Thanks. [[User:Psiĥedelisto|Psiĥedelisto]] ([[User talk:Psiĥedelisto|talk]] • [[Special:Contributions/Psiĥedelisto|contribs]]) <sup>please ''always'' [[Help:Notifications|ping]]!</sup> 10:11, 4 January 2022 (UTC)}}
end
:{{re|Psiĥedelisto}} I've implemented a version that's a bit cleaner. Would you please review it? It passes extant tests, but I think that we could probably add a few more to make certain edge-case behaviours more explicit. <span style="white-space:nowrap;">{&#123;[[User:Nihiltres|<span style="color:#233D7A;">Nihiltres</span>]]&#8202;&#124;[[User talk:Nihiltres|talk]]&#8202;&#124;[[Special:Contributions/Nihiltres|edits]]}&#125;</span> 22:53, 1 January 2022 (UTC)
 
::{{re|Nihiltres}} Only had one suggestion, to use [[Module:Error]]. [https://en.wikipedia.org/w/index.php?title=Module%3AFormat_link%2Fsandbox&type=revision&diff=1063683884&oldid=1063220129]. Looks good!~ [[User:Psiĥedelisto|Psiĥedelisto]] ([[User talk:Psiĥedelisto|talk]] • [[Special:Contributions/Psiĥedelisto|contribs]]) <sup>please ''always'' [[Help:Notifications|ping]]!</sup> 10:11, 4 January 2022 (UTC)
local function maybeItalicize(s, shouldItalicize)
:::{{re|Psiĥedelisto}} Great, I'll make the update as soon as I've got the time to also update the documentation with all the new stuff. :) <span style="white-space:nowrap;">{&#123;[[User:Nihiltres|<span style="color:#233D7A;">Nihiltres</span>]]&#8202;&#124;[[User talk:Nihiltres|talk]]&#8202;&#124;[[Special:Contributions/Nihiltres|edits]]}&#125;</span> 18:07, 4 January 2022 (UTC)
-- 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('§&nbsp;%s', section)
else
return mw.ustring.format('%s §&nbsp;%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) then
local success, exists = pcall(function() return title.exists end)
if success and not exists then
category = mw.ustring.format('[[Category:%s]]', catMissing)
end
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

Revision as of 11:12, 28 April 2024

+|target=

Template:Edit template-protected

I request the module be edited to reflect the changes in Special:PermaLink/1062625990, which add a |target= parameter. The intention of this parameter is mostly for humor (to look like a fancy link to one thing but really be a link to another thing) in talk and project space. It also has some use in {{format linkr}} as it can allow users to link to pages which would be URL-encoding converted right now. Tests were added in Special:PermaLink/1061891226.

Template:Small Template:=3 Psiĥedelisto (talkcontribs) please always ping! 16:04, 29 December 2021 (UTC)

I don't see the benefit of this change given that the first positional parameter already specifies the target, and the second already specifies the display. It seems like it complicates the code needlessly, especially as implemented (I'd override the output of parseLink rather than integrate a second parameter to it). That said, perhaps I'm not interpreting the use-case quite right. What does this add that the template/module can't already do? {{Nihiltres |talk |edits}} 18:21, 29 December 2021 (UTC)
Template:Re I don't mind reimplementing, but we should probably agree it's useful before I bother. So, consider e.g. Template:Code which would create Template:Format linkr/sandbox. It is intended mostly for use with {{format linkr}}, mostly where you rely heavily on that template's auto-formatting to remove underscores, URL encoding, etc., and is useless when display is given. All three should never be given. Psiĥedelisto (talkcontribs) please always ping! 19:55, 30 December 2021 (UTC)
Template:Re I think I might still not understand—in particular, the double pipe in your example really complicates it (is it an error?)—but translating to a functional goal, my guess is that you essentially want the option of applying the link formatting to the display, so that e.g. {{format link|Display#Section|target=Target}} would resolve to [[:Target|Display §&nbsp;Section]]. Is that a reasonable interpretation? I'm concerned that it's over-specialized, but if it isn't awful to implement and doesn't introduce edge-cases to extant uses, I don't see why not. {{Nihiltres |talk |edits}} 21:27, 30 December 2021 (UTC)
Template:Re Not an error. It skips |display=, which is also possible. Your example, byte for byte, already works with my sandbox version: Template:Format link/sandbox. Now, whether or not this is marginal use is somewhat debatable…I think more people would use {{format linkr}} if they knew about it, because it really speeds up section linking, especially on foreign-language wikis (I bet this is why it was so quickly copied to Vietnamese Wikipedia). URL encoding and underlines really slow me down. Template:=3 Psiĥedelisto (talkcontribs) please always ping! 22:24, 30 December 2021 (UTC)
Template:Re I thought of another use for the feature, which I just used on Talk:Furry fandom—often I want to link to a section in the article but write it on talk. So I subst'd the /sandbox form of {{format linkr}} with args Template:Code to get § BDSM. That's actually very useful in practice, so I hope you'll reconsider this feature's utility. Psiĥedelisto (talkcontribs) please always ping! 02:20, 31 December 2021 (UTC)

Template:Undent Template:Re I think you've made the case for including the feature, but I'd like to see a sandbox version that doesn't pollute parseLink, so as to uphold the single-responsibility principle. I'll poke at making a version like that; the main annoyance is that I'll probably need to extract the functionality that does the formatting §nbsp;for display to separate it from the part that makes a [[:link]]. I'll probably work on that, oh, next year (remember the current date). ;) {{Nihiltres |talk |edits}} 20:31, 31 December 2021 (UTC)

Deactivating edit request since I see no need for an uninvolved template editor to do anything here (Nihiltres is an admin and can make then change themselves once they are satisfied) * Pppery * it has begun... 05:16, 1 January 2022 (UTC)
Template:Small
Template:Re I've implemented a version that's a bit cleaner. Would you please review it? It passes extant tests, but I think that we could probably add a few more to make certain edge-case behaviours more explicit. {{Nihiltres |talk |edits}} 22:53, 1 January 2022 (UTC)
Template:Re Only had one suggestion, to use Module:Error. [1]. Looks good!~ Psiĥedelisto (talkcontribs) please always ping! 10:11, 4 January 2022 (UTC)
Template:Re Great, I'll make the update as soon as I've got the time to also update the documentation with all the new stuff. :) {{Nihiltres |talk |edits}} 18:07, 4 January 2022 (UTC)