Module:GetShortDescription/sandbox
![]() | This is the module sandbox page for Module:GetShortDescription (diff). See also the companion subpage for test cases (run). |
![]() | This module is rated as ready for general use. It has reached a mature form and is thought to be relatively bug-free and ready for use wherever appropriate. It is ready to mention on help pages and other Wikipedia resources as an option for new users to learn. To reduce server load and bad output, it should be improved by sandbox testing rather than repeated trial-and-error editing. |
![]() | This module is subject to page protection. It is a highly visible module in use by a very large number of pages, or is substituted very frequently. Because vandalism or mistakes would affect many pages, and even trivial editing might cause substantial load on the servers, it is protected from editing. |
![]() | This Lua module is used on approximately 12,000 pages and changes may be widely noticed. Test changes in the module's /sandbox or /testcases subpages, or in your own module sandbox. Consider discussing changes on the talk page before implementing them. |
![]() | This module depends on the following other modules: |
![]() | This module is required by Module:Annotated link. |
![]() | This module may, by design, output alarming informational messages under certain circumstances; if these messages are displayed on any page invoking this module directly or via any other module or template using it, the page will be added to Category:Pages displaying alarming messages about Module:GetShortDescription. |
Usage
{{#invoke:GetShortDescription|main |name= |only= |prefer= |fallback= |lang_italic= |lang_nocat= |lang_size= |lang_cat= |lang_rtl= |lang_no= }}
name
By providing only the required page name (including namespace), the module will look for an explicit {{short description}}
in that page, but if not found, will try to fetch the wikidata description. If neither are found, the result will be an empty string.
If the result is a wikidata description, and it is declared (at the source) as being of a foreign language (i.e. not en), the result will be appropriately formatted by Module:Lang (the module powering {{lang}}
), in accordance with MOS:OTHERLANG; see #Foreign language wikidata descriptions (below).
- Markup:
{{#invoke:GetShortDescription|main |name=Wikipedia}}
- Result: table
This is equivalent to stating |prefer=explicit
; see #prefer (below).
only
Providing a value for |only=
will limit the search to being only for the stated description. If no description is found, the result will be an empty string, unless a fallback is provided; see #fallback (below).
explicit
- Markup:
{{#invoke:GetShortDescription|main |name=Wikipedia |only=explicit }}
- Result: table
wikidata
- Markup:
{{#invoke:GetShortDescription|main |name=Wikipedia |only=wikidata }}
- Result: table
prefer
Providing a value for |prefer=
will initiate the search for the stated description, but try for the alternative if none is found. If no description is found, the result will be an empty string, unless a fallback is provided; see #fallback (below).
explicit or wikidata
- Markup:
{{#invoke:GetShortDescription|main |name=Wikipedia |prefer=explicit }}
- Result: table
wikidata or explicit
- Markup:
{{#invoke:GetShortDescription|main |name=Wikipedia |prefer=wikidata }}
- Result: table
fallback
If a value for |fallback=
is provided, and no description is found by the expressed route, the result will be the stated fallback.
only or fallback
- Markup:
{{#invoke:GetShortDescription|main |name=Example |only=explicit |fallback=This is a fallback }}
- Result:
prefer or fallback
- Markup:
{{#invoke:GetShortDescription|main |name=Example |prefer=wikidata |fallback=This is a fallback }}
- Result: table
Foreign language wikidata descriptions
Should a wikidata description be retrieved, which is declared (at the source) as being of a foreign language (i.e. not en), per MOS:OTHERLANG, the return will be formatted as appropriate by Module:Lang by default. This may be disabled with |lang_no=yes
or adjusted via the parameters for {{lang}}
: |lang_italic=
, |lang_nocat=
, |lang_size=
, |lang_cat=
and |lang_rtl=
; see lang's documentation for details.
Requiring this module
Instances when a table is returned
Providing a value for |objectify_alarm=
will cause alarming messages (red informational messages) to be returned as tables.
Providing a value for |report_redlinks=
will cause the return of a report instead of nothing in the event that the page named is nonexistent (i.e. a WP:REDLINK) and a search for a {{short description}}
template is processed.
A table will also be returned in the event that the module is instructed to |prefer=explicit
(its default), and returns a Wikidata description. If the reason for there being no explicit short description is because it was set to none; the table will include a value for table.none
See below for examples of these behaviors:
local getShortDescription = require( 'Module:GetShortDescription' ).main
local short_description = getShortDescription( {
-- required
name = 'page name',
-- optional
prefer = 'explicit' or 'wikidata',
only = 'explicit' or 'wikidata',
fallback = 'fallback',
objectify_alarm = true,
report_redlinks = true,
lang_no = 'yes',
-- {{lang}} options
lang_italic = <yes, no, unset, invert, default>,
lang_nocat = <yes, y, true, t, on, 1>,
lang_size = <CSS font-size e.g. '1.5em'>,
lang_cat = <no, n, false, f, off, 0>,
lang_rtl = <no (default), yes>
} )
-- If we've requested to report_redlinks or to objectify_alarm then
if type( short_description ) == 'table' then
if short_description.alarm then
-- An alarming message has been returned
local alarming_message = short_description.alarm
elseif short_description.redlink then
-- Do something about that
elseif short_description.wikidata then
-- A Wikidata description was returned without being explicitly requested
local wikidata_description = short_description.wikidata
if short_description.none then
-- Because the explicit short desc was 'none'
end
end
end
local function isEmpty( value ) return value == nil or value == '' end
local function notEmpty( value ) return not isEmpty( value ) end
local function isNone( value ) return value:lower() == 'none' end
local function alarmingMessage( message, preview )
message = '<span style="color:#d33">[[Module:GetShortDescription]] ' .. message .. '.</span>'
if not preview then message = message .. '[[Category:Pages displaying alarming messages about Module:GetShortDescription]]' end
return message
end
-- Grammatically reasonable concatenation of possible issues into one message per problematic link target.
local function previewWarning( args_name, quantity_of_things )
local message = ''
if quantity_of_things.params > 3 then message = message .. ' with extraneous parameters' end
if quantity_of_things.descriptions > 1 then message = message .. ', declaring ' .. quantity_of_things.descriptions .. ' short descriptions' end
if quantity_of_things.templates > 1 or notEmpty( message ) then
message = 'has detected that [[:' .. args_name .. '|' .. args_name .. ']] has ' .. quantity_of_things.templates .. ' {{tlx|short description}}' .. message
mw.addWarning( alarmingMessage( message, true ) )
end
end
local function getWikidataDescription( title, args, fallback )
local wikidata_id = mw.wikibase.getEntityIdForTitle( title )
if isEmpty( wikidata_id ) then return nil end
local wikidata_description, wikidata_description_lang = mw.wikibase.getDescriptionWithLang( wikidata_id )
if isEmpty( wikidata_description ) then return nil end
local result = { wikidata = wikidata_description }
if isEmpty( args.lang_no ) and notEmpty( wikidata_description_lang ) and wikidata_description_lang ~= 'en' then
-- According to the docs this is possible...
result.wikidata = require( 'Module:Lang' )._lang {
wikidata_description_lang,
wikidata_description,
italic = args.lang_italic,
nocat = args.lang_nocat,
size = args.lang_size,
cat = args.lang_cat,
rtl = args.lang_rtl
}
end
result.fellback = fallback
return result
end
local function getShortDescription( title_table, args_name, fallback )
local page_content = title_table:getContent()
-- Assume no content is a nonexistent title because it's cheaper than testing if it exists.
if isEmpty( page_content ) then return { redlink = true } end
local contents_of_all_short_description_templates = {}
-- Because there could be any number of short description templates, and not all where there should be; get all the templates.
for template in page_content:gmatch( '{%b{}}' ) do
local short_description_content = mw.ustring.match( template, '^{{%s*[Ss]hort description%s*|%s*(.-)%s*}}' )
if notEmpty( short_description_content ) then
-- Collect the contents of short description templates.
contents_of_all_short_description_templates[ #contents_of_all_short_description_templates+1 ] = short_description_content
end
-- An opportunity for efficiency gain exists - to break if another type of template is found e.g. citation templates,
-- but on an appallingly formatted page, a short description template down by the categories would likely be missed.
end
if #contents_of_all_short_description_templates < 1 then return nil end
local quantity_of_things = {
templates = #contents_of_all_short_description_templates,
descriptions = 0,
params = 0
}
local possible_short_descriptions = {}
for template_content_index, short_description_template_contents in ipairs( contents_of_all_short_description_templates ) do
-- Split the contents at pipes and trim.
local short_description_template_params = mw.text.split( short_description_template_contents, '%s*|%s*' )
if #short_description_template_params > quantity_of_things.params then
quantity_of_things.params = #short_description_template_params
end
possible_short_descriptions[ template_content_index ] = {}
-- Look through the params:
for i, param in ipairs( short_description_template_params ) do
if param == 'noreplace' or mw.ustring.match( param, '^2%s*=%s*noreplace$' ) then
-- Take note of 'noreplace'-ing for establishment of hierarchy later.
possible_short_descriptions[ template_content_index ].noreplace = true
else
local has_equals = param:match( '=' )
if not has_equals or param:match( '^1' ) then
-- Grab the short description.
if has_equals then param = mw.ustring.gsub( param, '^1%s*=%s*', '' ) end
-- If the template has both a numbered and an unnumbered short description;
-- whichever comes last (ltr) will be used by that template, so overwriting works out great.
possible_short_descriptions[ template_content_index ].description = param
-- And we want to know the total quantity of descriptions being declared.
quantity_of_things.descriptions = quantity_of_things.descriptions + 1
end
end
end
end
local short_descriptions = {}
-- Look through the short descriptions.
for i, possible_short_description in ipairs( possible_short_descriptions ) do
if possible_short_description.description then
-- If a description is 'noreplace'-ing or 'none'; demote it.
if ( possible_short_description.noreplace or isNone( possible_short_description.description ) ) and #possible_short_descriptions > 1 then
-- But don't demote it if it's already at the bottom.
if i > 1 then table.insert( short_descriptions, #short_descriptions, possible_short_description )
else short_descriptions[ #short_descriptions+1 ] = possible_short_description end
else short_descriptions[ #short_descriptions+1 ] = possible_short_description end
end
end
-- Let previewWarning() work out if these numbers are bad.
previewWarning( args_name, quantity_of_things )
if #short_descriptions >= 1 then
local short_description = short_descriptions[ #short_descriptions ].description
if notEmpty( short_description ) then return { explicit = short_description, fellback = fallback } end
end
return nil
end
local function isSisterProjectLink( title )
local sister_project_prefixes = {
'wiktionary', 'wikt',
'wikinews', 'n',
'wikibooks', 'b',
'wikiquote', 'q',
'wikisource', 's',
'wikispecies', 'species',
'wikiversity', 'v',
'wikivoyage', 'voy',
'commons', 'c',
'wikidata', 'd',
'mediawikiwiki', 'mw',
'wikimedia', 'foundation', 'wmf',
'meta', 'm',
'incubator',
'phabricator', 'phab'
}
local pre_colon = title:match( '^(%a+):' )
if pre_colon then
for i, sister in ipairs( sister_project_prefixes ) do
if pre_colon == sister then return true end
end
end
return false
end
-- Resolve redirects (including multiple) to their end target.
local function getTitleAndTable( orig_name )
local title_table = mw.title.new( orig_name )
title_table = title_table.redirectTarget or title_table
local title = title_table.prefixedText
if title == orig_name then
return title, title_table
end
return getTitleAndTable( title )
end
local function getDescription( args )
local args_name = args.name
if isEmpty( args_name ) then return { alarm = 'requires a page name (including namespace)' } end
local title, title_table = getTitleAndTable( args_name )
if isSisterProjectLink( title ) then return nil end
local only = args.only
local prefer = args.prefer or 'explicit'
-- Pass args_name to getShortDescription() so previewWarning()s won't be confusing for redirects.
if notEmpty( only ) then
if only == 'explicit' then return getShortDescription( title_table, args_name ) end
if only == 'wikidata' then return getWikidataDescription( title, args ) end
return { alarm = 'accepts either "explicit" or "wikidata" as the value of |only=' } end
if notEmpty( prefer ) then
if prefer == 'explicit' then
local short_description = getShortDescription( title_table, args_name )
if notEmpty( short_description ) then
if short_description.redlink or ( not isNone( short_description.explicit ) or args.none_is_valid ) then return short_description end
end
return getWikidataDescription( title, args, true ) end
if prefer == 'wikidata' then return getWikidataDescription( title, args ) or getShortDescription( title_table, args_name, true ) end
return { alarm = 'accepts either "explicit" or "wikidata" as the value of |prefer=' }
end
end
local function main( args )
local result = getDescription( args )
if notEmpty( result ) then
if result.alarm then result.alarm = alarmingMessage( result.alarm ) end
if args.stringify then
if result.alarm then result = result.alarm else
result = result.explicit or result.wikidata
if args.none_is_nil and isNone( result ) then result = nil end
end
elseif not result.alarm and args.none_is_nil then
local description = result.explicit or result.wikidata
if description and args.none_is_nil and isNone( description ) then result = nil end
end
end
return result
end
local p = {}
function p.main( frame )
local args = require( 'Module:Arguments' ).getArgs( frame )
if isEmpty( args ) then return alarmingMessage( 'could not getArgs' ) end
--[[ DON'T FORGET THIS ]]
local result = main( args )
--mw.logObject( result )
return result
--[[ DON'T FORGET THIS ]]
end
return p
-- p.main{ name="" }
-- p.main{ name="", stringify=true }
-- p.main{ name="jhgfd" }
-- p.main{ name="jhgfd", stringify=true }
-- p.main{ name="Wikipedia:example of a double redirect" }
-- p.main{ name="Wikipedia:example of a double redirect", stringify=true }
-- p.main{ name="The Partisan", only="wackydata" }
-- p.main{ name="The Partisan", only="wackydata", stringify=true }
-- p.main{ name="List of sausages" }
-- p.main{ name="List of sausages", none_is_valid=true }
-- p.main{ name="List of sausages", none_is_valid=true, none_is_nil=true }
-- p.main{ name="List of sausages", stringify=true }
-- p.main{ name="List of sausages", none_is_valid=true, stringify=true }
-- p.main{ name="List of sausages", none_is_valid=true, none_is_nil=true, stringify=true }