<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://afropedia.world/index.php?action=history&amp;feed=atom&amp;title=Module%3AAnnotated_link</id>
	<title>Module:Annotated link - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://afropedia.world/index.php?action=history&amp;feed=atom&amp;title=Module%3AAnnotated_link"/>
	<link rel="alternate" type="text/html" href="https://afropedia.world/index.php?title=Module:Annotated_link&amp;action=history"/>
	<updated>2026-04-04T12:07:56Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.45.1</generator>
	<entry>
		<id>https://afropedia.world/index.php?title=Module:Annotated_link&amp;diff=619&amp;oldid=prev</id>
		<title>Djehuti: 1 revision imported</title>
		<link rel="alternate" type="text/html" href="https://afropedia.world/index.php?title=Module:Annotated_link&amp;diff=619&amp;oldid=prev"/>
		<updated>2024-05-31T19:50:06Z</updated>

		<summary type="html">&lt;p&gt;1 revision imported&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&lt;br /&gt;
local function pipedLink(name, display) return &amp;#039;[[:&amp;#039;..name..&amp;#039;|&amp;#039;..display..&amp;#039;]]&amp;#039; end&lt;br /&gt;
&lt;br /&gt;
local function isEmpty(value) return value == nil or value == &amp;#039;&amp;#039; end&lt;br /&gt;
&lt;br /&gt;
local function notEmpty(value) return not isEmpty(value) end&lt;br /&gt;
&lt;br /&gt;
-- Unescape functionality grabbed from https://stackoverflow.com/a/14899740/1832568&lt;br /&gt;
local function unescape(str)&lt;br /&gt;
	str = string.gsub(str, &amp;#039;&amp;amp;#(%d+);&amp;#039;, string.char)&lt;br /&gt;
	str = string.gsub(str, &amp;#039;&amp;amp;#x(%d+);&amp;#039;, function(d) return string.char(tonumber(d, 16)) end)&lt;br /&gt;
	return str&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function hashDelimitedList(list_string) return mw.text.gsplit(unescape(list_string), &amp;#039;%s*#%s*&amp;#039;) end&lt;br /&gt;
&lt;br /&gt;
local function alarmingMessage(message)&lt;br /&gt;
	return &amp;#039;&amp;lt;span style=&amp;quot;color:#d33&amp;quot;&amp;gt;[[Module:Annotated link]] &amp;#039;..message..&amp;#039;.&amp;lt;/span&amp;gt;&amp;#039;..&lt;br /&gt;
		&amp;#039;[[Category:Pages displaying alarming messages about Module:Annotated link]]&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function optionallyVisibleCategory(class, category)&lt;br /&gt;
	return &amp;#039;&amp;lt;span style=&amp;quot;display:none&amp;quot; class=&amp;quot;&amp;#039;..class..&amp;#039;&amp;quot;&amp;gt;&amp;#039;..category..&lt;br /&gt;
		&amp;#039;&amp;lt;/span&amp;gt;[[Category:&amp;#039;..category..&amp;#039; via Module:Annotated link]]&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function handleFirstLetterCase(short_description, case)&lt;br /&gt;
	return mw.ustring.gsub(short_description, &amp;#039;^([^%d])&amp;#039;, function(first_char)&lt;br /&gt;
		if case == &amp;#039;upper&amp;#039; then&lt;br /&gt;
			return mw.ustring.upper(first_char)&lt;br /&gt;
		end&lt;br /&gt;
		return mw.ustring.lower(first_char) end&lt;br /&gt;
	)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local mLang = require(&amp;#039;Module:Lang&amp;#039;)&lt;br /&gt;
local function langify(args)&lt;br /&gt;
	local lang = args.lang&lt;br /&gt;
	local text = args.text&lt;br /&gt;
	if isEmpty(lang) or lang == &amp;#039;en&amp;#039; then&lt;br /&gt;
		return text&lt;br /&gt;
	end&lt;br /&gt;
	return mLang._lang {&lt;br /&gt;
		lang,&lt;br /&gt;
		text,&lt;br /&gt;
		italic = args.italic,&lt;br /&gt;
		nocat = args.nocat,&lt;br /&gt;
		size = args.size,&lt;br /&gt;
		cat = args.cat,&lt;br /&gt;
		rtl = args.rtl&lt;br /&gt;
	}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function formatResult(result, dash, description, prefix_parentheses)&lt;br /&gt;
	if notEmpty(description) then&lt;br /&gt;
		if prefix_parentheses then&lt;br /&gt;
			local startIdx = description:find(&amp;quot;%(&amp;quot;)&lt;br /&gt;
			if startIdx then&lt;br /&gt;
				 local beforeParens = description:sub(1, startIdx - 2)&lt;br /&gt;
				 local insideParens = description:sub(startIdx, -1)&lt;br /&gt;
				 return result..&amp;#039; &amp;#039;..insideParens..dash..&amp;#039; &amp;#039;..beforeParens&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		return result..dash..&amp;#039; &amp;#039;..description&lt;br /&gt;
	end&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function annotatedLink(args)&lt;br /&gt;
	local name = args.name&lt;br /&gt;
	if isEmpty(name) then&lt;br /&gt;
		return alarmingMessage(&amp;#039;requires a page name (including namespace)&amp;#039;)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- In order to handle an attempt to annotate a template link&lt;br /&gt;
	-- already formatted with the likes of {{tl|&amp;lt;template name&amp;gt;}};&lt;br /&gt;
	-- unescape name to make sense of braces in lua patern matching.&lt;br /&gt;
	name = unescape(name)&lt;br /&gt;
	&lt;br /&gt;
	if name:match(&amp;#039;^{%b{}}$&amp;#039;) then&lt;br /&gt;
		-- The possibility to extract useful data exists here: e.g. {{tl*|Template}}.&lt;br /&gt;
		return alarmingMessage(&lt;br /&gt;
			&amp;#039;requires only a page name (including namespace) without markup. &amp;#039;..&lt;br /&gt;
			&amp;#039;If an attempt is being made to annotate a link to a template, &amp;#039;..&lt;br /&gt;
			&amp;#039;provide only the template name with namespace e.g. &amp;quot;Template:Example&amp;quot;&amp;#039;)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- If a literal link was provided as name;&lt;br /&gt;
	-- extract the content and apply it to name and display as appropriate.&lt;br /&gt;
	local wikilink = mw.ustring.match(name, &amp;#039;^%[%[%s*:*%s*(.-)%s*%]%]$&amp;#039;)&lt;br /&gt;
	if wikilink then&lt;br /&gt;
		local link_name, link_display = unpack(mw.text.split(wikilink, &amp;#039;%s*|%s*&amp;#039;))&lt;br /&gt;
		if link_name then&lt;br /&gt;
			name = link_name&lt;br /&gt;
		end&lt;br /&gt;
		if link_display and isEmpty(args.display) then&lt;br /&gt;
			args.display = link_display&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Prepare to concatenate.&lt;br /&gt;
	local result&lt;br /&gt;
	&lt;br /&gt;
	local is_template = name:match(&amp;#039;^Template:(.+)$&amp;#039;)&lt;br /&gt;
	local template_link = args.template_link&lt;br /&gt;
	if is_template and template_link ~= &amp;#039;no&amp;#039; then&lt;br /&gt;
		result = &amp;#039;{{&amp;#039;..pipedLink(name, is_template)..&amp;#039;}}&amp;#039;&lt;br /&gt;
		if template_link == &amp;#039;code&amp;#039; then&lt;br /&gt;
			result = &amp;#039;&amp;lt;code&amp;gt;&amp;#039;..result..&amp;#039;&amp;lt;/code&amp;gt;&amp;#039;&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		local display = args.display&lt;br /&gt;
		if isEmpty(display) then&lt;br /&gt;
			display = name&lt;br /&gt;
		end&lt;br /&gt;
		result = langify({&lt;br /&gt;
			lang = args.link_lang,&lt;br /&gt;
			text = pipedLink(name, display),&lt;br /&gt;
			italic = args.link_lang_italic,&lt;br /&gt;
			nocat = args.link_lang_nocat,&lt;br /&gt;
			size = args.link_lang_size,&lt;br /&gt;
			cat = args.link_lang_cat,&lt;br /&gt;
			rtl = args.link_lang_rtl&lt;br /&gt;
		})&lt;br /&gt;
		&lt;br /&gt;
		if notEmpty(args.quote) then&lt;br /&gt;
			result = &amp;#039;&amp;quot;&amp;#039;..result..&amp;#039;&amp;quot;&amp;#039;&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		local abbr = args.abbr&lt;br /&gt;
		if notEmpty(abbr) then&lt;br /&gt;
			result = result..&amp;#039; (&amp;lt;abbr&amp;#039;&lt;br /&gt;
			local abbr_title = args.abbr_title&lt;br /&gt;
			if notEmpty(abbr_title) then&lt;br /&gt;
				result = result..&amp;#039; title=&amp;quot;&amp;#039;..abbr_title..&amp;#039;&amp;quot;&amp;#039;&lt;br /&gt;
			end&lt;br /&gt;
			result = result..&amp;#039;&amp;gt;&amp;#039;..abbr..&amp;#039;&amp;lt;/abbr&amp;gt;)&amp;#039;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if isEmpty(result) then&lt;br /&gt;
		return alarmingMessage(&amp;#039;could not create a link for &amp;quot;&amp;#039;..name..&amp;#039;&amp;quot;&amp;#039;)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local aka = args.aka&lt;br /&gt;
	if notEmpty(aka) then&lt;br /&gt;
		result = result..&amp;#039;, also known as &amp;#039;..langify({&lt;br /&gt;
			lang = args.aka_lang,&lt;br /&gt;
			text = aka,&lt;br /&gt;
			italic = args.aka_lang_italic,&lt;br /&gt;
			nocat = args.aka_lang_nocat,&lt;br /&gt;
			size = args.aka_lang_size,&lt;br /&gt;
			cat = args.aka_lang_cat,&lt;br /&gt;
			rtl = args.aka_lang_rtl&lt;br /&gt;
		})&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local wedge = args.wedge&lt;br /&gt;
	if notEmpty(wedge) then&lt;br /&gt;
		result = result..&amp;#039;, &amp;#039;..langify({&lt;br /&gt;
			lang = args.wedge_lang,&lt;br /&gt;
			text = wedge,&lt;br /&gt;
			italic = args.wedge_lang_italic,&lt;br /&gt;
			nocat = args.wedge_lang_nocat,&lt;br /&gt;
			size = args.wedge_lang_size,&lt;br /&gt;
			cat = args.wedge_lang_cat,&lt;br /&gt;
			rtl = args.wedge_lang_rtl&lt;br /&gt;
		})&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Exclude wikidata fallback for any specified list of link titles,&lt;br /&gt;
	-- unless explicity instructed that it&amp;#039;s okay.&lt;br /&gt;
	local not_wikidata_for_links_starting_with = args.not_wikidata_for_links_starting_with&lt;br /&gt;
	if isEmpty(args.wikidata) and notEmpty(not_wikidata_for_links_starting_with) then&lt;br /&gt;
		for only_explicit in hashDelimitedList(not_wikidata_for_links_starting_with) do&lt;br /&gt;
			if name:match(&amp;#039;^&amp;#039;..only_explicit) then&lt;br /&gt;
				args.only = &amp;#039;explicit&amp;#039;&lt;br /&gt;
				break&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Get the short description from Module:GetShortDescription.&lt;br /&gt;
	local short_description = require(&amp;#039;Module:GetShortDescription&amp;#039;).main({&lt;br /&gt;
		none_is_valid = args.none_is_valid,&lt;br /&gt;
		none_is_nil = args.none_is_nil,&lt;br /&gt;
		lang_italic = args.desc_lang_italic,&lt;br /&gt;
		lang_nocat = args.desc_lang_nocat,&lt;br /&gt;
		lang_size = args.desc_lang_size,&lt;br /&gt;
		lang_cat = args.desc_lang_cat,&lt;br /&gt;
		lang_rtl = args.desc_lang_rtl,&lt;br /&gt;
		lang_no = args.desc_lang_no,&lt;br /&gt;
		prefer = args.prefer,&lt;br /&gt;
		only = args.only,&lt;br /&gt;
		name = name&lt;br /&gt;
	})&lt;br /&gt;
	&lt;br /&gt;
	local dash = args.dash&lt;br /&gt;
	if isEmpty(dash) then&lt;br /&gt;
		dash = &amp;#039;&amp;amp;nbsp;–&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local fallback = args.fallback&lt;br /&gt;
&lt;br /&gt;
	if isEmpty(short_description) or short_description.redlink then&lt;br /&gt;
		return formatResult(result, dash, fallback, args.prefix_parentheses)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if short_description.alarm then&lt;br /&gt;
		return short_description.alarm&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local maintenance = &amp;#039;&amp;#039;&lt;br /&gt;
	&lt;br /&gt;
	if short_description.redirected then&lt;br /&gt;
		maintenance = optionallyVisibleCategory(&lt;br /&gt;
			&amp;#039;category-annotation-with-redirected-description&amp;#039;,&lt;br /&gt;
			&amp;#039;Pages displaying short descriptions of redirect targets&amp;#039;)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local fellback&lt;br /&gt;
	&lt;br /&gt;
	if short_description.wikidata then&lt;br /&gt;
		if short_description.fellback then&lt;br /&gt;
			fellback = true&lt;br /&gt;
			maintenance = maintenance..optionallyVisibleCategory(&lt;br /&gt;
				&amp;#039;category-wikidata-fallback-annotation&amp;#039;,&lt;br /&gt;
				&amp;#039;Pages displaying wikidata descriptions as a fallback&amp;#039;)&lt;br /&gt;
		end&lt;br /&gt;
		short_description = short_description.wikidata&lt;br /&gt;
		-- Filter against likely rubbish wikidata descriptions.&lt;br /&gt;
		local not_wikidata_descriptions_including = args.not_wikidata_descriptions_including&lt;br /&gt;
		if notEmpty(not_wikidata_descriptions_including) then&lt;br /&gt;
			-- Case insentive matching.&lt;br /&gt;
			local lower_case_short_description = short_description:lower()&lt;br /&gt;
			for exclusion in hashDelimitedList(not_wikidata_descriptions_including:lower()) do&lt;br /&gt;
				if lower_case_short_description:match(exclusion) then&lt;br /&gt;
					short_description = &amp;#039;&amp;#039;&lt;br /&gt;
					break&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		if isEmpty(short_description) then&lt;br /&gt;
			return formatResult(result, dash, fallback, args.prefix_parentheses)&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		short_description = short_description.explicit&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local lower_case_name = name:lower()&lt;br /&gt;
	&lt;br /&gt;
	if notEmpty(short_description) and not short_description:match(&amp;#039; &amp;#039;) then&lt;br /&gt;
		-- Filter against likely rubbish single word descriptions.&lt;br /&gt;
		local lower_case_short_description = short_description:lower()&lt;br /&gt;
		local not_single_word = args.not_single_word&lt;br /&gt;
		if notEmpty(not_single_word) then&lt;br /&gt;
			-- Case insentive matching.&lt;br /&gt;
			for single_word in hashDelimitedList(not_single_word:lower()) do&lt;br /&gt;
				if single_word == lower_case_short_description then&lt;br /&gt;
					short_description = &amp;#039;&amp;#039;&lt;br /&gt;
					break&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		if isEmpty(short_description) or lower_case_name:match(lower_case_short_description) then&lt;br /&gt;
			return formatResult(result, dash, fallback, args.prefix_parentheses)&lt;br /&gt;
		end&lt;br /&gt;
		if isEmpty(args.space_cat) then&lt;br /&gt;
			maintenance = maintenance..optionallyVisibleCategory(&lt;br /&gt;
				&amp;#039;category-spaceless-annotation&amp;#039;,&lt;br /&gt;
				&amp;#039;Pages displaying short descriptions with no spaces&amp;#039;)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if lower_case_name == short_description:lower() then&lt;br /&gt;
		if fellback then&lt;br /&gt;
			return formatResult(result, dash, fallback, args.prefix_parentheses)&lt;br /&gt;
		end&lt;br /&gt;
		maintenance = maintenance..optionallyVisibleCategory(&lt;br /&gt;
			&amp;#039;category-annotation-matches-name&amp;#039;,&lt;br /&gt;
			&amp;#039;Pages displaying short descriptions matching their page name&amp;#039;)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
-- Short descriptions on en Wikipedia should be formatted with an uppercase first letter, but&lt;br /&gt;
-- the typical application of this module will require the first character to be lowercase, but&lt;br /&gt;
-- some descriptions may start with proper names and should start with an uppercase letter even if used in an annotaion.&lt;br /&gt;
-- By default; this module will not affect the first letter case of descriptions retrieved by Module:GetShortDescription, but&lt;br /&gt;
-- the first letter case may be transformed explicitly if required.&lt;br /&gt;
	local desc_first_letter_case = args.desc_first_letter_case&lt;br /&gt;
	if desc_first_letter_case == &amp;#039;upper&amp;#039; or desc_first_letter_case == &amp;#039;lower&amp;#039; then&lt;br /&gt;
		short_description = handleFirstLetterCase(short_description, desc_first_letter_case)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return formatResult(result, dash, (short_description or fallback)..maintenance, args.prefix_parentheses)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
function p.main(frame)&lt;br /&gt;
	local args = require(&amp;#039;Module:Arguments&amp;#039; ).getArgs(frame)&lt;br /&gt;
	if isEmpty(args) then&lt;br /&gt;
		return alarmingMessage(&amp;#039;could not getArgs&amp;#039;) -- This really would be alarming.&lt;br /&gt;
	end&lt;br /&gt;
	return annotatedLink(args)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Djehuti</name></author>
	</entry>
</feed>