Module:UtilsPage

local p = {} local h = {}

local utilsCargo = require("Module:UtilsCargo") local utilsString = require("Module:UtilsString") local utilsTable = require("Module:UtilsTable")

local SEPARATOR = "#" function p.dpl(args) local dplArgs = "" for k, v in pairs(args) do		if k == "format" or type(v) == "table" and v.value == "format" then mw.addWarning(" argument cannot be used here. Format the resulting Lua table instead.") elseif type(v) == "table" then for _, andedValue in ipairs(v) do dplArgs = dplArgs .. h.appendArg(k, andedValue) end else dplArgs = dplArgs .. h.appendArg(k, v)		end end dplArgs = dplArgs .. h.appendArg("format", SEPARATOR..",,%PAGE%" .. SEPARATOR .. ",") local result = mw.getCurrentFrame:preprocess("") if not utilsString.endsWith(result, SEPARATOR) then return {} end result = string.gsub(result, SEPARATOR .. ":", SEPARATOR) -- strip : prefix from Category results result = utilsString.trim(result, SEPARATOR) result = utilsString.split(result, SEPARATOR) return result end function h.appendArg(param, value) value = tostring(value) value = string.gsub(value, "\|", "|") if param and value then return "|" .. param .. "=" .. value .. "\n" else return "" end end

function p.exists(fullPageName, noRedirect) local anchorStart = string.find(fullPageName, "#") if anchorStart then fullPageName = string.sub(fullPageName, 1, anchorStart - 1) end local queryResults = utilsCargo.query("_pageData", "_pageName, _isRedirect", {		where = utilsCargo.allOf({ _pageName = fullPageName })		})	return #queryResults > 0 and (not noRedirect or queryResults[1]._isRedirect == "0") end

function p.fullUrl(page, queryParams) local baseUrl = mw.site.server .. "/"	local pageUrl = baseUrl .. mw.uri.encode(page, "WIKI") if queryParams then local encodedParams = {} for k, v in pairs(queryParams) do local param = k .. "=" .. mw.uri.encode(tostring(v), "QUERY") table.insert(encodedParams, param) end local queryStr = "?" .. table.concat(encodedParams, "&") pageUrl = pageUrl .. queryStr end return pageUrl end

function p.getSubpages(fullPageName) local title = fullPageName and mw.title.new(fullPageName) or mw.title.getCurrentTitle local pages = p.dpl({		namespace= title.nsText,		titlematch= '%' .. title.text .. '/%',	}) table.sort(pages) return pages end

function p.inCategory(category, fullPageName) if (not category) or (not fullPageName) then return false end local title = mw.title.new(fullPageName) local dplResult = p.dpl({		category= p.stripNamespace(category),		namespace= title.nsText,		title= title.text,		skipthispage= "no",	}) return #dplResult ~= 0 end

function p.inNamespace(namespaces, fullPageName) if type(namespaces) == "string" then namespaces = {namespaces} end local title = fullPageName and mw.title.new(fullPageName) or mw.title.getCurrentTitle return utilsTable.includes(namespaces, title.nsText) end

function p.isRedirect(page) local anchorStart = string.find(page, "#") if anchorStart then page = string.sub(page, 1, anchorStart - 1) end local queryResults = utilsCargo.query("_pageData", "_pageName, _isRedirect", {		where = utilsCargo.allOf({ _pageName = page })		})	return #queryResults > 0 and queryResults[1]._isRedirect == "1" end

function p.stripNamespace(page, namespace) if not namespace then namespace = "[^:]*" end return string.gsub(page, ":?".. namespace..":", "") end

function p.Schemas return { exists = { fullPageName = { type = "string", required = true, desc = "Full page name with namespace prefix.", },			noRedirect = { type = "boolean", desc = "If true, redirects are not considered." },		},		fullUrl = { fullPageName = { type = "string", required = true, desc = "Full page name with namespace prefix.", },			queryParams = { type = "map", keys = { type = "string" }, values = { oneOf = { { type = "string" }, { type = "number" }, },				},				desc = ".", },		},		getSubpages = { fullPageName = { type = "string", desc = "A full page name with namespace prefix. If nil,  is used.", },		},		inCategory = { category = { type = "string", required = true, desc = "Category name with or without namespace prefix.", },			fullPageName = { type = "string", required = true, desc = "Full page name with namespace prefix." },		},		inNamespace = { namespaces = { desc = "A namespace or array of namespaces.", required = true, oneOf = { { type = "string" }, { type = "array", items = { type = "string" } } },			},			fullPageName = { type = "string", desc = "Full pagename. Defaults to the name of the current page." }		},		stripNamespace = { page = { required = true, type = "string", desc = "Pagename to strip namespace prefix from.", },			namespace = { type = "string", desc = "Namespace to strip. If nil, any namespace will be stripped." },		},	} end

