Jump to content

Module:Canada by province category navigation: Difference between revisions

From Wikipedia, the free encyclopedia
Content deleted Content added
v00.07 -- start changing county to province
v00.08 -- finish changing county to province
Line 1: Line 1:
--[[ v00.07 -- start changing county to province
--[[ v00.08 -- finish changing county to province


each title consists of 3 parts
each title consists of 3 parts
Line 165: Line 165:
end
end


-- Does the pagename include a county name?
-- Does the pagename include a province name?
function findprovinceNameInPagename(pn, provinceList, description)
function findprovinceNameInPagename(pn, provinceList, description)
local i, aProvince, testCounty
local i, aProvince, testProvince
debugLog(2, "checking [" .. pn .."] for a county name in county set: " .. description)
debugLog(2, "checking [" .. pn .."] for a province name in province set: " .. description)
for i, aProvince in ipairs(provinceList) do
for i, aProvince in ipairs(provinceList) do
testCounty = aProvince
testProvince = aProvince
debugLog(3, "testing: [" .. testCounty .. "]")
debugLog(3, "testing: [" .. testProvince .. "]")
local testCountyEncoded = patternSearchEncode(testCounty)
local testProvinceEncoded = patternSearchEncode(testProvince)
-- For efficiency, the first test is a simple match as a a screening test
-- For efficiency, the first test is a simple match as a a screening test
-- If the bare county name is nowhere in the pagename, then no need for
-- If the bare county name is nowhere in the pagename, then no need for
Line 179: Line 179:
--so we need several passes to ensure that any match is of a complete word
--so we need several passes to ensure that any match is of a complete word
debugLog(4, "simple match? ")
debugLog(4, "simple match? ")
if (not mw.ustring.match(pn, testCountyEncoded)) then
if (not mw.ustring.match(pn, testProvinceEncoded)) then
debugLog(nil, "Fail")
debugLog(nil, "Fail")
else
else
Line 185: Line 185:


debugLog(4, "match whole name? ")
debugLog(4, "match whole name? ")
if (pn == testCounty) then
if (pn == testProvince) then
debugLog(nil, "Yes")
debugLog(nil, "Yes")
return testCounty
return testProvince
end
end
debugLog(nil, "No")
debugLog(nil, "No")


-- special for Quebec City
-- special for Quebec City
if (testCounty == 'Quebec') then
if (testProvince == 'Quebec') then
debugLog(4, "matches 'Quebec City'? ")
debugLog(4, "matches 'Quebec City'? ")
if (mw.ustring.match(pn, 'Quebec City')) then
if (mw.ustring.match(pn, 'Quebec City')) then
Line 202: Line 202:


debugLog(4, "match at start, followed by separator? ")
debugLog(4, "match at start, followed by separator? ")
if mw.ustring.match(pn, "^" .. testCountyEncoded .. "[^%w]") then
if mw.ustring.match(pn, "^" .. testProvinceEncoded .. "[^%w]") then
debugLog(nil, "Yes")
debugLog(nil, "Yes")
return testCounty
return testProvince
end
end
debugLog(nil, "No")
debugLog(nil, "No")
debugLog(4, "match at end, preceded by separator? ")
debugLog(4, "match at end, preceded by separator? ")
if mw.ustring.match(pn, "[^%w]" .. testCountyEncoded .. "$") then
if mw.ustring.match(pn, "[^%w]" .. testProvinceEncoded .. "$") then
debugLog(nil, "Yes")
debugLog(nil, "Yes")
return testCounty
return testProvince
end
end
debugLog(nil, "No")
debugLog(nil, "No")


debugLog(4, "match anywhere, preceded and followed by separator? ")
debugLog(4, "match anywhere, preceded and followed by separator? ")
if mw.ustring.match(pn, "[^%w]" .. testCountyEncoded .. "[^%w]") then
if mw.ustring.match(pn, "[^%w]" .. testProvinceEncoded .. "[^%w]") then
debugLog(nil, "Yes")
debugLog(nil, "Yes")
return testCounty
return testProvince
end
end
debugLog(nil, "No")
debugLog(nil, "No")
Line 240: Line 240:
debugLog(2, "split pagename around [" .. validprovinceName .. "]")
debugLog(2, "split pagename around [" .. validprovinceName .. "]")
local validProvinceEncoded = mw.ustring.gsub(validprovinceName, "([%W])", "%%%1")
local validProvinceEncoded = mw.ustring.gsub(validprovinceName, "([%W])", "%%%1")
match_prefix, match_county, match_suffix = mw.ustring.match(pn, "^(.*)(" .. validProvinceEncoded .. ")(.*)$")
match_prefix, match_province, match_suffix = mw.ustring.match(pn, "^(.*)(" .. validProvinceEncoded .. ")(.*)$")
title_prefix = match_prefix
title_prefix = match_prefix
title_suffix = match_suffix
title_suffix = match_suffix
thisPageProvince = mw.ustring.gsub(match_county, "^County%s+", "")
debugLog(2, "parse successful")
debugLog(2, "parse successful")
debugLog(3, "title_prefix = [" .. title_prefix .. "]")
debugLog(3, "title_prefix = [" .. title_prefix .. "]")
debugLog(3, "thisPageProvince = [" .. thisPageProvince .. "]")
debugLog(3, "thisPageProvince = [" .. match_province .. "]")
debugLog(3, "title_suffix = [" .. title_suffix .. "]")
debugLog(3, "title_suffix = [" .. title_suffix .. "]")
return true
return true

Revision as of 12:08, 26 September 2019

--[[ v00.08 -- finish changing county to province

 each title consists of 3 parts
    * prefix
    * province name
    * suffix
 e.g. "Foo in Quebec"
    * prefix = "Foo in "
    * province name = "Quebec"
    * suffix = ""
 e.g. "Nunavut-related lists"
    * prefix = ""
    * province name = "Nunavut"
    * suffix = "-related lists"
]]

-- config
local textSize = '90%'
local tableClass="toc"
local tableFallbackMaxWidth="auto"
local tableMaxWidth="calc(100% - 25em)" -- Template:GeoGroup has width: 23em<
-- local tableStyle="margin-left:0; margin-right:auto; clear:left !important; margin-top:0 !important; float:left; width:auto;"
local tableStyle="margin-left:0; margin-right:auto; clear:left !important; margin-top:0 !important; width:auto;"
local evenRowStyle = "vertical-align:top; background-color:#f3f3f3;"
local oddRowStyle = "vertical-align:top;"
local labelStyle = "text-align:right; font-weight: bold; padding: 0.25em 0.5em 0.25em 0.5em;"
local listStyle = "text-align:left; font-weight: normal; padding: 0.25em 0.5em 0.25em 0.5em;"
local greyLinkColor = "#888"

local callingTemplates = {
	'Template:CanadaByProvinceCatNav',
}

-- globals for this module
local debugging = false
local debugmsg = ""
local tableRowNum = 0
local title_prefix = ""
local title_suffix = ""
local title_prefix
local title_suffix
local thisPageProvince
local greyLinkCount = 0
local blueLinkCount = 0
local parentname = ""
local templateName

local getArgs = require('Module:Arguments').getArgs
local yesno = require('Module:Yesno')
local p = {}

local CanadaProvinces = {
	'Alberta',
	'British Columbia',
	'Manitoba',
	'New Brunswick',
	'Newfoundland and Labrador',
	'the Northwest Territories',
	'Nova Scotia',
	'Nunavut',
	'Ontario',
	'Prince Edward Island',
	'Quebec',
	'Saskatchewan',
	'Yukon'
}

function trackingCategory()
	-- discount this page, which will always be coded as a blue link, but rendered as bold un-navigable
	blueLinkCount = blueLinkCount - 1
	if greyLinkCount == 0 then
		return "[[Category:" .. templateName .. " with no grey links]]"
	end
	if blueLinkCount == 0 then
		return "[[Category:" .. templateName .. " with all grey links]]"
	end
	if  greyLinkCount > 5 then
		return "[[Category:" .. templateName .. " with over 5 grey links]]"
	end
	return ""
end

function makeTableRow(rowLabel, provinceList)
	debugLog(2, "makeTableRow, label: ")
	if (rowLabel == nil) then
		rowLabel = "By&nbsp;province<br />or territory"
		debugLog(nil, rowLabel)
	else
		rowLabel = mw.text.trim(rowLabel)
		debugLog(nil, " [" .. rowLabel .. "]")
	end
	tableRowNum = tableRowNum + 1
	local thisRow
	if (tableRowNum % 2) == 0 then
		debugLog(3, "Even-numbered")
		thisRow = '<tr style="' .. evenRowStyle .. '">\n'
	else
		debugLog(3, "Odd-numbered")
		thisRow = '<tr style="' .. oddRowStyle .. '">\n'
	end
	if not ((rowLabel == nil) or (rowLabel =="")) then
		thisRow = thisRow .. '<td style="' .. labelStyle .. '">' .. rowLabel .. '</td>\n'
	end
	-- now begin making the row contents
	thisRow = thisRow .. '<td style="' .. listStyle .. ';"><div class="hlist">\n'
	local i, aProvince
		debugLog(3, "Process provinceList")
	for i, aProvince in ipairs(provinceList) do
		debugLog(4, "No. [" .. tostring(i) .. ": [" .. aProvince .. "]")
		myCatName = makeCatName(aProvince, title_prefix, title_suffix)
		thisRow = thisRow .. "* " .. makeCatLink(myCatName, aProvince) .. "\n"
	end
	thisRow = thisRow .. '</div></td>\n</tr>'
	return thisRow
end


function makeTable()
	debugLog(1, "makeTable")
	tableRowNum = 0
	local myTable = '<table class="' .. tableClass .. '"'
	myTable = myTable .. ' style="' .. tableStyle .. '; font-size:' .. textSize .. '; max-width:' .. tableFallbackMaxWidth .. '; max-width:' .. tableMaxWidth ..'">\n'

	myTable = myTable .. makeTableRow(nil, CanadaProvinces)
	myTable = myTable .. "</table>\n"
	return myTable
end


-- Make a piped link to a category, if it exists
-- If it doesn't exist, just display the greyed the link title without linking
function makeCatLink(catname, disp)
	local displaytext
	if (disp ~= "") and (disp ~= nil) then
		-- use 'disp' parameter, but strip any leading word "the"
		displaytext = mw.ustring.gsub(disp, "^[tT]he%s+", "");
	else
		displaytext = catname
	end
	local fmtlink
	local catPage = mw.title.new( catname, "Category" )
	if (catPage.exists) then
		fmtlink = "[[:Category:" .. catname .. "|" .. displaytext .. "]]"
		blueLinkCount = blueLinkCount + 1
	else
		fmtlink = '<span style="color:' .. greyLinkColor .. '">' .. displaytext .. "</span>"
		greyLinkCount = greyLinkCount + 1
	end

	return fmtlink
end


function makeCatName(provinceName, prefix, suffix)
	local this_cat_name = '';
	this_cat_name = this_cat_name .. prefix
	this_cat_name = this_cat_name .. provinceName
	this_cat_name = this_cat_name .. suffix
	return this_cat_name
end


function patternSearchEncode(s)
	return mw.ustring.gsub(s, "([%W])", "%%%1")
end

-- Does the pagename include a province name?
function findprovinceNameInPagename(pn, provinceList, description)
	local i, aProvince, testProvince
	debugLog(2, "checking [" .. pn .."] for a province name in province set: " .. description)
	for i, aProvince in ipairs(provinceList) do
		testProvince = aProvince
		debugLog(3, "testing: ["  .. testProvince .. "]")
		local testProvinceEncoded = patternSearchEncode(testProvince)
		-- For efficiency, the first test is a simple match as a a screening test
		-- If the bare county name is nowhere in the pagename, then no need for
		-- more precise checks
		-- This check would be one line in regex, but Lua pattern matching is cruder,
		--so we need several passes to ensure that any match is of a complete word
		debugLog(4, "simple match? ")
		if (not mw.ustring.match(pn, testProvinceEncoded)) then
			debugLog(nil, "Fail")
		else
			debugLog(nil, "Success")

			debugLog(4, "match whole name? ")
			if (pn == testProvince) then
				debugLog(nil, "Yes")
				return testProvince
			end
			debugLog(nil, "No")

			-- special for Quebec City
			if (testProvince == 'Quebec') then
				debugLog(4, "matches 'Quebec City'? ")
				if (mw.ustring.match(pn, 'Quebec City')) then
					debugLog(nil, "Yes, so fail")
					return nil
				end
				debugLog(nil, "No, so OK")
			end

			debugLog(4, "match at start, followed by separator? ")
			if mw.ustring.match(pn, "^" .. testProvinceEncoded .. "[^%w]") then
				debugLog(nil, "Yes")
				return testProvince
			end
			debugLog(nil, "No")
			
			debugLog(4, "match at end, preceded by separator? ")
			if mw.ustring.match(pn, "[^%w]" .. testProvinceEncoded .. "$") then
				debugLog(nil, "Yes")
				return testProvince
			end
			debugLog(nil, "No")

			debugLog(4, "match anywhere, preceded and followed by separator? ")
			if mw.ustring.match(pn, "[^%w]" .. testProvinceEncoded .. "[^%w]") then
				debugLog(nil, "Yes")
				return testProvince
			end
			debugLog(nil, "No")
		end
	end
	return nil
end

-- parse the pagename to find 3 parts: prefix, province name, suffix
function parsePagename(pn)
	debugLog(1, "parsePagename: [" .. pn .. "]")
	local validprovinceName
	validprovinceName = findprovinceNameInPagename(pn, CanadaProvinces, "provincelst")
	if validprovinceName == nil then
		return false
	end
	
	-- if we get here, the page name "pn" includes a validprovinceName
	-- so now we need to split the string
	
	debugLog(2, "split pagename around [" .. validprovinceName .. "]")
	local validProvinceEncoded = mw.ustring.gsub(validprovinceName, "([%W])", "%%%1")
	match_prefix, match_province, match_suffix = mw.ustring.match(pn, "^(.*)(" .. validProvinceEncoded .. ")(.*)$")
	
	title_prefix = match_prefix
	title_suffix = match_suffix
	debugLog(2, "parse successful")
	debugLog(3, "title_prefix = [" .. title_prefix .. "]")
	debugLog(3, "thisPageProvince = [" .. match_province .. "]")
	debugLog(3, "title_suffix = [" .. title_suffix .. "]")
	return true
end


function publishDebugLog()
	if not debugging then
		return ""
	end
	return "==Debugging ==\n\n" .. debugmsg .. "\n== Output ==\n"
end


-- debugLog builds a log which can be output if debuging is enabled
-- each log entry is given a level, so that the output is not simply a flat list
-- a debug msg may be appended to the previous msg by setting the level to nil
function debugLog(level, msg)

	if (debugmsg == nil) then
		debugmsg = ""
	end

	if (level ~= nil) then
		-- not appending, so make a new line
		debugmsg = debugmsg .. "\n"
		-- then add the level
		local i
		for i = 1, level do
			if (i % 2) == 1 then
				debugmsg = debugmsg .. "#"
			else
				debugmsg = debugmsg .. "*"
			end
		end 
	end
	debugmsg = debugmsg .. " " .. msg
	return true
end


function getYesNoParam(args, thisParamName, defaultVal)
	local paramVal = args[thisParamName]
	if paramVal == nil then
		paramVal = ""
	end

	debugLog(2, "Evaluate yes/no parameter: [" .. thisParamName .. "] = [" .. paramVal .. "]")
	debugLog(3, "default = " .. ((defaultVal and "Yes") or "No"))
	debugLog(3, "Evaluate as: ")
	local returnValue
	if paramVal == "" then
		returnValue = defaultVal
	else
		returnValue = yesno(args[thisParamName], defaultVal)
	end
	if (returnValue) then
		debugLog(nil, "Yes")
	else
		debugLog(nil, "No")
	end
	return returnValue
end

function makeErrorMsg(s)
	return '<p class="error">[[' .. parentname .. ']] Error: ' .. s .. '</p>\n'
end

function isValidParent(p)
	local i, aParent
	for i, aParent in ipairs(callingTemplates) do
		if p == aParent then
			return true
		end
	end
	return false
end

function p.main(frame)
	local parent = frame:getParent()
	if parent then
		 parentname = parent:getTitle():gsub('/sandbox$', '')
	end

	if (parentname == nil) or not isValidParent(parentname) then
		local errormsg = '<p class="error"> Error: ' .. parentname .. ' is not a valid wrapper for [[' .. frame:getTitle() .. ']]\n'
		errormsg = errormsg .. '<br><br>Valid wrappers: '
		local i, aParent
		for i, aParent in ipairs(callingTemplates) do
			errormsg = errormsg .. '[[' .. aParent  .. ']]'
		end
		errormsg = errormsg .. '</p>'
		return errormsg
	end
	templateName = mw.ustring.gsub(parentname, "^Template:", "")
	
	debugLog(1, "Check parameters")
	debugging = getYesNoParam(frame.args, "debug", false)

	-- get the page title
	thispage = mw.title.getCurrentTitle()
	thispagename = thispage.text;
	
	debugLog(1, "mw.title.getCurrentTitle()")
	debugLog(2, "thispage.text = [" .. thispage.text .."]")
	debugLog(2, "thispage.namespace = [" .. thispage.namespace .."]")
	debugLog(2, "thispage.nsText = [" .. thispage.nsText .."]")
	debugLog(2, "is it a cat? using (thispage:inNamespace(14)): ")
	if not (thispage:inNamespace(14)) then
		debugLog(nil, "No, this is not a category")
		debugLog(1, "Not a category, so no output")
		return makeErrorMsg("only for use on a category page") .. publishDebugLog()
	end
	debugLog(nil, "Yes, this is a category")

	if not parsePagename(thispagename) then
		-- some error parsing the title, so don't proceed to output
		local trackingCatInvalid = "[[Category:" .. templateName .. " on invalid category]]"
		return makeErrorMsg('the name of this category does not include a valid Candian province or territory') .. publishDebugLog() .. trackingCatInvalid
	end
	
	debugLog(1, "all parse done")
	debugLog(2, "title_prefix = [" .. title_prefix .. "]")
	debugLog(2, "title_suffix = [" .. title_suffix .. "]")

	return publishDebugLog() .. makeTable() .. trackingCategory()

end

return p