Module:Annotated link: Difference between revisions

Content deleted Content added
blimey
disable wikidata short descriptions, per RFC and multiple talk page discussions. Please report any bugs on the template talk page
 
(52 intermediate revisions by 4 users not shown)
Line 1:
local p = {}
 
local function pipedLink(name, display) return '[[:'..name..'|'..display..']]' end
local getShortDescription = require( 'Module:GetShortDescription' ).main
local mLang = require( 'Module:Lang' )
 
local function errorMessageisEmpty(value) messagereturn )value == nil or value == '' end
 
return '<strong class="error">ERROR with invocation of [[Module:AnnotatedLink]]: ' .. message .. '</strong>'
local function notEmpty(value) return not isEmpty(value) end
 
-- Unescape functionality grabbed from https://stackoverflow.com/a/14899740/1832568
local function unescape(str)
str = string.gsub(str, '&#(%d+);', string.char)
str = string.gsub(str, '&#x(%d+);', function(d) return string.char(tonumber(d, 16)) end)
return str
end
 
local function hashDelimitedList(list_string) return mw.text.gsplit(unescape(list_string), '%s*#%s*') end
 
local function alarmingMessage(message)
return '<span style="color:#d33">[[Module:Annotated link]] '..message..'.</span>'..
'[[Category:Pages displaying alarming messages about Module:Annotated link]]'
end
 
local function optionallyVisibleCategory(class, category)
return '<span style="display:none" class="'..class..'">'..category..
'</span>[[Category:'..category..' via Module:Annotated link]]'
end
 
local function handleFirstLetterCase(short_description, case)
return mw.ustring.gsub(short_description, '^([^%d])', function(first_char)
if case == 'upper' then
return mw.ustring.upper(first_char)
end
return mw.ustring.lower(first_char) end
)
end
 
local functionmLang langify= require( args 'Module:Lang')
local function langify(args)
local lang = args.lang
local text = args.text
if not isEmpty(lang) or lang == 'en' then
return text
end
Line 17 ⟶ 44:
lang,
text,
italic = args.italic or '',
nocat = args.nocat or '',
size = args.size or '',
cat = args.cat or '',
rtl = args.rtl or ''
}
end
 
