Theme: iWiki Log in Register

Diff: Module:URL

Comparing revision #1 (2022-09-11 18:55:11) with revision #2 (2023-02-03 04:17:57).

OldNew
--
--
-- This module implements {{URL}}
-- This module implements {{URL}}
--
--
-- See unit tests at [[Module:URL/testcases]]
-- See unit tests at [[Module:URL/testcases]]
local p = {}
local p = {}
 
 
local function safeUri(s)
local function safeUri(s)
	local success, uri = pcall(function()
	local success, uri = pcall(function()
		return mw.uri.new(s)
		return mw.uri.new(s)
	end)
	end)
	if success then
	if success then
		return uri
		return uri
	end
	end
end
end
local function extractUrl(args)
local function extractUrl(args)
	for name, val in pairs(args) do
	for name, val in pairs(args) do
		if name ~= 2 and name ~= "msg" then
		if name ~= 2 and name ~= "msg" then
			local url = name .. "=" .. val;
			local url = name .. "=" .. val;
			url = mw.ustring.gsub(url, '^[Hh][Tt][Tt][Pp]([Ss]?):(/?)([^/])', 'http%1://%3')
			url = mw.ustring.gsub(url, '^[Hh][Tt][Tt][Pp]([Ss]?):(/?)([^/])', 'http%1://%3')
			local uri = safeUri(url);
			local uri = safeUri(url);
			if uri and uri.host then
			if uri and uri.host then
				return url
				return url
			end
			end
		end
		end
	end
	end
end
end
function p._url(url, text, msg)
function p._url(url, text, msg)
	url = mw.text.trim(url or '')
	url = mw.text.trim(url or '')
	text = mw.text.trim(text or '')
	text = mw.text.trim(text or '')
	local nomsg = (msg or ''):sub(1,1):lower() == "n" or msg == 'false' -- boolean: true if msg is "false" or starts with n or N
	local nomsg = (msg or ''):sub(1,1):lower() == "n" or msg == 'false' -- boolean: true if msg is "false" or starts with n or N
	if url == '' then
	if url == '' then
		if text == '' then
		if text == '' then
			if nomsg then
			if nomsg then
				return nil
				return nil
			else
			else
				return mw.getCurrentFrame():expandTemplate{ title = 'tlx', args = { 'URL', "''example.com''", "''optional display text''" } }
				return mw.getCurrentFrame():expandTemplate{ title = 'tlx', args = { 'URL', "''example.com''", "''optional display text''" } }
			end
			end
		else
		else
			return text
			return text
		end
		end
	end
	end
	-- If the URL contains any unencoded spaces, encode them, because MediaWiki will otherwise interpret a space as the end of the URL.
	-- If the URL contains any unencoded spaces, encode them, because MediaWiki will otherwise interpret a space as the end of the URL.
	url = mw.ustring.gsub(url, '%s', function(s) return mw.uri.encode(s, 'PATH') end)
	url = mw.ustring.gsub(url, '%s', function(s) return mw.uri.encode(s, 'PATH') end)
	-- If there is an empty query string or fragment id, remove it as it will cause mw.uri.new to throw an error
	-- If there is an empty query string or fragment id, remove it as it will cause mw.uri.new to throw an error
	url = mw.ustring.gsub(url, '#$', '')
	url = mw.ustring.gsub(url, '#$', '')
	url = mw.ustring.gsub(url, '%?$', '')
	url = mw.ustring.gsub(url, '%?$', '')
	-- If it's an HTTP[S] URL without the double slash, fix it.
	-- If it's an HTTP[S] URL without the double slash, fix it.
	url = mw.ustring.gsub(url, '^[Hh][Tt][Tt][Pp]([Ss]?):(/?)([^/])', 'http%1://%3')
	url = mw.ustring.gsub(url, '^[Hh][Tt][Tt][Pp]([Ss]?):(/?)([^/])', 'http%1://%3')
	local uri = safeUri(url)
	local uri = safeUri(url)
	-- Handle URL's without a protocol and URL's that are protocol-relative, 
	-- Handle URL's without a protocol and URL's that are protocol-relative, 
	-- e.g. www.example.com/foo or www.example.com:8080/foo, and //www.example.com/foo
	-- e.g. www.example.com/foo or www.example.com:8080/foo, and //www.example.com/foo
	if uri and (not uri.protocol or (uri.protocol and not uri.host)) and url:sub(1, 2) ~= '//' then
	if uri and (not uri.protocol or (uri.protocol and not uri.host)) and url:sub(1, 2) ~= '//' then
		url = 'http://' .. url
		url = 'http://' .. url
		uri = safeUri(url)
		uri = safeUri(url)
	end
	end
	if text == '' then
	if text == '' then
		if uri then
		if uri then
			if uri.path == '/' then uri.path = '' end
			if uri.path == '/' then uri.path = '' end
			local port = ''
			local port = ''
			if uri.port then port = ':' .. uri.port end
			if uri.port then port = ':' .. uri.port end
			text = mw.ustring.lower(uri.host or '') .. port .. (uri.relativePath or '')
			text = mw.ustring.lower(uri.host or '') .. port .. (uri.relativePath or '')
			-- Add <wbr> before _/.-# sequences
			-- Add <wbr> before _/.-# sequences
			text = mw.ustring.gsub(text,"(/+)","<wbr/>%1")      -- This entry MUST be the first. "<wbr/>" has a "/" in it, you know.
			text = mw.ustring.gsub(text,"(/+)","<wbr/>%1")      -- This entry MUST be the first. "<wbr/>" has a "/" in it, you know.
			text = mw.ustring.gsub(text,"(%.+)","<wbr/>%1")
			text = mw.ustring.gsub(text,"(%.+)","<wbr/>%1")
			-- text = mw.ustring.gsub(text,"(%-+)","<wbr/>%1") 	-- DISABLED for now
			-- text = mw.ustring.gsub(text,"(%-+)","<wbr/>%1") 	-- DISABLED for now
			text = mw.ustring.gsub(text,"(%#+)","<wbr/>%1")
			text = mw.ustring.gsub(text,"(%#+)","<wbr/>%1")
			text = mw.ustring.gsub(text,"(_+)","<wbr/>%1")
			text = mw.ustring.gsub(text,"(_+)","<wbr/>%1")
		else -- URL is badly-formed, so just display whatever was passed in
		else -- URL is badly-formed, so just display whatever was passed in
			text = url
			text = url
		end
		end
	end
	end
	return mw.ustring.format('<span class="url">[%s %s]</span>', url, text)
	return mw.ustring.format('<span class="url">[%s %s]</span>', url, text)
