Module:Delink/sandbox
Appearance
![]() | This is the module sandbox page for Module:Delink (diff). See also the companion subpage for test cases (run). |
![]() | This module is rated as ready for general use. It has reached a mature form and is thought to be relatively bug-free and ready for use wherever appropriate. It is ready to mention on help pages and other Wikipedia resources as an option for new users to learn. To reduce server load and bad output, it should be improved by sandbox testing rather than repeated trial-and-error editing. |
![]() | This module is subject to page protection. It is a highly visible module in use by a very large number of pages, or is substituted very frequently. Because vandalism or mistakes would affect many pages, and even trivial editing might cause substantial load on the servers, it is protected from editing. |
![]() | This module can only be edited by administrators because it is transcluded onto one or more cascade-protected pages. |
![]() | This Lua module is used in system messages, and on approximately 3,460,000 pages, or roughly 5% of all pages. Changes to it can cause immediate changes to the Wikipedia user interface. 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. Please discuss changes on the talk page before implementing them. |
This module implements the {{delink}} template. Please see the template page for documentation.
-- This module de-links most wikitext.
local getArgs = require('Module:Arguments').getArgs
local yesno = require('Module:Yesno')
p = {}
local function whitespaceYesno(val)
-- Like yesno, but trims whitespace from vals and removes blank strings.
if type(val) == 'string' then
val = val:match('^%s*(.-)%s*$')
if val == '' then
return nil
end
end
return yesno(val)
end
function p._delinkReversePipeTrick(s)
if s:find('^%[%[|.*[|\n]') or s == '[[|]]' then -- Check for newlines or multiple pipes.
return s
else
return s:match('%[%[|(.*)%]%]')
end
end
function p._delinkPipeTrick(s)
-- s the tile area, without bracket nor pipe
-- We need to deal with colons, brackets, and commas, per [[Help:Pipe trick]].
-- First, remove the text before the first colon, if any.
s = s:gsub('^(.-:)', '')
-- Next up, brackets and commas.
if s:find('%(.-%)$') then -- Brackets trump commas.
s = s:match('(.-) ?%(.-%)$')
elseif s:find(',') then -- If there are no brackets, display only the text before the first comma.
s = s:match('(.-),.*$')
end
return s
end
function p._delinkWikilink(s)
-- s should be a string starting with '[[' and ending with ']]'. It should not contain other ']]'
-- Deal with nested links
local nested = '[[' .. s:sub(3):gsub('%[%[.-%]%]', p._delinkWikilink)
if nested ~= s then
return nested
end
-- Deal with the reverse pipe trick.
if s:find('^%[%[|') then
return p._delinkReversePipeTrick(s)
end
local decoded = mw.uri.decode(s, 'PATH') -- decode percent-encoded entities. Leave underscores and plus signs.
decoded = mw.text.decode(decoded, true) -- decode HTML entities.
-- Check for bad titles. To do this we need to find the
-- title area of the link, i.e. the part before any pipes.
local titlearea, display = decoded:match('^%[%[([^|%]]*)|?(.*)%]%]')
-- Check for bad characters.
if titlearea:find('[%[%]<>{}%%%c\n]') then
return s
end
-- Check for categories, interwikis, and files.
local colonprefix = titlearea:match('^(.-):') or '' -- Get the text before the first colon.
local ns = mw.site.namespaces[colonprefix] -- see if this is a known namespace
if mw.language.isKnownLanguageTag(colonprefix)
or (ns and (ns.id == 6 or ns.id == 14))
then
return ''
end
-- Remove the colon if the link is using the [[Help:Colon trick]].
if titlearea:sub(1, 1) == ':' then
titlearea = titlearea:sub(2)
end
-- Deal with links using the [[Help:Pipe trick]].
if display == '' then
return p._delinkPipeTrick(titlearea)
end
-- Find the display area of the wikilink
if not display then -- Find if we're dealing with a piped link.
-- Remove new lines from the display of multiline piped links,
-- where the pipe is before the first new line.
titlearea = titlearea:gsub('\n', '')
end
return display or titlearea
end
function p._delinkURL(s)
-- Assume we have already delinked internal wikilinks, and that
-- we have been passed some text between two square brackets [foo].
-- If the text contains a line break it is not formatted as a URL, regardless of other content.
if s:find('\n') then
return s
end
-- Check if the text has a valid URL prefix and at least one valid URL character.
local valid_url_prefixes = {'//', 'http://', 'https://', 'ftp://', 'gopher://', 'mailto:', 'news:', 'irc://'}
local url_prefix
for i,v in ipairs(valid_url_prefixes) do
if s:find('^%[' .. v ..'[^"%s].*%]' ) then
url_prefix = v
break
end
end
-- Get display text
if not url_prefix then
-- Deal with nested links or send back original string.
return '[' .. s:sub(2):gsub('%[.-%]', p._delinkURL)
end
s = s:match('^%[' .. url_prefix .. '(.*)%]') -- Grab all of the text after the URL prefix and before the final square bracket.
s = s:match('^.-(["<> [].*)') or '' -- Grab all of the text after the first URL separator character ("<> ).
s = s:match('^%s*(%S.*)$') or '' -- If the separating character was a space, trim it off.
local s_decoded = mw.text.decode(s, true)
if s_decoded:find('%c') then
return s
else
return s_decoded
end
end
function p._delink(args)
local text = args[1] or ''
if whitespaceYesno(args.refs) then
-- Remove any [[Help:Strip markers]] representing ref tags. In most situations
-- this is not a good idea - only use it if you know what you are doing!
text = mw.ustring.gsub(text, 'UNIQ%w*%-ref%-%d*%-QINU', '')
end
if whitespaceYesno(args.comments) ~= false then
text = text:gsub('<!%-%-.-%-%->', '') -- Remove html comments.
end
if whitespaceYesno(args.wikilinks) ~= false then
text = text:gsub('%[%[.-%]%]', p._delinkWikilink) -- De-link wikilinks.
end
if whitespaceYesno(args.urls) ~= false then
text = text:gsub('%[.-%]', p._delinkURL) -- De-link URLs.
end
if whitespaceYesno(args.whitespace) ~= false then
-- Replace single new lines with a single space, but leave double new lines
-- and new lines only containing spaces or tabs before a second new line.
text = text:gsub('([^\n \t][ \t]*)\n([ \t]*[^\n \t])', '%1 %2')
text = text:gsub('[ \t]+', ' ') -- Remove extra tabs and spaces.
end
return text
end
function p.delink(frame)
local args = frame:getParent().args
return p._delink(args)
end
return p