local function handleFirstLetterCaseformatResult(result, short_descriptiondash, casedescription, prefix_parentheses)
if not casenotEmpty(description) then
if prefix_parentheses then
return short_description
local startIdx = description:find("%(")
end
if startIdx then
local case_altered_short_description = mw.ustring.gsub( short_description, '^([^%d])', function( first_char )
local beforeParens = description:sub(1, startIdx - 2)
if case == 'lower' then
local insideParens = description:sub(startIdx, -1)
return mw.ustring.lower( first_char )
return result..' '..insideParens..dash..' '..beforeParens
end
end
return mwresult.ustring.upper(dash..' first_char )'..description
end )
if case_altered_short_description ~= short_description then
mw.log( 'tracking categories rule' )
end
return case_altered_short_descriptionresult
end
 
local function annotatedLink( args )
local name = args.name
if not isEmpty(name) then
return errorMessagealarmingMessage('requires 'a page name (including namespace) MUST be provided' )
end
-- In order to handle an attempt to annotate a template link
local case = args.desc_first_letter_case
-- already formatted with the likes of {{tl|<template name>}};
local dash = args.dash or ' –'
-- unescape name to make sense of braces in lua patern matching.
local display = args.display
name = unescape(name)
local wedge = args.wedge
local quote = args.quote
local abbr = args.abbr
local aka = args.aka
if name:match('^{%b{}}$') then
local GSD_args = {
-- The possibility to extract useful data exists here: e.g. {{tl*|Template}}.
args = {
return alarmingMessage(
lang_italic = args.desc_lang_italic,
'requires only a page name (including namespace) without markup. '..
lang_nocat = args.desc_lang_nocat,
'If an attempt is being made to annotate a link to a template, '..
lang_size = args.desc_lang_size,
'provide only the template name with namespace e.g. "Template:Example"')
lang_cat = args.desc_lang_cat,
end
lang_rtl = args.desc_lang_rtl,
lang_no = args.desc_lang_no,
fallback = args.fallback,
prefer = args.prefer,
only = args.only,
name = name
}
}
-- If a literal link was provided as name;
local result = langify( {
-- extract the content and apply it to name and display as appropriate.
lang = args.link_lang,
local wikilink = mw.ustring.match(name, '^%[%[%s*:*%s*(.-)%s*%]%]$')
text = '[[:' .. name .. '|' .. ( display or name ) .. ']]',
if wikilink then
italic = args.link_lang_italic,
local link_name, link_display = unpack(mw.text.split(wikilink, '%s*|%s*'))
nocat = args.link_lang_nocat,
if link_name then
size = args.link_lang_size,
name = link_name
cat = args.link_lang_cat,
end
rtl = args.link_lang_rtl
if link_display and isEmpty(args.display) then
} )
args.display = link_display
end
end
-- Prepare to concatenate.
if quote then
result = '"' .. local result .. '"'
local is_template = name:match('^Template:(.+)$')
local template_link = args.template_link
if is_template and template_link ~= 'no' then
result = '{{'..pipedLink(name, is_template)..'}}'
if template_link == 'code' then
result = '<code>'..result..'</code>'
end
else
local display = args.display
if isEmpty(display) then
display = name
end
result = langify({
lang = args.link_lang,
text = pipedLink(name, display),
italic = args.link_lang_italic,
nocat = args.link_lang_nocat,
size = args.link_lang_size,
cat = args.link_lang_cat,
rtl = args.link_lang_rtl
})
if notEmpty(args.quote) then
result = '"'..result..'"'
end
local abbr = args.abbr
if notEmpty(abbr) then
result = result..' (<abbr'
local abbr_title = args.abbr_title
if notEmpty(abbr_title) then
result = result..' title="'..abbr_title..'"'
end
result = result..'>'..abbr..'</abbr>)'
end
end
if abbrisEmpty(result) then
return alarmingMessage('could not create a link for "'..name..'"')
result = result .. ' (' .. abbr .. ')'
end
iflocal aka then= args.aka
if notEmpty(aka) then
result = result .. ', also known as ' .. langify( {
result = result..', also known as '..langify({
lang = args.aka_lang,
text = aka,
Line 97 ⟶ 153:
cat = args.aka_lang_cat,
rtl = args.aka_lang_rtl
} )
end
iflocal wedge then= args.wedge
if notEmpty(wedge) then
result = result .. ', ' .. langify( {
result = result..', '..langify({
lang = args.wedge_lang,
text = wedge,
Line 109 ⟶ 166:
cat = args.wedge_lang_cat,
rtl = args.wedge_lang_rtl
} )
end
-- Exclude wikidata fallback for any specified list of link titles,
local short_description = handleFirstLetterCase( getShortDescription( GSD_args ), case )
-- unless explicity instructed that it's okay.
if short_description and short_description ~= '' then
local not_wikidata_for_links_starting_with = args.not_wikidata_for_links_starting_with
result = result .. dash .. ' ' .. short_description
if isEmpty(args.wikidata) and notEmpty(not_wikidata_for_links_starting_with) then
for only_explicit in hashDelimitedList(not_wikidata_for_links_starting_with) do
if name:match('^'..only_explicit) then
args.only = 'explicit'
break
end
end
end
-- Get the short description from Module:GetShortDescription.
return result
local short_description = require('Module:GetShortDescription').main({
none_is_valid = args.none_is_valid,
none_is_nil = args.none_is_nil,
lang_italic = args.desc_lang_italic,
lang_nocat = args.desc_lang_nocat,
lang_size = args.desc_lang_size,
lang_cat = args.desc_lang_cat,
lang_rtl = args.desc_lang_rtl,
lang_no = args.desc_lang_no,
prefer = args.prefer,
only = args.only,
name = name
})
local dash = args.dash
end
if isEmpty(dash) then
dash = '&nbsp;–'
end
 
local fallback = args.fallback
function p.main( frame )
local args = frame.args
local annotated_link = annotatedLink( args )
mw.log( annotated_link )
return annotated_link
end
 
if isEmpty(short_description) or short_description.redlink then
return p
return formatResult(result, dash, fallback, args.prefix_parentheses)
 
end
--[[
if short_description.alarm then
{{#invoke:AnnotatedLink|main
return short_description.alarm
end
local maintenance = ''
|name= |display= |wedge= |quote= |dash= |abbr= |desc_first_letter_case= |aka=
|link_lang= |link_lang_italic= |link_lang_nocat= |link_lang_size= |link_lang_cat= |link_lang_rtl=
|wedge_lang= |wedge_lang_italic= |wedge_lang_nocat= |wedge_lang_size= |wedge_lang_cat= |wedge_lang_rtl=
|aka_lang= |aka_lang_italic= |aka_lang_nocat= |aka_lang_size= |aka_lang_cat= |aka_lang_rtl=
if short_description.redirected then
|only= |prefer= |fallback=
maintenance = optionallyVisibleCategory(
'category-annotation-with-redirected-description',
'Pages displaying short descriptions of redirect targets')
end
local fellback
|desc_lang_italic= |desc_lang_nocat= |desc_lang_size= |desc_lang_cat= |desc_lang_rtl= |desc_lang_no=
if short_description.wikidata then
}}
-- if short_description.fellback then
-- fellback = true
-- maintenance = maintenance..optionallyVisibleCategory(
-- 'category-wikidata-fallback-annotation',
-- 'Pages displaying wikidata descriptions as a fallback')
-- end
-- short_description = short_description.wikidata
-- Filter against likely rubbish wikidata descriptions.
-- local not_wikidata_descriptions_including = args.not_wikidata_descriptions_including
-- if notEmpty(not_wikidata_descriptions_including) then
-- Case insentive matching.
-- local lower_case_short_description = short_description:lower()
-- for exclusion in hashDelimitedList(not_wikidata_descriptions_including:lower()) do
-- if lower_case_short_description:match(exclusion) then
short_description = ''
-- break
-- end
-- end
-- end
if isEmpty(short_description) then
return formatResult(result, dash, fallback, args.prefix_parentheses)
end
else
short_description = short_description.explicit
end
local lower_case_name = name:lower()
p.main { args = { name = "", display = "", wedge = "", quote = "", dash = "", abbr = "", desc_first_letter_case = "", aka = "" } }
if notEmpty(short_description) and not short_description:match(' ') then
p.main { args = { name = "The Partisan" } }
-- Filter against likely rubbish single word descriptions.
p.main { args = { name = "The Partisan", quote = "yes" } }
local lower_case_short_description = short_description:lower()
p.main { args = { name = "The Partisan", quote = "yes", only = "wikidata", desc_first_letter_case = "upper" } }
local not_single_word = args.not_single_word
if notEmpty(not_single_word) then
-- Case insentive matching.
for single_word in hashDelimitedList(not_single_word:lower()) do
if single_word == lower_case_short_description then
short_description = ''
break
end
end
end
if isEmpty(short_description) or lower_case_name:match(lower_case_short_description) then
return formatResult(result, dash, fallback, args.prefix_parentheses)
end
if isEmpty(args.space_cat) then
maintenance = maintenance..optionallyVisibleCategory(
'category-spaceless-annotation',
'Pages displaying short descriptions with no spaces')
end
end
if lower_case_name == short_description:lower() then
p.main { args = { name = "Author, Author (Star Trek: Voyager)" } }
if fellback then
p.main { args = { name = "Author, Author (Star Trek: Voyager)", display = "Author, Author" } }
return formatResult(result, dash, fallback, args.prefix_parentheses)
p.main { args = { name = "Author, Author (Star Trek: Voyager)", display = "Author, Author", wedge = "''(Star Trek: Voyager)''" } }
end
maintenance = maintenance..optionallyVisibleCategory(
'category-annotation-matches-name',
'Pages displaying short descriptions matching their page name')
end
-- Short descriptions on en Wikipedia should be formatted with an uppercase first letter, but
p.main { args = { name = "Confédération Mondiale des Activités Subaquatiques", display = "World Underwater Federation", abbr = "CMAS", aka = "''Confédération Mondiale des Activités Subaquatiques''", desc_first_letter_case = "lower" } }
-- the typical application of this module will require the first character to be lowercase, but
-- some descriptions may start with proper names and should start with an uppercase letter even if used in an annotaion.
-- By default; this module will not affect the first letter case of descriptions retrieved by Module:GetShortDescription, but
-- the first letter case may be transformed explicitly if required.
local desc_first_letter_case = args.desc_first_letter_case
if desc_first_letter_case == 'upper' or desc_first_letter_case == 'lower' then
short_description = handleFirstLetterCase(short_description, desc_first_letter_case)
end
return formatResult(result, dash, (short_description or fallback)..maintenance, args.prefix_parentheses)
end
 
local p = {}
--]]
 
function p.main(frame)
-- p.main { args = { name = "The Partisan", quote = "yes", only = "wikidata", desc_first_letter_case = "upper", wedge = "from the album ''[[Songs from a Room]]''", aka = "La Complainte du partisan", aka_lang = "fr" } }
local args = require('Module:Arguments' ).getArgs(frame)
if isEmpty(args) then
return alarmingMessage('could not getArgs') -- This really would be alarming.
end
return annotatedLink(args)
end
 
return p