Jump to content

Module:Delink/testcases: Difference between revisions

From Wikipedia, the free encyclopedia
Content deleted Content added
Another test case for HTML breaks
No edit summary
Tag: Reverted
Line 1: Line 1:
-- This module de-links most wikitext.
local p = require('Module:UnitTests')


require('Module:No globals')
function p:test01_basic()
self:preprocess_equals_many('{{delink/sandbox|', '}}', {
{ '[[Apple]]', 'Apple'},
{ '[[Orange]]s are dissimilar to [[Apple]]s', 'Oranges are dissimilar to Apples'},
{ '[[Apple]]s and [[orange]]s and [[fruit salad|other kinds of fruit]]', 'Apples and oranges and other kinds of fruit'},
{ 'All [[Gone]] [[wikt:to|]] [[Bed]] [[Now]]', 'All Gone to Bed Now'},
{ '[[Survey]] of [http://books.google.com Google Books] on [[UK|Britain]]', 'Survey of Google Books on Britain'}
}, {nowiki='yes'})
end


local p = {}
function p:test02_cats_and_interwikis()
self:preprocess_equals_many('{{delink/sandbox|', '}}', {
{ '[[Category:Foo]]', ''},
{ '[[category:Foo]]', ''},
{ '[[Image:Foo]]', ''},
{ '[[es:Foo]]', ''},
{ '[[wikt:Foo]]', 'wikt:Foo'},
{ '[[es:Wikipedia:Políticas]]', ''},
{ '[[abcd:efgh:ijkl]]', 'abcd:efgh:ijkl'},
{ '[[cbk-zam:abcd:efgh]]', ''},
{ '[[meatball:WikiPedia]]', 'meatball:WikiPedia' },
}, {nowiki='yes'})
end


local getArgs
function p:test03_colontrick()
self:preprocess_equals_many('{{delink/sandbox|', '}}', {
{ '[[:Category:Foo]]', 'Category:Foo'},
{ '[[:es:Foo]]', 'es:Foo'},
{ '[[:wikt:Foo]]', 'wikt:Foo'},
{ '[[:es:Wikipedia:Políticas]]', 'es:Wikipedia:Políticas'},
{ '[[:abcd:efgh:ijkl]]', 'abcd:efgh:ijkl'},
{ '[[:cbk-zam:abcd:efgh]]', 'cbk-zam:abcd:efgh'},
{ '[[:meatball:WikiPedia]]', 'meatball:WikiPedia'},
}, {nowiki='yes'})
end


function p:test04_pipetrick()
local function delinkReversePipeTrick(s)
if s:match("^%[%[|.*[|\n]") then -- Check for newlines or multiple pipes.
self:preprocess_equals_many('{{delink/sandbox|', '}}', {
return s
{ '[[Pipe (computing)|]]', 'Pipe'},
else
{ '[[Boston, Massachusetts|]]', 'Boston'},
return s:match("%[%[|(.*)%]%]")
{ '[[Wikipedia:Verifiability|]]', 'Verifiability'},
end
{ '[[User:Example|]]', 'Example'},
{ '[[Template:Welcome|]]', 'Welcome'},
{ '[[Yours, Mine and Ours (1968 film)|]]', 'Yours, Mine and Ours'},
{ '[[:es:Wikipedia:Políticas|]]', 'Wikipedia:Políticas'},
{ '[[Il Buono, il Brutto, il Cattivo|]]', 'Il Buono'},
{ '[[Wikipedia:Manual of Style (Persian)|]]', 'Manual of Style'},
{ '[[Wikipedia:Manual of Style(Persian)|]]', 'Manual of Style'},
{ '[[foo|bar|]]', 'bar|'},
{ '[[foo||]]', '|'},
{ 'xx[[foo bar (baz)|]]xx', 'xxfoo bar xx'},
}, {nowiki='yes'})
end
end


