Roovet Articles
Module:Official website
| This Lua module is used on approximately 335,000 pages, or roughly 875% of all pages. To avoid major disruption and server load, any changes should be tested in the module's /sandbox or /testcases subpages, or in your own module sandbox. The tested changes can be added to this page in a single edit. Consider discussing changes on the talk page before implementing them. |
This module uses the Wikidata property:
official website (P856) (see uses)
| 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 implements {{Official website}}. Please see the template page for documentation.
Tracking categories
- Category:Official website missing URL (0)
- Category:Official website different in Wikidata and Wikipedia (0)
- Category:Official website not in Wikidata (0)
See also
-- Module:Official_website
-- Robust version that works WITH or WITHOUT Wikibase.
-- If Wikibase (mw.wikibase) is unavailable, the module will gracefully
-- skip all Wikidata lookups and only use the provided |url= / positional args.
local makeUrl = require('Module:URL')._url
local p = {}
-- -------- Utility helpers --------
-- Wrapper for pcall which returns nil on failure.
local function quickPcall(func)
local ok, res = pcall(func)
if ok then
return res
end
end
-- Detect whether Wikibase is available on this wiki.
local hasWikibase = (mw and mw.wikibase)
and type(mw.wikibase.getEntityIdForCurrentPage) == 'function'
and type(mw.wikibase.getAllStatements) == 'function'
local function getCurrentQid()
if not hasWikibase then return nil end
return quickPcall(function()
return mw.wikibase.getEntityIdForCurrentPage()
end)
end
-- Gets the rank for a Wikidata property table. Returns 1, 0 or -1.
local function getRank(prop)
local rank = prop and prop.rank
if rank == 'preferred' then return 1 end
if rank == 'normal' then return 0 end
if rank == 'deprecated' then return -1 end
return 0
end
-- Finds whether a Wikidata property is qualified as being in English (P407 = Q1860).
local function isEnglish(prop)
local ret = quickPcall(function ()
if not prop or not prop.qualifiers or not prop.qualifiers.P407 then
return false
end
for _, lang in ipairs(prop.qualifiers.P407) do
local v = lang and lang.datavalue and lang.datavalue.value
if v and v['numeric-id'] == 1860 then
return true
end
end
return false
end)
return ret == true
end
-- Normalize URL for comparison (trim spaces and trailing slashes).
local function normalizeUrl(u)
if type(u) ~= 'string' then return u end
u = mw.text.trim(u)
-- remove trailing slashes (one or more)
u = u:gsub('/+$', '')
return u
end
-- -------- Wikidata fetch (guarded) --------
local fetchWikidataUrl
fetchWikidataUrl = function()
-- If Wikibase isn't available, short-circuit to nil and memoize.
if not hasWikibase then
fetchWikidataUrl = function() return nil end
return nil
end
-- Get objects for all official sites (P856) on Wikidata.
local websites = quickPcall(function ()
return mw.wikibase.getAllStatements(getCurrentQid(), 'P856')
end) or {}
-- Clone for safe sorting.
websites = mw.clone(websites)
-- Add original index to stabilize sort.
for i, website in ipairs(websites) do
website._index = i
end
-- Sort by (1) rank, (2) English qualifier, (3) original index.
table.sort(websites, function(ws1, ws2)
local r1, r2 = getRank(ws1), getRank(ws2)
if r1 ~= r2 then
return r1 > r2
end
local e1, e2 = isEnglish(ws1), isEnglish(ws2)
if e1 ~= e2 then
return e1
end
return (ws1._index or 0) < (ws2._index or 0)
end)
-- Extract URL string from top candidate.
local url = quickPcall(function ()
local snak = websites[1] and websites[1].mainsnak
return snak and snak.datavalue and snak.datavalue.value or nil
end)
-- Memoize result.
fetchWikidataUrl = function ()
return url
end
return url
end
-- -------- Rendering --------
-- Render the URL link + optional adornments.
local function renderUrl(options)
if not options.url and not options.wikidataurl then
-- Nothing to show; offer a helpful message.
local qid = hasWikibase and getCurrentQid() or nil
local result = '<strong class="error">No URL found. ' ..
'Please specify a URL' ..
(hasWikibase and ' here or add one to Wikidata.' or ' here.') ..
'</strong>'
if hasWikibase and qid then
result = result ..
' [[File:OOjs UI icon edit-ltr-progressive.svg|frameless|text-top|10px' ..
'|alt=Edit this at Wikidata' ..
'|link=https://www.wikidata.org/wiki/' .. qid .. '#P856' ..
'|Edit this at Wikidata]]'
end
return result
end
local ret = {}
ret[#ret + 1] = string.format(
'<span class="official-website">%s</span>',
makeUrl(options.url or options.wikidataurl, options.display)
)
-- If pulling from Wikidata and a local URL wasn't provided, show edit badge (only if Wikibase exists).
if options.wikidataurl and not options.url and hasWikibase then
local qid = getCurrentQid()
if qid then
ret[#ret + 1] =
'[[File:OOjs UI icon edit-ltr-progressive.svg|frameless|text-top|10px' ..
'|alt=Edit this at Wikidata' ..
'|link=https://www.wikidata.org/wiki/' .. qid .. '#P856' ..
'|Edit this at Wikidata]]'
end
end
if options.format == 'flash' then
ret[#ret + 1] = mw.getCurrentFrame():expandTemplate{
title = 'Color',
args = {'#505050', '(Requires [[Adobe Flash Player]])'}
}
end
if options.mobile then
ret[#ret + 1] = '(' .. makeUrl(options.mobile, 'Mobile') .. ')'
end
return table.concat(ret, ' ')
end
-- Render the tracking category (only when it makes sense).
local function renderTrackingCategory(url, wikidataurl)
-- Only in article namespace.
if mw.title.getCurrentTitle().namespace ~= 0 then
return ''
end
-- If Wikibase isn't available, we cannot track Wikidata-related categories.
if not hasWikibase then
-- If no URL at all, optionally add a local maintenance category.
if not url then
return '[[Category:Official website missing URL]]'
end
return ''
end
local category
if not url and not wikidataurl then
category = 'Official website missing URL'
elseif not url and wikidataurl then
-- OK: URL solely from Wikidata -> no category
return ''
elseif url and wikidataurl then
if normalizeUrl(url) ~= normalizeUrl(wikidataurl) then
category = 'Official website different in Wikidata and Wikipedia'
end
else
category = 'Official website not in Wikidata'
end
return category and string.format('[[Category:%s]]', category) or ''
end
-- -------- Public interface --------
function p._main(args)
local url = args[1] or args.URL or args.url
local wikidataurl = fetchWikidataUrl()
local formattedUrl = renderUrl{
url = url,
wikidataurl = wikidataurl,
display = args[2] or args.name or 'Official website',
format = args.format,
mobile = args.mobile
}
return formattedUrl .. renderTrackingCategory(url, wikidataurl)
end
function p.main(frame)
local args = require('Module:Arguments').getArgs(frame, {
wrappers = 'Template:Official website'
})
return p._main(args)
end
return p