Documentation for this module may be created at Module:UtilsPage/doc
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("<code>format</code> 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("{{#dpl:" .. dplArgs .. "}}") 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 = "{{Wp|Query string|Query parameters}}.", }, }, getSubpages = { fullPageName = { type = "string", desc = "A full page name with namespace prefix. If nil, <code>mw.title.getCurrentTitle()</code> 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 [[Special:CargoTables/_pageData|_pageData]] Cargo table. Unlike {{Scribunto Manual|lib=mw.title}} 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 {{Scribunto Manual|lib=mw.uri.fullUrl}}. Unlike <code>mw.uri.fullUrl</code>, it cannot translate interwiki links. To format the link as an internal link, see [[Module:UtilsMarkup#link]].", params = {"fullPageName", "queryParams"}, returns = "The url for the specified wiki page.", cases = { { args = {"Mipha's Grace"}, expect = "//zeldawiki.wiki/Mipha%27s_Grace", }, { args = {"Special:Upload", { wpDestFile = "TWWHD Great Fairy Figurine Model.png" } }, expect = "//zeldawiki.wiki/Special:Upload?wpDestFile=TWWHD+Great+Fairy+Figurine+Model.png" }, { args = {"New Page", { action = "edit", redlink = 1, }}, expect = "//zeldawiki.wiki/New_Page?action=edit&redlink=1", }, }, }, dpl = { desc = "<p>This function is wrapper for the [[gphelp:Extension:DPL3/Manual|DPL]] parser function.</p>" .. "<p>When constructing queries, keep in mind DPL's [https://www.mediawiki.org/wiki/Extension:DynamicPageList3#Configuration configured limits].</p>" .. "<ul>" .. "<li>A single query can return no more than 500 results. (<code>maxResultCount</code>)</li>" .. "<li>A single query using <code>category</code> selection may contain no more than 4 categories. (<code>maxCategoryCount</code>)</li>" .. "</ul>", params = {"args"}, returns = "Array of results.", cases = { { args = { {titlematch = "Link|Zelda", namespace = "Category"} }, expect = {"Category:Link", "Category:Zelda"} }, { desc = "Repeating arguments", args = { { category = "Lynels", notcategory = { "Sub-Bosses", "Enemies in Hyrule Warriors: Age of Calamity", }, }, }, expect = {"Blue Lynel", "Red 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 = "<code>true</code> if and only if <code>fullPageName</code> (or the current page) has a namespace prefix that is one of <code>namespaces</code>, 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 [[Special:CargoTables/_pageData|_pageData]] Cargo table. Unlike {{Scribunto Manual|lib=mw.title}} 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 = "<code>true</code> if the page is a redirect, <code>false</code> 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 = "<code>page</code> 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