function p:test05_reverse_pipetrick()
local function delinkPipeTrick(s)
local linkarea, display = "", ""
self:preprocess_equals_many('{{delink/sandbox|', '}}', {
-- We need to deal with colons, brackets, and commas, per [[Help:Pipe trick]].
{ '[[|foo]]', 'foo'},
{ '[[|multiple|pipes]]', '[[|multiple|pipes]]'},
-- First, remove the text before the first colon, if any.
{ '[[|foo (bar)]]', 'foo (bar)'},
if s:match(":") then
{ '[[|foo, bar (baz)]]', 'foo, bar (baz)'},
s = s:match("%[%[.-:(.*)|%]%]")
{ '[[|simultaneous pipe trick|]]', '[[|simultaneous pipe trick|]]'},
-- If there are no colons, grab all of the text apart from the square brackets and the pipe.
}, {nowiki='yes'})
else
s = s:match("%[%[(.*)|%]%]")
end
-- Next up, brackets and commas.
if s:match("%(.-%)$") then -- Brackets trump commas.
s = s:match("(.-) ?%(.-%)$")
elseif s:match(",") then -- If there are no brackets, display only the text before the first comma.
s = s:match("(.-),.*$")
end
return s
end
end


function p:test06_badlinks()
local function delinkWikilink(s)
local result = s
self:preprocess_equals_many('{{delink/sandbox|', '}}', {
-- Deal with the reverse pipe trick.
{ '[[<]]', '[[<]]'},
if result:match("%[%[|") then
{ '[[Category:<]]', '[[Category:<]]'},
return delinkReversePipeTrick(result)
{ '[[:Category:<]]', '[[:Category:<]]'},
end
{ '[[:Category:<|Foo]]', '[[:Category:<|Foo]]'},
{ '[[:Category:<|]]', '[[:Category:<|]]'},
result = mw.uri.decode(result, "PATH") -- decode percent-encoded entities. Leave underscores and plus signs.
{ '[[:Category:Foo|<]]', '<'},
result = mw.text.decode(result, true) -- decode HTML entities.
{ '[[Category:Foo|<]]', ''},
{ '[[Foo:Bar|<]]', '<'},
-- Check for bad titles. To do this we need to find the
{ '[[Foo:Bar:>]]', '[[Foo:Bar:>]]'},
-- title area of the link, i.e. the part before any pipes.
{ '[[es:Wikipedia:<]]', '[[es:Wikipedia:<]]'},
local titlearea
{ '[[es:Wikipedia:Foo|<]]', ''},
if result:match("|") then -- Find if we're dealing with a piped link.
{ '[[:es:Wikipedia:<]]', '[[:es:Wikipedia:<]]'},
titlearea = result:match("^%[%[(.-)|.*%]%]")
{ '[[:es:Wikipedia:Foo|<]]', '<'},
else
{ '[[Foo:Bar:Foo#>]]', 'Foo:Bar:Foo#>'},
titlearea = result:match("^%[%[(.-)%]%]")
{ '[[Foo:Bar:Foo>#Baz]]', '[[Foo:Bar:Foo>#Baz]]'},
end
{ '[[Foo#Bar>#Baz]]', 'Foo#Bar>#Baz'},
-- Check for bad characters.
{ '[[Foo>#Bar#Baz]]', '[[Foo>#Bar#Baz]]'},
if mw.ustring.match(titlearea, "[%[%]<>{}%%%c\n]") then
{ '[[wikt:es:asdf:&#x0000;Template:title#Fragment]]', '[[wikt:es:asdf:&#x0000;Template:title#Fragment]]'},
return s
{ '[[foo]]', '[[foo]]'}, -- ASCII delete character
end
}, {nowiki='yes'})
end
-- Check for categories, interwikis, and files.

local colonprefix = result:match("%[%[(.-):.*%]%]") or "" -- Get the text before the first colon.
function p:test07_URI_slashes()
local ns = mw.site.namespaces[colonprefix] -- see if this is a known namespace
self:preprocess_equals_many('{{delink/sandbox|', '}}', {
if mw.language.isKnownLanguageTag(colonprefix)
{ '[/foo]', '[/foo]'},
or ( ns and ( ns.canonicalName == "File" or ns.canonicalName == "Category" ) ) then
{ '[/foo bar]', '[/foo bar]'},
return ""
{ '[//foo]', ''},
end
{ '[//foo bar]', 'bar'},
{ '[///foo]', ''},
-- Remove the colon if the link is using the [[Help:Colon trick]].
{ '[///foo bar]', 'bar'},
if result:match("%[%[:") then
{ '[////foo]', ''},
result = "[[" .. result:match("%[%[:(.*%]%])")
{ '[////foo bar]', 'bar'},
end
{ '[///////////////////////////////////foo]', ''},
{ '[///////////////////////////////////foo bar]', 'bar'},
-- Deal with links using the [[Help:Pipe trick]].
}, {nowiki='yes'})
if mw.ustring.match(result, "^%[%[[^|]*|%]%]") then
end
return delinkPipeTrick(result)

