<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-Hans-CN">
	<id>https://www.wikiw.cn/index.php?action=history&amp;feed=atom&amp;title=%E6%A8%A1%E5%9D%97%3ACitation%2FCS1%2FLinks</id>
	<title>模块:Citation/CS1/Links - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="https://www.wikiw.cn/index.php?action=history&amp;feed=atom&amp;title=%E6%A8%A1%E5%9D%97%3ACitation%2FCS1%2FLinks"/>
	<link rel="alternate" type="text/html" href="https://www.wikiw.cn/index.php?title=%E6%A8%A1%E5%9D%97:Citation/CS1/Links&amp;action=history"/>
	<updated>2026-04-08T20:52:36Z</updated>
	<subtitle>本wiki上该页面的版本历史</subtitle>
	<generator>MediaWiki 1.44.0</generator>
	<entry>
		<id>https://www.wikiw.cn/index.php?title=%E6%A8%A1%E5%9D%97:Citation/CS1/Links&amp;diff=2049&amp;oldid=prev</id>
		<title>imported&gt;Antigng：​已保护“Module:Citation/CS1/Links”：​高风险模块（[编辑=仅允许管理员]（无限期）[移动=仅允许管理员]（无限期））</title>
		<link rel="alternate" type="text/html" href="https://www.wikiw.cn/index.php?title=%E6%A8%A1%E5%9D%97:Citation/CS1/Links&amp;diff=2049&amp;oldid=prev"/>
		<updated>2022-04-26T16:36:50Z</updated>

		<summary type="html">&lt;p&gt;已保护“&lt;a href=&quot;/index.php?title=%E6%A8%A1%E5%9D%97:Citation/CS1/Links&quot; title=&quot;模块:Citation/CS1/Links&quot;&gt;Module:Citation/CS1/Links&lt;/a&gt;”：​&lt;a href=&quot;/index.php?title=WP:HRT&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;WP:HRT（页面不存在）&quot;&gt;高风险模块&lt;/a&gt;（[编辑=仅允许管理员]（无限期）[移动=仅允许管理员]（无限期））&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;--[[&lt;br /&gt;
&lt;br /&gt;
本模块用于处理维基内链和外链。目前导出四个函数：&lt;br /&gt;
&lt;br /&gt;
check_for_external_link()用于批量检查参数中可能存在的外链。&lt;br /&gt;
&lt;br /&gt;
make_external_link()依据输入的url参数和&amp;quot;显示&amp;quot;参数输出维基外链，&lt;br /&gt;
并对其中url参数的格式进行检查。若查出url格式不正确，&lt;br /&gt;
在设定&amp;quot;源&amp;quot;参数的情况下，会根据该参数产生&amp;quot;引文格式1错误&amp;quot;信息，&lt;br /&gt;
附于生成的外链后方；如&amp;quot;源&amp;quot;参数未设定，则会抛出内部错误终止程序。&lt;br /&gt;
&lt;br /&gt;
make_internal_link()依据输入的&amp;quot;目标页面&amp;quot;参数和&amp;quot;显示&amp;quot;参数输出维基内链，&lt;br /&gt;
并对其中&amp;quot;目标页面&amp;quot;参数的格式稍加检查。&lt;br /&gt;
若查出&amp;quot;目标页面&amp;quot;格式不正确(例如：含有页面标题中不允许出现的字符)，&lt;br /&gt;
在设定&amp;quot;源&amp;quot;参数的情况下，会根据该参数产生&amp;quot;引文格式1错误&amp;quot;信息，&lt;br /&gt;
该条信息被其它模块处理后会显示于引文的尾部；&lt;br /&gt;
如&amp;quot;源&amp;quot;参数未设定，则会抛出内部错误终止程序。&lt;br /&gt;
&lt;br /&gt;
以上两个函数既可用于处理模板参数，也可用于转换配置模块中的有关参数。&lt;br /&gt;
&lt;br /&gt;
但请注意，用于前者时必须指定&amp;quot;源&amp;quot;参数（即被处理的参数名称）并保证其值有效，&lt;br /&gt;
用于后者时必须确保配置文件模块编写正确。否则将导致Lua错误！&lt;br /&gt;
&lt;br /&gt;
remove_wiki_link()用于移除维基内链。&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; F O R W A R D   D E C L A R A T I O N S &amp;gt;--------------------------------------&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local is_set;&lt;br /&gt;
local append_error, set_error, throw_error;&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; I S _ S C H E M E &amp;gt;------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
does this thing that purports to be a uri scheme seem to be a valid scheme?  The scheme is checked to see if it&lt;br /&gt;
is in agreement with http://tools.ietf.org/html/std66#section-3.1 which says:&lt;br /&gt;
	Scheme names consist of a sequence of characters beginning with a&lt;br /&gt;
   letter and followed by any combination of letters, digits, plus&lt;br /&gt;
   (&amp;quot;+&amp;quot;), period (&amp;quot;.&amp;quot;), or hyphen (&amp;quot;-&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
returns true if it does, else false&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function is_scheme (scheme)&lt;br /&gt;
	return scheme and scheme:match (&amp;#039;^%a[%a%d%+%.%-]*:&amp;#039;);						-- true if scheme is set and matches the pattern&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[=[-------------------------&amp;lt; I S _ D O M A I N _ N A M E &amp;gt;--------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Does this thing that purports to be a domain name seem to be a valid domain name?&lt;br /&gt;
&lt;br /&gt;
Syntax defined here: http://tools.ietf.org/html/rfc1034#section-3.5&lt;br /&gt;
BNF defined here: https://tools.ietf.org/html/rfc4234&lt;br /&gt;
Single character names are generally reserved; see https://tools.ietf.org/html/draft-ietf-dnsind-iana-dns-01#page-15;&lt;br /&gt;
	see also [[Single-letter second-level domain]]&lt;br /&gt;
list of tlds: https://www.iana.org/domains/root/db&lt;br /&gt;
&lt;br /&gt;
rfc952 (modified by rfc 1123) requires the first and last character of a hostname to be a letter or a digit.  Between&lt;br /&gt;
the first and last characters the name may use letters, digits, and the hyphen.&lt;br /&gt;
&lt;br /&gt;
Also allowed are IPv4 addresses. IPv6 not supported&lt;br /&gt;
&lt;br /&gt;
domain is expected to be stripped of any path so that the last character in the last character of the tld.  tld&lt;br /&gt;
is two or more alpha characters.  Any preceding &amp;#039;//&amp;#039; (from splitting a url with a scheme) will be stripped&lt;br /&gt;
here.  Perhaps not necessary but retained incase it is necessary for IPv4 dot decimal.&lt;br /&gt;
&lt;br /&gt;
There are several tests:&lt;br /&gt;
	the first character of the whole domain name including subdomains must be a letter or a digit&lt;br /&gt;
	single-letter/digit second-level domains in the .org TLD&lt;br /&gt;
	q, x, and z SL domains in the .com TLD&lt;br /&gt;
	i and q SL domains in the .net TLD&lt;br /&gt;
	single-letter SL domains in the ccTLDs (where the ccTLD is two letters)&lt;br /&gt;
	two-character SL domains in gTLDs (where the gTLD is two or more letters)&lt;br /&gt;
	three-plus-character SL domains in gTLDs (where the gTLD is two or more letters)&lt;br /&gt;
	IPv4 dot-decimal address format; TLD not allowed&lt;br /&gt;
&lt;br /&gt;
returns true if domain appears to be a proper name and tld or IPv4 address, else false&lt;br /&gt;
&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local function is_domain_name (domain)&lt;br /&gt;
	if not domain then&lt;br /&gt;
		return false;															-- if not set, abandon&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	domain = domain:gsub (&amp;#039;^//&amp;#039;, &amp;#039;&amp;#039;);											-- strip &amp;#039;//&amp;#039; from domain name if present; done here so we only have to do it once&lt;br /&gt;
	&lt;br /&gt;
	if not domain:match (&amp;#039;^[%a%d]&amp;#039;) then										-- first character must be letter or digit&lt;br /&gt;
		return false;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if domain:match (&amp;#039;%f[%a%d][%a%d]%.org$&amp;#039;) then								-- one character .org hostname&lt;br /&gt;
		return true;&lt;br /&gt;
	elseif domain:match (&amp;#039;%f[%a][qxz]%.com$&amp;#039;) then								-- assigned one character .com hostname (x.com times out 2015-12-10)&lt;br /&gt;
		return true;&lt;br /&gt;
	elseif domain:match (&amp;#039;%f[%a][iq]%.net$&amp;#039;) then								-- assigned one character .net hostname (q.net registered but not active 2015-12-10)&lt;br /&gt;
		return true;&lt;br /&gt;
	elseif domain:match (&amp;#039;%f[%a%d][%a%d][%a%d%-]+[%a%d]%.xn%-%-[%a%d]+$&amp;#039;) then	-- internationalized domain name with ACE prefix&lt;br /&gt;
		return true;&lt;br /&gt;
	elseif domain:match (&amp;#039;%f[%a%d][%a%d]%.cash$&amp;#039;) then							-- one character/digit .cash hostname&lt;br /&gt;
		return true;&lt;br /&gt;
	elseif domain:match (&amp;#039;%f[%a%d][%a%d]%.%a%a$&amp;#039;) then							-- one character hostname and cctld (2 chars)&lt;br /&gt;
		return true;&lt;br /&gt;
	elseif domain:match (&amp;#039;%f[%a%d][%a%d][%a%d]%.%a%a+$&amp;#039;) then					-- two character hostname and tld&lt;br /&gt;
		return true;&lt;br /&gt;
	elseif domain:match (&amp;#039;%f[%a%d][%a%d][%a%d%-]+[%a%d]%.%a%a+$&amp;#039;) then			-- three or more character hostname.hostname or hostname.tld&lt;br /&gt;
		return true;&lt;br /&gt;
	elseif domain:match (&amp;#039;^%d%d?%d?%.%d%d?%d?%.%d%d?%d?%.%d%d?%d?&amp;#039;) then		-- IPv4 address&lt;br /&gt;
		return true;&lt;br /&gt;
	else&lt;br /&gt;
		return false;&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; I S _ U R L &amp;gt;------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
returns true if the scheme and domain parts of a url appear to be a valid url; else false.&lt;br /&gt;
&lt;br /&gt;
This function is the last step in the validation process.  This function is separate because there are cases that&lt;br /&gt;
are not covered by split_url(), for example is_parameter_ext_wikilink() which is looking for bracketted external&lt;br /&gt;
wikilinks.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function is_url (scheme, domain)&lt;br /&gt;
	if is_set (scheme) then														-- if scheme is set check it and domain&lt;br /&gt;
		return is_scheme (scheme) and is_domain_name (domain);&lt;br /&gt;
	else&lt;br /&gt;
		return is_domain_name (domain);											-- scheme not set when url is protocol relative&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S P L I T _ U R L &amp;gt;------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Split a url into a scheme, authority indicator, and domain.&lt;br /&gt;
If protocol relative url, return nil scheme and domain else return nil for both scheme and domain.&lt;br /&gt;
&lt;br /&gt;
When not protocol relative, get scheme, authority indicator, and domain.  If there is an authority indicator (one&lt;br /&gt;
or more &amp;#039;/&amp;#039; characters following the scheme&amp;#039;s colon), make sure that there are only 2.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function split_url (url_str)&lt;br /&gt;
	local scheme, authority, domain;&lt;br /&gt;
	&lt;br /&gt;
	url_str = url_str:gsub (&amp;#039;([%a%d])%.?[/%?#].*$&amp;#039;, &amp;#039;%1&amp;#039;);						-- strip FQDN terminator and path(/), query(?), fragment (#) (the capture prevents false replacement of &amp;#039;//&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
	if url_str:match (&amp;#039;^//%S*&amp;#039;) then											-- if there is what appears to be a protocol relative url&lt;br /&gt;
		domain = url_str:match (&amp;#039;^//(%S*)&amp;#039;)&lt;br /&gt;
	elseif url_str:match (&amp;#039;%S-:/*%S+&amp;#039;) then										-- if there is what appears to be a scheme, optional authority indicator, and domain name&lt;br /&gt;
		scheme, authority, domain = url_str:match (&amp;#039;(%S-:)(/*)(%S+)&amp;#039;);			-- extract the scheme, authority indicator, and domain portions&lt;br /&gt;
		authority = authority:gsub (&amp;#039;//&amp;#039;, &amp;#039;&amp;#039;, 1);								-- replace place 1 pair of &amp;#039;/&amp;#039; with nothing;&lt;br /&gt;
		if is_set(authority) then												-- if anything left (1 or 3+ &amp;#039;/&amp;#039; where authority should be) then&lt;br /&gt;
			return scheme;														-- return scheme only making domain nil which will cause an error message&lt;br /&gt;
		end&lt;br /&gt;
		domain = domain:gsub (&amp;#039;(%a):%d+&amp;#039;, &amp;#039;%1&amp;#039;);								-- strip port number if present&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return scheme, domain;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; L I N K _ P A R A M _ O K &amp;gt;---------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
checks the content of |title-link=, |series-link=, |author-link= etc for properly formatted content: no wikilinks, no urls&lt;br /&gt;
&lt;br /&gt;
Link parameters are to hold the title of a wikipedia article so none of the WP:TITLESPECIALCHARACTERS are allowed:&lt;br /&gt;
	# &amp;lt; &amp;gt; [ ] | { } _&lt;br /&gt;
except the underscore which is used as a space in wiki urls and # which is used for section links&lt;br /&gt;
&lt;br /&gt;
returns false when the value contains any of these characters.&lt;br /&gt;
&lt;br /&gt;
When there are no illegal characters, this function returns TRUE if value DOES NOT appear to be a valid url (the&lt;br /&gt;
|&amp;lt;param&amp;gt;-link= parameter is ok); else false when value appears to be a valid url (the |&amp;lt;param&amp;gt;-link= parameter is NOT ok).&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function link_param_ok (value)&lt;br /&gt;
	local scheme, domain;&lt;br /&gt;
	if value:find (&amp;#039;[&amp;lt;&amp;gt;%[%]|{}]&amp;#039;) then											-- if any prohibited characters&lt;br /&gt;
		return false;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	scheme, domain = split_url (value);											-- get scheme or nil and domain or nil from url; &lt;br /&gt;
	return not is_url (scheme, domain);											-- return true if value DOES NOT appear to be a valid url&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[=[-------------------------&amp;lt; M A K E _ I N T E R N A L _ L I N K &amp;gt;------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Format a wikilink with error checking; when both link and display text is provided, returns a wikilink in the form [[L|D]]; if only&lt;br /&gt;
link is provided (or link and display are the same), returns a wikilink in the form [[L]].&lt;br /&gt;
&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local function make_internal_link (link, display, source)&lt;br /&gt;
	if not link_param_ok (link) then&lt;br /&gt;
		if is_set (source) then&lt;br /&gt;
			append_error (&amp;#039;bad_paramlink&amp;#039;, {source});&lt;br /&gt;
		else&lt;br /&gt;
			throw_error(&amp;#039;bad_link_no_origin&amp;#039;);&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if is_set (display) and link ~= display then			&lt;br /&gt;
		return table.concat ({&amp;#039;[[&amp;#039;, link, &amp;#039;|&amp;#039;, display, &amp;#039;]]&amp;#039;});			&lt;br /&gt;
	else&lt;br /&gt;
		return table.concat ({&amp;#039;[[&amp;#039;, link, &amp;#039;]]&amp;#039;});&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[=[-------------------------&amp;lt; R E M O V E _ W I K I _ L I N K &amp;gt;----------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Gets the display text from a wikilink like [[A|B]] or [[B]] gives B&lt;br /&gt;
&lt;br /&gt;
The str:gsub() returns either A|B froma [[A|B]] or B from [[B]] or B from B (no wikilink markup).&lt;br /&gt;
&lt;br /&gt;
In l(), l:gsub() removes the link and pipe (if they exist); the second :gsub() trims whitespace from the label&lt;br /&gt;
if str was wrapped in wikilink markup.  Presumably, this is because without wikimarkup in str, there is no match&lt;br /&gt;
in the initial gsub, the replacement function l() doesn&amp;#039;t get called.&lt;br /&gt;
&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local function remove_wiki_link (str)&lt;br /&gt;
	return (str:gsub (&amp;quot;%[%[([^%[%]]*)%]%]&amp;quot;, function(l)&lt;br /&gt;
		return l:gsub (&amp;quot;^[^|]*|(.*)$&amp;quot;, &amp;quot;%1&amp;quot; ):gsub (&amp;quot;^%s*(.-)%s*$&amp;quot;, &amp;quot;%1&amp;quot;);&lt;br /&gt;
	end));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[=[-------------------------&amp;lt; I S _ W I K I L I N K &amp;gt;--------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Determines if str is a wikilink, extracts, and returns the wikilink type, link text, and display text parts.&lt;br /&gt;
If str is a complex wikilink ([[L|D]]):&lt;br /&gt;
	returns wl_type 2 and D and L from [[L|D]];&lt;br /&gt;
if str is a simple wikilink ([[D]])&lt;br /&gt;
	returns wl_type 1 and D from [[D]] and L as empty string;&lt;br /&gt;
if not a wikilink:&lt;br /&gt;
	returns wl_type 0, str as D, and L as empty string.&lt;br /&gt;
&lt;br /&gt;
trims leading and trailing whitespace and pipes from L and D ([[L|]] and [[|D]] are accepted by MediaWiki and&lt;br /&gt;
treated like [[D]]; while [[|D|]] is not accepted by MediaWiki, here, we accept it and return D without the pipes).&lt;br /&gt;
&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local function is_wikilink (str)&lt;br /&gt;
	local D, L&lt;br /&gt;
	local wl_type = 2;															-- assume that str is a complex wikilink [[L|D]]&lt;br /&gt;
&lt;br /&gt;
	if not str:match (&amp;#039;^%[%[[^%]]+%]%]$&amp;#039;) then									-- is str some sort of a wikilink (must have some sort of content)&lt;br /&gt;
		return 0, str, &amp;#039;&amp;#039;;														-- not a wikilink; return wl_type as 0, str as D, and empty string as L&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	L, D = str:match (&amp;#039;^%[%[([^|]+)|([^%]]+)%]%]$&amp;#039;);							-- get L and D from [[L|D]] &lt;br /&gt;
&lt;br /&gt;
	if not is_set (D) then														-- if no separate display&lt;br /&gt;
		D = str:match (&amp;#039;^%[%[([^%]]*)|*%]%]$&amp;#039;);									-- get D from [[D]] or [[D|]]&lt;br /&gt;
		wl_type = 1; &lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	D = mw.text.trim (D, &amp;#039;%s|&amp;#039;);												-- trim white space and pipe characters &lt;br /&gt;
	return wl_type, D, L or &amp;#039;&amp;#039;;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S A F E _ F O R _ U R L &amp;gt;------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Escape sequences for content that will be used for URL descriptions&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function safe_for_url( str )&lt;br /&gt;
	if str:match( &amp;quot;%[%[.-%]%]&amp;quot; ) ~= nil then &lt;br /&gt;
		append_error( &amp;#039;wikilink_in_url&amp;#039;, {});&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return str:gsub( &amp;#039;[%[%]\n]&amp;#039;, {	&lt;br /&gt;
		[&amp;#039;[&amp;#039;] = &amp;#039;&amp;amp;#91;&amp;#039;,&lt;br /&gt;
		[&amp;#039;]&amp;#039;] = &amp;#039;&amp;amp;#93;&amp;#039;,&lt;br /&gt;
		[&amp;#039;\n&amp;#039;] = &amp;#039; &amp;#039; } );&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; C H E C K _ U R L &amp;gt;------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Determines whether a URL string appears to be valid.&lt;br /&gt;
&lt;br /&gt;
First we test for space characters.  If any are found, return false.  Then split the url into scheme and domain&lt;br /&gt;
portions, or for protocol relative (//example.com) urls, just the domain.  Use is_url() to validate the two&lt;br /&gt;
portions of the url.  If both are valid, or for protocol relative if domain is valid, return true, else false.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function check_url( url_str )&lt;br /&gt;
	if nil == url_str:match (&amp;quot;^%S+$&amp;quot;) then										-- if there are any spaces in |url=value it can&amp;#039;t be a proper url&lt;br /&gt;
		return false;&lt;br /&gt;
	end&lt;br /&gt;
	local scheme, domain;&lt;br /&gt;
&lt;br /&gt;
	scheme, domain = split_url (url_str);										-- get scheme or nil and domain or nil from url; &lt;br /&gt;
	return is_url (scheme, domain);												-- return true if value appears to be a valid url&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; M A K E _ E X T E R N A L _ L I N K &amp;gt;--------------------------------------------&lt;br /&gt;
&lt;br /&gt;
Format an external link with error checking&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function make_external_link( URL, label, source )&lt;br /&gt;
	local error_str = &amp;quot;&amp;quot;;&lt;br /&gt;
	if not is_set( label ) then&lt;br /&gt;
		label = URL;&lt;br /&gt;
		if is_set( source ) then&lt;br /&gt;
			error_str = set_error( &amp;#039;bare_url_missing_title&amp;#039;, source, false, &amp;quot; &amp;quot; );&lt;br /&gt;
		else&lt;br /&gt;
			throw_error( &amp;#039;bare_url_no_origin&amp;#039; );&lt;br /&gt;
		end			&lt;br /&gt;
	end&lt;br /&gt;
	if not check_url( URL ) then&lt;br /&gt;
		if is_set ( source ) then&lt;br /&gt;
			error_str = set_error( &amp;#039;bad_url&amp;#039;, source, false, &amp;quot; &amp;quot; ) .. error_str;&lt;br /&gt;
		else&lt;br /&gt;
			throw_error( &amp;#039;bad_url_no_origin&amp;#039; );&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return table.concat({ &amp;quot;[&amp;quot;, URL, &amp;quot; &amp;quot;, safe_for_url( label ), &amp;quot;]&amp;quot;, error_str });&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[=[-------------------------&amp;lt; I S _ P A R A M E T E R _ E X T _ W I K I L I N K &amp;gt;----------------------------&lt;br /&gt;
&lt;br /&gt;
Return true if a parameter value has a string that begins and ends with square brackets [ and ] and the first&lt;br /&gt;
non-space characters following the opening bracket appear to be a url.  The test will also find external wikilinks&lt;br /&gt;
that use protocol relative urls. Also finds bare urls.&lt;br /&gt;
&lt;br /&gt;
The frontier pattern prevents a match on interwiki links which are similar to scheme:path urls.  The tests that&lt;br /&gt;
find bracketed urls are required because the parameters that call this test (currently |title=, |chapter=, |work=,&lt;br /&gt;
and |publisher=) may have wikilinks and there are articles or redirects like &amp;#039;//Hus&amp;#039; so, while uncommon, |title=[[//Hus]]&lt;br /&gt;
is possible as might be [[en://Hus]].&lt;br /&gt;
&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local function is_parameter_ext_wikilink (value)&lt;br /&gt;
local scheme, domain;&lt;br /&gt;
&lt;br /&gt;
	value = value:gsub (&amp;#039;([^%s/])/[%a%d].*&amp;#039;, &amp;#039;%1&amp;#039;);								-- strip path information (the capture prevents false replacement of &amp;#039;//&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
	if value:match (&amp;#039;%f[%[]%[%a%S*:%S+.*%]&amp;#039;) then								-- if ext wikilink with scheme and domain: [xxxx://yyyyy.zzz]&lt;br /&gt;
		scheme, domain = value:match (&amp;#039;%f[%[]%[(%a%S*:)(%S+).*%]&amp;#039;)&lt;br /&gt;
	elseif value:match (&amp;#039;%f[%[]%[//%S*%.%S+.*%]&amp;#039;) then							-- if protocol relative ext wikilink: [//yyyyy.zzz]&lt;br /&gt;
		domain = value:match (&amp;#039;%f[%[]%[//(%S*%.%S+).*%]&amp;#039;);&lt;br /&gt;
	elseif value:match (&amp;#039;%a%S*:%S+&amp;#039;) then										-- if bare url with scheme; may have leading or trailing plain text&lt;br /&gt;
		scheme, domain = value:match (&amp;#039;(%a%S*:)(%S+)&amp;#039;);&lt;br /&gt;
	elseif value:match (&amp;#039;//%S*%.%S+&amp;#039;) then										-- if protocol relative bare url: //yyyyy.zzz; may have leading or trailing plain text&lt;br /&gt;
		domain = value:match (&amp;#039;//(%S*%.%S+)&amp;#039;);									-- what is left should be the domain&lt;br /&gt;
	else&lt;br /&gt;
		return false;															-- didn&amp;#039;t find anything that is obviously a url&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return is_url (scheme, domain);												-- return true if value appears to be a valid url&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--[[-------------------------&amp;lt; C H E C K _ F O R _ U R L &amp;gt;-----------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
loop through a list of parameters and their values.  Look at the value and if it has an external link, emit an error message.&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function check_for_external_link (parameter_list)&lt;br /&gt;
local error_message = &amp;#039;&amp;#039;;&lt;br /&gt;
	for k, v in pairs (parameter_list) do										-- for each parameter in the list&lt;br /&gt;
		if is_parameter_ext_wikilink (v) then									-- look at the value; if there is a url add an error message&lt;br /&gt;
			if is_set(error_message) then										-- once we&amp;#039;ve added the first portion of the error message ...&lt;br /&gt;
				error_message=error_message .. &amp;quot;, &amp;quot;;							-- ... add a comma space separator&lt;br /&gt;
			end&lt;br /&gt;
			error_message=error_message .. &amp;quot;&amp;amp;#124;&amp;quot; .. k .. &amp;quot;=&amp;quot;;				-- add the failed parameter&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if is_set (error_message) then												-- done looping, if there is an error message, display it&lt;br /&gt;
		append_error( &amp;#039;param_has_ext_link&amp;#039;, {error_message});&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; S E T _ S E L E C T E D _ M O D U L E S &amp;gt;--------------------------------------&lt;br /&gt;
&lt;br /&gt;
Import some functions from Module:Citation/CS1/Utilities and Module:Citation/CS1/Error&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local function set_selected_modules (utilities_page_ptr, error_page_ptr)&lt;br /&gt;
	is_set = utilities_page_ptr.is_set;&lt;br /&gt;
	&lt;br /&gt;
	append_error = error_page_ptr.append_error;&lt;br /&gt;
	set_error = error_page_ptr.set_error;&lt;br /&gt;
	throw_error = error_page_ptr.throw_error;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[--------------------------&amp;lt; E X P O R T E D   F U N C T I O N S &amp;gt;------------------------------------------&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
return {&lt;br /&gt;
	check_for_external_link = check_for_external_link,							-- exported functions&lt;br /&gt;
	make_external_link = make_external_link,&lt;br /&gt;
	make_internal_link = make_internal_link,&lt;br /&gt;
	remove_wiki_link = remove_wiki_link,&lt;br /&gt;
	&lt;br /&gt;
	set_selected_modules = set_selected_modules&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>imported&gt;Antigng</name></author>
	</entry>
</feed>