Module:Sister project links

From WikiMD's Wellness Encyclopedia

Implements {{Sister project links}}

See {{Sister project links/testcases}} for test cases for box, {{Sister bar/testcases}} for bar.

Note: in order to make the test cases work, the Sandbox CSS classes have "-sand" appended to their names. If you wish to update the CSS, copy the contents of each class from Module:Sister project links/sandbox/styles.css to Module:Sister project links/styles.css, but do not alter the class names, nor just copy-paste the entire CSS file. For the current difference in CSS between Sandbox and Main, see here.


require('strict')

-- Module to create sister project link box
local getArgs = require('Module:Arguments').getArgs
local sideBox = require('Module:Side box')._main
local p = {}

local inSandbox = mw.getCurrentFrame():getTitle():find('sandbox', 1, true) 

-- Function to add "-sand" to classes when called from sandbox
local function sandbox(s)
	return inSandbox and s.."-sand" or s
end

-- Information about how to handle each sister lives in separate data file
local cfg = mw.loadData(sandbox('Module:Sister project links/config'))
local logo = cfg.logo
local prefixList = cfg.prefixList
local sisterName = cfg.sisterName
local sisterInfo = cfg.sisterInfo
local defaultSisters = cfg.defaultSisters
local sisterDb = cfg.sisterDb
local trackingType = cfg.trackingType 

-- Function to canonicalize string
local function canonicalize(s)
	if s == nil then
		return {nil, nil}
	end
	if tostring(type(s)) == "table" then
		return s
	end
	s = mw.text.trim(tostring(s))
	if s == "" then
		return {nil, nil}
	end
	local lowerS = s:lower()
	if lowerS == 'yes' or lowerS == 'y' or lowerS == 't' or lowerS == '1' or lowerS == 'true' or lowerS == 'on' then
		return {nil, true}
	end
	if lowerS == 'no' or lowerS == 'n' or lowerS == 'f' or lowerS == '0' or lowerS == 'false' or lowerS == 'off' then
		return {nil, false}
	end
	return {s, true}
end

local function mergeArgs(argList, noAll)
	local test = nil
	if noAll then
		test = false
	end
	local allSame = true
	for _, arg in ipairs(argList) do
		if arg[2] then
			return arg
		end
		allSame = allSame and (arg[2] == test)
	end
	if allSame then
		return {nil, test}
	end
	if noAll then
		return {nil, nil}
	end
	return {nil, false}
end
		
local function getSitelink(wiki, qid)
	if mw.wikibase and mw.wikibase.getSitelink then
		return qid and mw.wikibase.getSitelink(qid, wiki)
	end
	return nil
end

local function fetchWikidata(prefix, qid)
	if mw.wikibase then
		local sisterDbName = sisterDb[prefix]
		return sisterDbName and getSitelink(sisterDbName, qid)
	end
	return nil
end

local function genSisterLink(args, tracking)
	if args[1][2] == false or (not args.default and args[1][2] == nil) then
		return nil
	end
	local sitelink = args.sitelink or fetchWikidata(args.sisterPrefix, args.qid)
	if args.auto and not sitelink and args[1][2] == nil then
		return nil
	end
	local link = args[1][1] or sitelink or (args.search and "Special:"..args.search)
	if not link then
		return nil
	end
	if tracking then
		if args[1][1] and sitelink then
			local page = mw.ustring.gsub(args[1][1], "_", " ")
			page = mw.ustring.sub(page, 1, 1):upper()..mw.ustring.sub(page, 2)
			local pageNS = mw.ustring.match(page, "^([^:]+):")
			local sitelinkNS = mw.ustring.match(sitelink, "^([^:]+):")
			if page == sitelink then
				tracking.wdHidden = args.sisterPrefix
			elseif pageNS ~= sitelinkNS then
				tracking.wdNamespace = args.sisterPrefix
			else
				tracking.wdMismatch = args.sisterPrefix
			end
		elseif not (args[1][2] or sitelink) and args.search then
			tracking.defaultSearch = args.sisterPrefix
		end
	end
	return {prefix=args.sisterPrefix, link=link, logo=args.logo, name=args.name,
		    information=args.information, prep=args.prep}
end

function p._main(args)
	local titleObject = mw.title.getCurrentTitle()
	local ns = titleObject.namespace
	if mw.wikibase then
		args.qid = args.qid or mw.wikibase.getEntityIdForTitle(args[1] or "") or mw.wikibase.getEntityIdForCurrentPage()
	else
		args.qid = nil
	end
	args.qid = args.qid and args.qid:upper()
	args[1] = args[1] or (mw.wikibase and mw.wikibase.getSitelink(args.qid or "")) or titleObject.text
	args.c = args.c or args.commons
	for _, k in ipairs(prefixList) do
		args[k] = canonicalize(args[k])
	end
	args.cookbook = canonicalize(args.cookbook)
	args.b = mergeArgs({args.b, args.cookbook})
	args.cookbook = args.cookbook[2]
	if args.trackSingle == nil then
    	args.trackSingle = true
	end
    if ns ~= 0 and ns ~= 14 then
    	args.trackSingle = false
    end
    for _,k in pairs({"auto", "commonscat", "author", "bar", "tracking", "sandbox", "trackSingle"}) do
    	args[k] = canonicalize(args[k])[2]
    end
	local tracking = (args.tracking or ns == 0) and {}
    local sisterList = {}
    for _, prefix in ipairs(prefixList) do
    	local link = sisterLink(prefix, args, tracking)
    	if link then
			table.insert(sisterList, link)
		end
	end
    local box = mw.html.create()
    if args.bar and #sisterList > 0 then
    	box:node(createSisterBar(sisterList, args))
    elseif #sisterList == 1 then
    	local sister = sisterList[1]
    	local link = "[["..sister.prefix..":"..sister.link.."|<b><i>"..(args.display or args[1]).."</i></b>]]"
    	if sister.name == 'Commons' then
    		sister.name = 'Wikimedia Commons'
    	end
    	local text = sister.name.." has "..mw.ustring.lower(sister.information).." related to "..link.."."
    	if sister.name == 'Wikipedia' then
    		text = "[["..sister.prefix..":"..sister.link.."|<b><i>"..sister.information.."</i></b>]] "..sister.prep.." [[Wikipedia]], the free encyclopedia"
    	end
    	box:wikitext(sideBox({
    		role = 'navigation',
    		position=args.position,
    		image="[[File:"..sister.logo.."|40x40px|class=noviewer|alt=|link=]]",
    		metadata='no',
    		class='plainlinks sistersitebox',
    	    text=text
    	}))
    elseif #sisterList > 0 then
    	box:wikitext(createSisterBox(sisterList, args))
    end
    if #sisterList == 0 and args.auto then
    	box:wikitext("[[Category:Pages with empty sister project links]]")
    end
	return tostring(box)
end

return p