Module:Delink/testcases: Difference between revisions
Appearance
Content deleted Content added
OliverGalvin (talk | contribs) Another test case for HTML breaks |
Masoud.h1368 (talk | contribs) 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 |
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 |
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 |
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:�Template:title#Fragment]]', '[[wikt:es:asdf:�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 |
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&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%bar]]', '[[foo%bar]]'}, |
|||
-- Append the left-most character to the result string. |
|||
{ '[[foo%62bar]]', '[[foo%62bar]]'}, |
|||
result = result .. mw.ustring.sub(s, 1, 1) |
|||
{ '[[foo�bar]]', '[[foo�bar]]'}, |
|||
s = mw.ustring.sub(s, 2, -1) |
|||
{ '[[foo�bar]]', '[[foo�bar]]'}, |
|||
end |
|||
{ '[[foo"bar]]', 'foo"bar'}, |
|||
return result |
|||
{ '[[foo"bar]]', 'foo"bar'}, |
|||
{ '[[foo&amp;bar]]', '[[foo&amp;bar]]'}, |
|||
}, {nowiki='yes'}) |
|||
end |
end |
||
function p |
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&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%bar]', 'foo%bar'}, |
|||
text = delinkLinkClass(text, "^%[.-%]", delinkURL) -- De-link URLs. |
|||
{ '[http://www.example.com foo%62bar]', 'foo%62bar'}, |
|||
end |
|||
{ '[http://www.example.com foo�bar]', 'foo�bar'}, |
|||
if not (args.whitespace == "no") then |
|||
{ '[http://www.example.com foo�bar]', 'foo�bar'}, |
|||
-- Replace single new lines with a single space, but leave double new lines |
|||
{ '[http://www.example.com foo"bar]', 'foo"bar'}, |
|||
-- and new lines only containing spaces or tabs before a second new line. |
|||
{ '[http://www.example.com foo"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 |
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 is the test cases page for the module Module:Delink. Results of the test cases. |
-- 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