end
function p:test08_URI_prefixes()
self:preprocess_equals_many('{{delink/sandbox|', '}}', {
-- Find the display area of the wikilink
{ '[://foo]', '[://foo]'},
if result:match("|") then -- Find if we're dealing with a piped link.
{ '[:://foo]', '[:://foo]'},
result = result:match("^%[%[.-|(.+)%]%]")
{ '[abcd://]', '[abcd://]'},
-- Remove new lines from the display of multiline piped links,
{ '[abcd://foo]', '[abcd://foo]'},
-- where the pipe is before the first new line.
{ '[http://]', '[http://]'},
result = result:gsub("\n", "")
{ '[http://foo]', ''},
else
{ '[https://]', '[https://]'},
result = result:match("^%[%[(.-)%]%]")
{ '[https://foo]', ''},
end
{ '[ftp://]', '[ftp://]'},
{ '[ftp://foo]', ''},
{ '[gopher://]', '[gopher://]'},
{ '[gopher://foo]', ''},
{ '[mailto:]', '[mailto:]'},
{ '[mailto:foo]', ''},
{ '[news]', '[news]'},
{ '[news at ten]', '[news at ten]'},
{ '[news:]', '[news:]'},
{ '[news: at ten]', '[news: at ten]'},
{ '[news:/]', ''},
{ '[news:/ at ten]', 'at ten'},
{ '[news://]', ''},
{ '[news://foo]', ''},
{ '[news://foo at ten]', 'at ten'},
{ '[irc://]', '[irc://]'},
{ '[irc://foo]', ''},
}, {nowiki='yes'})
end

function p:test09_URI_special_characters()
self:preprocess_equals_many('{{delink/sandbox|', '}}', {
{ '[:http://foo]', '[:http://foo]'},
{ '[http://<foo]', '<foo'},
{ '[http://foo"bar]', '"bar'},
{ '[http://"foo]', '[http://"foo]'},
{ '[http://>foo]', '>foo'},
{ '[http://foo<bar]', '<bar'},
{ '[http://foo>bar]', '>bar'},
{ '[http:// foo]', '[http:// foo]'},
}, {nowiki='yes'})
end

function p:test10_nesting()
self:preprocess_equals_many('{{delink/sandbox|', '}}', {
{ 'text[[<s name=]]>stricken</s>more text]]', 'text[[<s name=]]>stricken</s>more text]]'},
{ 'text[[<s>stricken</s>more text]]', 'text[[<s>stricken</s>more text]]'},
{ '[[outer[[inner]]outer]]', '[[outerinnerouter]]'},
{ '[http://outer outer [[inner]] outer]', 'outer inner outer'},
{ '[[outer[http://inner inner]outer]]', '[[outerinnerouter]]'},
{ '[[outer[http://inner]outer]]]', '[[outerouter]]]'},
}, {nowiki='yes'})
end

function p:test11_multiple_pipes()
self:preprocess_equals_many('{{delink/sandbox|', '}}', {
{ '[[foo|bar|baz]]', 'bar|baz'},
{ '[[foo|bar|baz|]]', 'bar|baz|'},
{ '[[|foo|bar|baz]]', '[[|foo|bar|baz]]'},
{ '[[|foo|bar|baz|]]', '[[|foo|bar|baz|]]'},
{ '[[foo|bar|baz||]]', 'bar|baz||'},
{ '[[||foobarbaz]]', '[[||foobarbaz]]'},
{ '[[foobarbaz||]]', '|'},
}, {nowiki='yes'})
end

function p:test12_http_links()
self:preprocess_equals_many('{{delink/sandbox|', '}}', {
{ '[http]', '[http]'},
{ '[http:foo]', '[http:foo]'},
{ '[http:]', '[http:]'},
{ '[http:foo]', '[http:foo]'},
{ '[http:/]', '[http:/]'},
{ '[http:/foo]', '[http:/foo]'},
{ '[http://]', '[http://]'},
{ '[http://foo]', ''},
}, {nowiki='yes'})
end

