--[[ v 10 subpages renamed testing - we have output - portal checking done, but output not working - full country-checking list is working - data moved to sub-modules Now working on fixing countries prefixed by "the" ToDo in further versions: * Tracking categories * error messages * Tidyup code ]] -- 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; width:auto; font-weight:normal; " local basicRowStyle="padding:0.3em 0.7em 0.3em 0.3em; vertical-align:top; text-align:left; border-top:1px solid darkgray; " local headerRowStyle="font-weight:normal; text-align:center; background-color:#f3f3f3" local headerCellStyle = "text-align:center; background-color:#f3f3f3;" local evenRowStyle = "" --background-color:#f3f3f3;" local oddRowStyle = "" local footerRowStyle="text-align:center; background-color:#f3f3f3; border-top:1px solid darkgray; " local footerCellStyle = "text-align:center; border-top:1px solid darkgray; background-color:#f3f3f3; " 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 defaultPortals = { "Human migration" } -- Behaviour switches local portalsEnabled = true local debuggingEnabled = false -- local debuggingEnabled = true -- globals for this module local debugmsg = "" local tableRowNum = 0 local greyLinkCount = 0 local blueLinkCount = 0 local parentname = "" local templateName local countryName1 = nil local countryName2 = nil local myTrackingCategories = "" local countryAdjectivesToNounsTable = { } local countryNounstoAdjectivesTable = { } local countriesPrefixedByThe = { } -- if the country name is prefixed by "the" in running text, -- then return that prefix -- Otherwise just return an empty string function countryPrefixThe(s) if (countriesPrefixedByThe[s] == true) then return "the " end return "" end -- other modules local getArgs = require('Module:Arguments').getArgs local yesno = require('Module:Yesno') local p = {} -- converts first character of a string to uppercase -- while leaving the rest unchanged function firstToUpper(str) return (str:gsub("^%l", string.upper)) end function makeTrackingCategory() -- 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]]" elseif greyLinkCount > 3 then return "[[Category:" .. templateName .. " with over 3 grey links]]" elseif greyLinkCount < 3 then return "[[Category:" .. templateName .. " with fewer than 3 grey links]]" end return "" end function makeTableRow(rowLabel, countryA, countryB) tableRowNum = tableRowNum + 1 debugLog(3, string.format("makeTableRow #%d", tableRowNum)) local rowLabel = string.format("%s in %s%s", getAdjectiveFromCountry(countryA), countryPrefixThe(countryB), countryB) debugLog(4, "rowLabel=" .. rowLabel) local thisRow if (tableRowNum % 2) == 0 then debugLog(4, "Even-numbered") thisRow = '<tr style="' .. basicRowStyle .. evenRowStyle .. '">\n' else debugLog(4, "Odd-numbered") thisRow = '<tr style="' .. basicRowStyle .. oddRowStyle .. '">\n' end thisRow = thisRow .. '<td style="' .. labelStyle .. '">' .. rowLabel .. '</td>\n' thisRow = thisRow .. '<td style="' .. listStyle .. ';"><div class="hlist">\n' -- now begin making the row contents thisRow = thisRow .. '* ' .. makeCatLink(string.format("%s expatriates in %s%s", getAdjectiveFromCountry(countryA), countryPrefixThe(countryB), countryB), "Expatriates") .. '\n' thisRow = thisRow .. '* <small>' .. makeCatLink(string.format("%s expatriate sportspeople in %s%s", getAdjectiveFromCountry(countryA), countryPrefixThe(countryB), countryB), "(sportspeople)") .. '</small>\n' thisRow = thisRow .. '* ' .. makeCatLink(string.format("%s emigrants to %s%s", getAdjectiveFromCountry(countryA), countryPrefixThe(countryB), countryB), "Emigrants") .. '\n' thisRow = thisRow .. '* ' .. makeCatLink(string.format("%s people of %s descent", getAdjectiveFromCountry(countryB), getAdjectiveFromCountry(countryA)), "Descent") .. '\n' local diasporaCatName = string.format("%s diaspora in %s%s", getAdjectiveFromCountry(countryA), countryPrefixThe(countryB), countryB) if (doesPageExist(diasporaCatName, "Category")) then thisRow = thisRow .. '* ' .. makeCatLink(diasporaCatName, "Diaspora") .. '\n' end thisRow = thisRow .. '</div></td>\n</tr>' debugLog(4, "Made the row") return thisRow end function makeTable() debugLog(1, "makeTable") debugLog(2, "countryName1=") if (countryName1 == nil) then debugLog(nil, "nil") else debugLog(nil, countryName1) end debugLog(2, "countryName2=") if (countryName2 == nil) then debugLog(nil, "nil") else debugLog(nil, countryName2) end -- sort country names debugLog(2, "checking sort order: ") if (countryName1 <= countryName2) then debugLog(nil, "checking sort order: OK") else debugLog(nil, "checking sort order: need to be swapped") local swapSpace = countryName1 countryName1 = countryName2 countryName2 = swapSpace debugLog(3, "Swapped.: Now countryName1=[%s], and countryName2=[%s]", countryName1, countryName2) end tableRowNum = 0 local myTable = '<table class="' .. tableClass .. '"' myTable = myTable .. ' style="' .. tableStyle .. '; font-size:' .. textSize .. '; max-width:' .. tableFallbackMaxWidth .. '; max-width:' .. tableMaxWidth ..'">\n' -- first make the header row tableRowNum = tableRowNum + 1 myTable = myTable .. "<tr style = " .. basicRowStyle .. headerRowStyle .. ">\n" myTable = myTable .. "<td colspan='2' style='" .. headerCellStyle .. "'>" myTable = myTable .. "Categories for [[human migration]] between '''[[" .. countryName1 .. "]] and " .. countryPrefixThe(countryName2) .. " [[" .. countryName2.. "]]'''" myTable = myTable .. "</td>\n</tr>\n" myTable = myTable .. makeTableRow(rowLabel, countryName1, countryName2) myTable = myTable .. makeTableRow(rowLabel, countryName2, countryName1) -- make the footer row myTable = myTable .. "<tr style = /" .. basicRowStyle .. footerRowStyle .. "'>\n" myTable = myTable .. "<td colspan='2' style='" .. footerCellStyle .. "'>" local fooBarRelations = string.format("%s–%s relations", countryName1, countryName2) myTable = myTable .. "''See also'': " .. makeCatLink(fooBarRelations, fooBarRelations) .. '\n' myTable = myTable .. "</td>\n</tr>\n" 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 trailing disambiguator displaytext = mw.ustring.gsub(disp, "%s+%(.+$", ""); else displaytext = catname end local fmtlink if (doesPageExist(catname, "Category")) then fmtlink = "[[:Category:" .. catname .. "|" .. displaytext .. "]]" blueLinkCount = blueLinkCount + 1 else fmtlink = '<span style="color:' .. greyLinkColor .. '">' .. displaytext .. "</span>" greyLinkCount = greyLinkCount + 1 end return fmtlink end function doesPageExist(s, myNamespace) local myTestPage = mw.title.new(s, myNamespace) if (myTestPage.exists) then return true else return false end end -- ##################### New stuff starts here ################ function getCountryFromAdjective(s) return countryAdjectivesToNounsTable[s] end function getAdjectiveFromCountry(s) return countryNounstoAdjectivesTable[s] end function stripThe(s) if s == nil then debugLog(2, string.format("cannot strip a nil value")) return nil end if mw.ustring.match( s, "^[T]he Gambia") ~= nil then return "the Gambia" end debugLog(2, string.format("stripping [%s]", s)) local stripped = mw.ustring.gsub(s, "^[tT]he ", "") if stripped == nil then debugLog(nil, " → nil") else debugLog(nil, string.format(" → [%s]", stripped)) end return stripped end -- semi-patterns -- add explanation local categoryMasks = { ["Fooian people of Barian descent"] = {false, "(.+) people of (.+) descent"}, ["Fooian emigrants to Bar"] = {true, "(.+) emigrants to (.+)"}, ["Fooian expatriates in Bar"] = {true, "(.+) expatriates in (.+)"}, ["Fooian expatriate sportspeople in Bar"] = {true, "(.+) expatriate sportspeople in (.+)"}, ["Fooian diaspora in Bar"] = {true, "(.+) diaspora in (.+)$"} } -- parse the pagename to find two countyName/countryAdjective pairs -- looks for one of 5 different types of category, -- as defined in categoryMasks{} -- Each of the 5 formats is tested in turn, until a format is found which -- matches the current pagename -- The return value is a string: -- "//success//" = matched a pattern, and built two countyName/countryAdjective pairs -- "//nomatch//" = did not match any pattern -- "//unknown//:sometext" = one of the countrynames or adjectives found in the title -- was not found in the lookup table -- "//error//" function parsePagename(pn) local splitResult = nil local nmasks = 0 debugLog(1, "parsePagename") debugLog(2, " pn = [" .. pn .."]") for catDescription, maskData in pairs(categoryMasks) do nmasks = nmasks + 1 debugLog(3, string.format("Mask #%d: catDescription=[%s], isNoun=[%s] pattern=[%s]" , nmasks, catDescription, tostring(maskData[1]), maskData[2])) splitResult = splitPagename(pn, maskData[1], "^" .. maskData[2] .. "$") if splitResult == "//success//" then return splitResult elseif splitResult == "//nomatch//" then -- do nothing. We'l just loop again and try the next mask elseif mw.ustring.match(splitResult, "^//unknown//") then return splitResult else return "//error//unexpected result from splitPagename" end end debugLog(2, "nmasks = ", tonumber(nmasks)) if splitResult == nil then splitResult = "splitResult=nil. Why????" end return splitResult end function splitPagename(pname, isNoun, pattern) debugLog(4, string.format("splitPagename: pname=[%s], isNoun=[%s], pattern=[%s]" , pname, tostring(isNoun), pattern)) if not mw.ustring.match(pname, pattern) then debugLog(5, "no match") return "//nomatch//" end local v1 = mw.ustring.gsub(pname, pattern, "%1") -- extract the "Fooian" athe start of the cat name local v2 = mw.ustring.gsub(pname, pattern, "%2") -- extract the "Foo" or "Fooian" athe start of the cat name debugLog(5, string.format("v1=[%s], v2=[%s]", v1, v2)) countryName1 = getCountryFromAdjective(v1) if countryName1 == nil then return "//unknown//adjective: " .. v1 end if isNoun then countryName2 = v2 countryName2 = stripThe(countryName2) if getAdjectiveFromCountry(countryName2) == nil then return "//unknown//noun: " .. v2 end else countryName2 = getCountryFromAdjective(v2) if countryName2 == nil then return "//unknown//adjective:" .. v2 end end return "//success//" end -- ###################### END NEWSTUFF ############################################### function publishDebugLog() if not debuggingEnabled 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 p.main(frame) local parent = frame:getParent() if parent then parentname = parent:getTitle():gsub('/sandbox$', '') end templateName = mw.ustring.gsub(parentname, "^Template:", "") -- get the page title debugLog(1, "mw.title.getCurrentTitle()") thispage = mw.title.getCurrentTitle() thispagename = thispage.text; 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") debugLog(2, "list categoryMasks") for x, y in ipairs(categoryMasks) do debugLog(3, "[" .. x .. "] = [" .. y .."]") end debugLog(1, "makeAdjectivesToNounsTable()") local nMade = makeAdjectivesToNounsTable() debugLog(2, string.format("makeAdjectivesToNounsTable() done: %d", nMade)) debugLog(1, "next call parsePagename()") local parseResult = parsePagename(thispagename) debugLog(1, "Parsed"); debugLog(2, string.format("parseResult=%s", parseResult)) debugLog(2, "countries found:") debugLog(3, "countryName1=") if (countryName1 == nil) then debugLog(nil, "nil") parseResult = parseResult .. " but countryName1 is nil" else debugLog(nil, string.format("[%s] .. and adjective = [%s]", countryName1, getAdjectiveFromCountry(countryName1))) end debugLog(3, "countryName2=") if countryName2 == nil then debugLog(nil, "nil") parseResult = parseResult .. " but countryName2 is nil" else debugLog(nil, string.format("[%s] .. and adjective = [%s]", countryName2, getAdjectiveFromCountry(countryName2))) end local myNavTable = ""; local myPortalsBox = "" if (parseResult ~= "//success//") then debugLog(1, "Not a success, so no makeTable()") else debugLog(1, "Calling makeTable") myNavTable = makeTable() debugLog(1, "Table made") debugLog(2, string.format("Greylinks: %d", greyLinkCount)) debugLog(1, "Making portals") -- myPortalsBox = makePortalBox() myPortalsBox = frame:expandTemplate{ title = 'Portal', args = {countryName1, countryName2} } debugLog(2, "Portals done") myTrackingCategories = makeTrackingCategory() end return publishDebugLog() .. myPortalsBox .. myNavTable .. myTrackingCategories end function makePortalBox() local myPortalsList = "" --[[ local myPortalsArray = {} if (doesPageExist(countryName1, "Portal")) then myPortalsList = myPortalsList .. "|" .. countryName1 myPortalsArray[#myPortalsArray + 1] = countryName1 end if (doesPageExist(countryName2, "Portal")) then myPortalsList = myPortalsList .. "|" .. countryName2 myPortalsArray[#myPortalsArray + 1] = countryName2 end local i, v for i, v in ipairs(defaultPortals) do if (doesPageExist(v, "Portal")) then myPortalsList = myPortalsList .. "|" .. v myPortalsArray[#myPortalsArray + 1] = countryName1 end end debugLog(2, string.format("Portal made.<br>myPortalsList = [%s]", myPortalsList)) -- showMyPortals(countryName1, countryName2) -- showMyPortals(myPortalsArray) ]] myPortalsList = frame:expandTemplate{ title = 'Portal', args = {countryName1, countryName2} } return myPortalsList end function makeAdjectivesToNounsTable() countriesPrefixedByThe = mw.loadData( 'Module:CountryNameDemonym/the' ) countryNounstoAdjectivesTable = mw.loadData( 'Module:CountryNameDemonym/adjectives' ) local myCounter = 0 local myNoun, myAdj for myNoun, myAdj in pairs(countryNounstoAdjectivesTable) do countryAdjectivesToNounsTable[myAdj] = myNoun myCounter = myCounter + 1 end return myCounter end return p