end
end
--[[
--[[
The main entry point for calling from Template:URL.
The main entry point for calling from Template:URL.
--]]
--]]
function p.url(frame)
function p.url(frame)
	local templateArgs = frame.args
	local templateArgs = frame.args
	local parentArgs = frame:getParent().args
	local parentArgs = frame:getParent().args
	local url = templateArgs[1] or parentArgs[1]
	local url = templateArgs[1] or parentArgs[1]
	local text = templateArgs[2] or parentArgs[2] or ''
	local text = templateArgs[2] or parentArgs[2] or ''
	local msg = templateArgs.msg or parentArgs.msg or ''
	local msg = templateArgs.msg or parentArgs.msg or ''
	url = url or extractUrl(templateArgs) or extractUrl(parentArgs) or ''
	url = url or extractUrl(templateArgs) or extractUrl(parentArgs) or ''
	return p._url(url, text, msg)
	return p._url(url, text, msg)
end
end
--[[
--[[
The entry point for calling from the forked Template:URL2.
The entry point for calling from the forked Template:URL2.
This function returns no message by default.
This function returns no message by default.
It strips out wiki-link markup, html tags, and everything after a space.
It strips out wiki-link markup, html tags, and everything after a space.
--]]
--]]
function p.url2(frame)
function p.url2(frame)
	local templateArgs = frame.args
	local templateArgs = frame.args
	local parentArgs = frame:getParent().args
	local parentArgs = frame:getParent().args
	local url = templateArgs[1] or parentArgs[1]
	local url = templateArgs[1] or parentArgs[1]
	local text = templateArgs[2] or parentArgs[2] or ''
	local text = templateArgs[2] or parentArgs[2] or ''
	-- default to no message
	-- default to no message
	local msg = templateArgs.msg or parentArgs.msg or 'no'
	local msg = templateArgs.msg or parentArgs.msg or 'no'
	url = url or extractUrl(templateArgs) or extractUrl(parentArgs) or ''
	url = url or extractUrl(templateArgs) or extractUrl(parentArgs) or ''
	-- if the url came from a Wikidata call, it might have a pen icon appended
	-- if the url came from a Wikidata call, it might have a pen icon appended
	-- we want to keep that and add it back at the end.
	-- we want to keep that and add it back at the end.
	local u1, penicon = mw.ustring.match( url, "(.*)(&nbsp;<span class='penicon.*)" )
	local u1, penicon = mw.ustring.match( url, "(.*)(&nbsp;<span class='penicon.*)" )
	if penicon then url = u1 end
	if penicon then url = u1 end
	-- strip out html tags and [ ] from url
	-- strip out html tags and [ ] from url
	url = (url or ''):gsub("<[^>]*>", ""):gsub("[%[%]]", "")
	url = (url or ''):gsub("<[^>]*>", ""):gsub("[%[%]]", "")
	-- truncate anything after a space
	-- truncate anything after a space
	url = url:gsub("%%20", " "):gsub(" .*", "")
	url = url:gsub("%%20", " "):gsub(" .*", "")
	return (p._url(url, text, msg) or "") .. (penicon or "")
	return (p._url(url, text, msg) or "") .. (penicon or "")
end
end
return p
return p