function p:test13_whitespace()
self:preprocess_equals_many('{{delink/sandbox|', '}}', {
{ 'xx[[ fruit salad | many kinds of fruit ]]xx', 'xx many kinds of fruit xx'},
{ '[http://www.example.com example]', 'example'},
{ [=[[[link with
a line break in]]]=], '[[link with a line break in]]'},
{ [=[[[link with

two line breaks in]]]=], [=[[[link with

two line breaks in]]]=] },
{ [=[an [http://www.example.com
example].]=], 'an [http://www.example.com example].'},
{ [=[an [http://www.example.com

example].]=], [=[an [http://www.example.com

example].]=] },
{ '[http://www.example.com HTML line breaks] between<br>two [http://www.example.com links]', 'HTML line breaks between two links'},
{ '[http://www.example.com HTML line break<br />within<br/>a link]', 'HTML line break within a link'},
{ '[http://www.example.com Double HTML line break<br /><br />within a link]', [=[Double HTML line break

within a link]=]},
{ '[http://www.example.com non-breaking spaces]', 'non-breaking spaces'},
{ '[http://www.example.com tab characters]', 'tab characters'},
{ '[http://www.example.com multiple non-breaking spaces]', 'multiple non-breaking spaces'},
{ '[http://www.example.com multiple tab characters]', 'multiple tab characters'},
}, {nowiki='yes'})
end