function p.Documentation return { exists = { desc = 'Checks whether a page exists using the _pageData Cargo table. Unlike this function does not register a link in Special:WantedPages or Special:WhatLinksHere, nor does it count as an "expensive parser function."', params = {"fullPageName", "noRedirect"}, returns = "Boolean indicating whether the page exists.", cases = { {					args = {"OoT"}, expect = true, },				{					args = {"OoT", true}, expect = false, },				{					desc = "Works for files and file redirects too", args = {"File:OoT Bomb Bag Model.png"}, expect = true, },				{					args = {"File:MM Bomb Bag Model.png"}, expect = true, },				{					args = {"File:MM Bomb Bag Model.png", true}, expect = false, },				{					desc = "Ignores section anchors", args = {"Impa#Biography"}, expect = true, },			},		},		getSubpages = { params = {"fullPageName"}, returns = "A list of subpages", cases = { outputOnly = true, {					args = {"Module:Constants"}, },				{					args = {"Module:UtilsPage"}, },			},		},		fullUrl = { desc = "A performant alternative to . Unlike, it cannot translate interwiki links. To format the link as an internal link, see Module:UtilsMarkup.", params = {"fullPageName", "queryParams"}, returns = "The url for the specified wiki page.", cases = { {					args = {"Mipha's Grace"}, expect = "//zeldapedia.wiki/Mipha%27s_Grace", },				{					args = {"Special:Upload", { wpDestFile = "TWWHD Great Fairy Figurine Model.png" } }, expect = "//zeldapedia.wiki/Special:Upload?wpDestFile=TWWHD+Great+Fairy+Figurine+Model.png" },				{					args = {"New Page", { action = "edit", redlink = 1, }},					expect = "//zeldapedia.wiki/New_Page?action=edit&redlink=1", },			},		},		dpl = { desc = "This function is wrapper for the DPL parser function.", params = {"args"}, returns = "Array of results. Results are limited to a 500 maximum.", cases = { {					args = { {titlematch = "Link|Zelda", namespace = "Category"} }, expect = {"Category:Link", "Category:Zelda"} },				{					desc = "Repeating arguments", args = { {							category = "Lynels", notcategory = { "Enemies in A Link Between Worlds", "Enemies in Breath of the Wild", "Enemies in Hyrule Warriors: Age of Calamity", },						},					},					expect = {"Purple Lynel", "Blue Lynel"}, },			},		},		inCategory = { params = {"category", "fullPageName"}, returns = "A boolean indicating whether the given page is a member of the given category.", cases = { {					desc = "Works with or without the namespace prefix.", args = {"Characters in Breath of the Wild", "Link"}, expect = true, },				{					args = {"Category:Characters", "Link"}, expect = true, },				{					args = {"Items", "Link"}, expect = false, },				{					args = {"Fakecategory", "Link"}, expect = false, },				{					desc = "For pages not in the main namespace, the namespace prefix is required.", args = {"Characters by Game", "Characters in Breath of the Wild"}, expect = false, },				{					args = {"Characters by Game", "Category:Characters in Breath of the Wild"}, expect = true, },			},		},		inNamespace = { params = {"namespaces", "fullPageName"}, returns = " if and only if   (or the current page) has a namespace prefix that is one of , regardless of whether the page actually exists.", cases = { {					desc = "Main namespace is the empty string.", args = {"", "Link"}, expect = true, },				{					args = {"Category", "Link"}, expect = false, },				{					args = {"Category", "Category:Link"}, expect = true, },				{					desc = "Can evaluate to true even when page does not exist.", args = {"Category", "Category:Flippityfloppityfloo"}, expect = true, },				{					desc = "Current page", args = {"Module"}, expect = true, },				{					desc = "Multiple namespaces", args = {{"User", "MediaWiki"}, "Princess Zelda"}, expect = false, },				{					args = {{"User", "MediaWiki"}, "User:Abdullah"}, expect = true, },			},		},		isRedirect = { desc = 'Checks whether a page is a redirect using the _pageData Cargo table. Unlike this function does not register a link in Special:WantedPages or Special:WhatLinksHere, nor does it count as an "expensive parser function."', params = {"page"}, returns = " if the page is a redirect,   otherwise.", cases = { {					args = {"OoT"}, expect = true, },				{					args = {"The Legend of Zelda: Ocarina of Time"}, expect = false, },				{					args = {"Notapage"}, expect = false, },			},		},		stripNamespace = { params = {"page", "namespace"}, returns = " with namespace prefix stripped off.", cases = { outputOnly = true, {					args = {"Category:Items in Breath of the Wild", "Category"}, expect = "Items in Breath of the Wild", },				{					args = {"Items in Breath of the Wild", "Category"}, expect = "Items in Breath of the Wild", },				{					args = {"Category:Items in Breath of the Wild", "File"}, expect = "Category:Items in Breath of the Wild", },				{					args = {"File:TWWHD Tingle Model.png", "File"}, expect = "TWWHD Tingle Model.png", },				{					args = {"File:TWWHD Tingle Model.png"}, expect = "TWWHD Tingle Model.png", },				{					args = {":Category:Items in Breath of the Wild"}, expect = "Items in Breath of the Wild", }			}		}	} end

return p