function p:test14_full_paragraphs()
self:preprocess_equals_many('{{delink/sandbox|', '}}', {
{
[==[He then studied at [[Saint Patrick Seminary, Menlo Park|St. Patrick's Seminary]] in [[Menlo Park, California|Menlo Park]]. He was [[Holy Orders|ordained]] to the [[Priesthood (Catholic Church)|priesthood]] on June 10, 1933.<ref name=hierarchy>{{cite news|work=Catholic-Hierarchy.org|title=Bishop Merlin Joseph Guilfoyle|url=http://www.catholic-hierarchy.org/bishop/bguimj.html}}</ref> In 1937, he earned a [[Doctor of Canon Law]] from the [[The Catholic University of America|Catholic University of America]] in [[Washington, D.C.]]<ref name=curtis/> He became a [[Monsignor|Domestic Prelate]] in 1949, and was co-founder and [[chaplain]] of [http://www.stthomasmore-sf.org/ St. Thomas More Society].]==],
[==[He then studied at St. Patrick's Seminary in Menlo Park. He was ordained to the priesthood on June 10, 1933. In 1937, he earned a Doctor of Canon Law from the Catholic University of America in Washington, D.C. He became a Domestic Prelate in 1949, and was co-founder and chaplain of St. Thomas More Society.]==],
},
})
end

function p:test15_full_paragraphs_removing_ref_strip_markers()
self:preprocess_equals_many('{{delink/sandbox|refs=yes|', '}}', {
{
[==[He then studied at [[Saint Patrick Seminary, Menlo Park|St. Patrick's Seminary]] in [[Menlo Park, California|Menlo Park]]. He was [[Holy Orders|ordained]] to the [[Priesthood (Catholic Church)|priesthood]] on June 10, 1933.<ref name=hierarchy>{{cite news|work=Catholic-Hierarchy.org|title=Bishop Merlin Joseph Guilfoyle|url=http://www.catholic-hierarchy.org/bishop/bguimj.html}}</ref> In 1937, he earned a [[Doctor of Canon Law]] from the [[The Catholic University of America|Catholic University of America]] in [[Washington, D.C.]]<ref name=curtis/> He became a [[Monsignor|Domestic Prelate]] in 1949, and was co-founder and [[chaplain]] of [http://www.stthomasmore-sf.org/ St. Thomas More Society].]==],
[==[He then studied at St. Patrick's Seminary in Menlo Park. He was ordained to the priesthood on June 10, 1933. In 1937, he earned a Doctor of Canon Law from the Catholic University of America in Washington, D.C. He became a Domestic Prelate in 1949, and was co-founder and chaplain of St. Thomas More Society.]==],
},
})
end


return result
function p:test16_html_comments()
self:preprocess_equals_many('{{delink/sandbox|', '}}', {
{ '[[foo<!--bar]]-->baz]]', 'foobaz'},
{ 'foo<!--bar-->baz', 'foobaz'},
{ 'foo<!--bar<!--baz-->bat-->bam', 'foobat-->bam'},
{ 'foo[http://abcd<!--bar-->efgh]baz', 'foobaz'},
{ 'foo[http://abcd<!--barefgh]baz-->bat', 'foo[http://abcdbat'},
{ 'foo[http://ab[[cd]]<!--barefgh]baz-->bat', 'foo[http://abcdbat'},
{ 'foo[http://ab{{!((}}cd<!--bar]]efgh]baz-->bat', 'foo[http://ab[[cdbat'},
{ 'foo[[bar<!--baz-->]]bam', 'foobarbam'},
}, {nowiki='yes'})
end
end


function p:test17_nowiki()
local function delinkURL(s)
-- Assume we have already delinked internal wikilinks, and that
self:preprocess_equals_many('{{delink/sandbox|', '}}', {
-- we have been passed some text between two square brackets [foo].
{ '<nowiki>[[foo]]</nowiki>', '[[foo]]'},
{ '[[foo]]<nowiki>[[bar]]</nowiki>[[baz]]', 'foo[[bar]]baz'},
-- If the text contains a line break it is not formatted as a URL, regardless of other content.
{ '<nowiki>[http://www.example.com foo]</nowiki>', '[http://www.example.com foo]'},
if s:match("\n") then
{ '{{!((}}foo<nowiki>bar]]</nowiki>', '[[foobar]]'},
return s
{ '<nowiki>[[foo</nowiki>bar]]', '[[foobar]]'},
end
{ '[http://www.exa<nowiki>mple.com foo]</nowiki>', '[http://www.example.com foo]'},
}, {nowiki='yes'})
-- 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 mw.ustring.match(s, '^%[' .. v ..'[^"%s].*%]' ) then
url_prefix = v
break
end
end
-- Get display text
if not url_prefix then
return s
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 = mw.ustring.match(s, "^%s*(%S.*)$") or "" -- If the separating character was a space, trim it off.
local s_decoded = mw.text.decode(s, true)
if mw.ustring.match(s_decoded, "%c") then
return s
else
return s_decoded
end
end
end


local function delinkLinkClass(s, pattern, delinkFunction)
function p:test18_decoding()
if not type(s) == "string" then
self:preprocess_equals_many('{{delink/sandbox|', '}}', {
error("Attempt to de-link non-string input.", 2)
{ '[[foo%25 bar]]', 'foo% bar'},
end
{ '[[foo%25bar]]', '[[foo%25bar]]'},
if not ( type(pattern) == "string" and mw.ustring.sub(pattern, 1, 1) == "^" ) then
{ '[[foo%24bar]]', 'foo$bar'},
error('Invalid pattern detected. Patterns must begin with "^".', 2)
{ '[[foo%88bar]]', '[[foo%88bar]]'},
end
{ '[[foo%6Abar]]', 'foojbar'},
-- Iterate over the text string, and replace any matched text. using the
{ '[[foo%11bar]]', '[[foo%11bar]]'},
-- delink function. We need to iterate character by character rather
{ '[[foo&amp;bar]]', 'foo&bar'},
-- than just use gsub, otherwise nested links aren't detected properly.
{ '[[foo%25bar]]', '[[foo%25bar]]'},
local result = ""
{ '[[foo&a%6Amp;bar]]', '[[foo&a%6Amp;bar]]'},
while s ~= '' do
{ '[[foo&%61mp;bar]]', 'foo&bar'},
-- Replace text using one iteration of gsub.
{ '[[foo&%62mp;bar]]', '[[foo&%62mp;bar]]'},
s = mw.ustring.gsub(s, pattern, delinkFunction, 1)
{ '[[foo&#x25;bar]]', '[[foo&#x25;bar]]'},
-- Append the left-most character to the result string.
{ '[[foo&#x25;62bar]]', '[[foo&#x25;62bar]]'},
result = result .. mw.ustring.sub(s, 1, 1)
{ '[[foo&#x0000;bar]]', '[[foo&#x0000;bar]]'},
s = mw.ustring.sub(s, 2, -1)
{ '[[foo&#x00000;bar]]', '[[foo&#x00000;bar]]'},
end
{ '[[foo&#x22;bar]]', 'foo"bar'},
return result
{ '[[foo&#x0000022;bar]]', 'foo"bar'},
{ '[[foo&amp;amp;bar]]', '[[foo&amp;amp;bar]]'},
}, {nowiki='yes'})
end
end


function p:test19_URL_decoding()
function p._delink(args)
local text = args[1] or ""
self:preprocess_equals_many('{{delink/sandbox|', '}}', {
if args.refs == "yes" then
{ '[http://www.example.com foo%25 bar]', 'foo%25 bar'},
-- Remove any [[Help:Strip markers]] representing ref tags. In most situations
{ '[http://www.example.com foo%25bar]', 'foo%25bar'},
-- this is not a good idea - only use it if you know what you are doing!
{ '[http://www.example.com foo%24bar]', 'foo%24bar'},
text = mw.ustring.gsub(text, "UNIQ%w*%-ref%-%d*%-QINU", "")
{ '[http://www.example.com foo%88bar]', 'foo%88bar'},
end
{ '[http://www.example.com foo%6Abar]', 'foo%6Abar'},
if not (args.comments == "no") then
{ '[http://www.example.com foo%11bar]', 'foo%11bar'},
text = text:gsub("<!%-%-.-%-%->", "") -- Remove html comments.
{ '[http://www.example.com foo&amp;bar]', 'foo&bar'},
end
{ '[http://www.example.com foo%25bar]', 'foo%25bar'},
if not (args.wikilinks == "no") then
{ '[http://www.example.com foo&a%6Amp;bar]', 'foo&a%6Amp;bar'},
text = delinkLinkClass(text, "^%[%[.-%]%]", delinkWikilink) -- De-link wikilinks.
{ '[http://www.example.com foo&%61mp;bar]', 'foo&%61mp;bar'},
end
{ '[http://www.example.com foo&%62mp;bar]', 'foo&%62mp;bar'},
if not (args.urls == "no") then
{ '[http://www.example.com foo&#x25;bar]', 'foo%bar'},
text = delinkLinkClass(text, "^%[.-%]", delinkURL) -- De-link URLs.
{ '[http://www.example.com foo&#x25;62bar]', 'foo%62bar'},
end
{ '[http://www.example.com foo&#x0000;bar]', 'foo&#x0000;bar'},
if not (args.whitespace == "no") then
{ '[http://www.example.com foo&#x00000;bar]', 'foo&#x00000;bar'},
-- Replace single new lines with a single space, but leave double new lines
{ '[http://www.example.com foo&#x22;bar]', 'foo"bar'},
-- and new lines only containing spaces or tabs before a second new line.
{ '[http://www.example.com foo&#x0000022;bar]', 'foo"bar'},
text = mw.ustring.gsub(text, "([^\n \t][ \t]*)\n([ \t]*[^\n \t])", "%1 %2")
}, {nowiki='yes'})
text = text:gsub("[ \t]+", " ") -- Remove extra tabs and spaces.
end
return text
end
end


function p:test20_no_link()
function p.delink(frame)
if not getArgs then
self:preprocess_equals_many('{{delink/sandbox|', '}}', {
getArgs = require('Module:Arguments').getArgs
{ '#Foo', '#Foo' },
end
{ 'Foo#Bar', 'Foo#Bar' },
return p._delink(getArgs(frame, {wrappers = 'Template:Delink'}))
}, {nowiki='yes'})
end
end



Revision as of 00:52, 30 March 2021

-- This module de-links most wikitext.

require('Module:No globals')

local p = {}

local getArgs

local function delinkReversePipeTrick(s)
    if s:match("^%[%[|.*[|\n]") then -- Check for newlines or multiple pipes.
        return s
    else
        return s:match("%[%[|(.*)%]%]")
    end
end

local function delinkPipeTrick(s)
    local linkarea, display = "", ""
    -- We need to deal with colons, brackets, and commas, per [[Help:Pipe trick]].
    
    -- First, remove the text before the first colon, if any.
    if s:match(":") then
        s = s:match("%[%[.-:(.*)|%]%]")
    -- If there are no colons, grab all of the text apart from the square brackets and the pipe.
    else
        s = s:match("%[%[(.*)|%]%]")
    end
    
    -- Next up, brackets and commas.
    if s:match("%(.-%)$") then -- Brackets trump commas.
        s = s:match("(.-) ?%(.-%)$")
    elseif s:match(",") then -- If there are no brackets, display only the text before the first comma.
        s = s:match("(.-),.*$")
    end
    return s
end

local function delinkWikilink(s)
    local result = s
    -- Deal with the reverse pipe trick.
    if result:match("%[%[|") then
        return delinkReversePipeTrick(result)
    end
    
    result = mw.uri.decode(result, "PATH") -- decode percent-encoded entities. Leave underscores and plus signs.
    result = mw.text.decode(result, 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
    if result:match("|") then -- Find if we're dealing with a piped link.
        titlearea = result:match("^%[%[(.-)|.*%]%]")
    else
        titlearea = result:match("^%[%[(.-)%]%]")
    end
    -- Check for bad characters.
    if mw.ustring.match(titlearea, "[%[%]<>{}%%%c\n]") then
        return s
    end
    
    -- Check for categories, interwikis, and files.
    local colonprefix = result: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.canonicalName == "File" or ns.canonicalName == "Category" ) ) then
        return ""
    end
    
    -- Remove the colon if the link is using the [[Help:Colon trick]].
    if result:match("%[%[:") then
        result = "[[" .. result:match("%[%[:(.*%]%])")
    end
    
    -- Deal with links using the [[Help:Pipe trick]].
    if mw.ustring.match(result, "^%[%[[^|]*|%]%]") then
        return delinkPipeTrick(result)
    end
    
    -- Find the display area of the wikilink
    if result:match("|") then -- Find if we're dealing with a piped link.
        result = result:match("^%[%[.-|(.+)%]%]")
        -- Remove new lines from the display of multiline piped links,
        -- where the pipe is before the first new line.
        result = result:gsub("\n", "")
    else
        result = result:match("^%[%[(.-)%]%]")
    end

    return result
end

local function 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:match("\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 mw.ustring.match(s, '^%[' .. v ..'[^"%s].*%]' ) then
            url_prefix = v
            break
        end
    end
    
    -- Get display text
    if not url_prefix then
        return s
    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 = mw.ustring.match(s, "^%s*(%S.*)$") or "" -- If the separating character was a space, trim it off.
    
    local s_decoded = mw.text.decode(s, true)
    if mw.ustring.match(s_decoded, "%c") then
        return s
    else    
        return s_decoded
    end
end

local function delinkLinkClass(s, pattern, delinkFunction)
    if not type(s) == "string" then
        error("Attempt to de-link non-string input.", 2)
    end
    if not ( type(pattern) == "string" and mw.ustring.sub(pattern, 1, 1) == "^" ) then
        error('Invalid pattern detected. Patterns must begin with "^".', 2)
    end
    -- Iterate over the text string, and replace any matched text. using the 
    -- delink function. We need to iterate character by character rather 
    -- than just use gsub, otherwise nested links aren't detected properly.
    local result = ""
    while s ~= '' do
        -- Replace text using one iteration of gsub.
        s = mw.ustring.gsub(s, pattern, delinkFunction, 1)
        -- Append the left-most character to the result string.
        result = result .. mw.ustring.sub(s, 1, 1)
        s = mw.ustring.sub(s, 2, -1)
    end
    return result
end

function p._delink(args)
    local text = args[1] or ""
    if args.refs == "yes" 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 not (args.comments == "no") then
        text = text:gsub("<!%-%-.-%-%->", "") -- Remove html comments.
    end
    if not (args.wikilinks == "no") then
        text = delinkLinkClass(text, "^%[%[.-%]%]", delinkWikilink) -- De-link wikilinks.
    end
    if not (args.urls == "no") then
        text = delinkLinkClass(text, "^%[.-%]", delinkURL) -- De-link URLs.
    end
    if not (args.whitespace == "no") 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 = mw.ustring.gsub(text, "([^\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)
    if not getArgs then
    	getArgs = require('Module:Arguments').getArgs
    end
    return p._delink(getArgs(frame, {wrappers = 'Template:Delink'}))
end

return p