Module:Sandbox/Aidan9382/RSP
Jump to navigation
Jump to search
Sandbox for testing various ways of combatting the current PEIS issue on WP:RSN - see discussions at WT:LUA ยง Lua programmer needed for short project related to Perennial sources page and Module talk:RSPTest/sandbox for the origin of this
local p = {}
local TopLevelPage = "Wikipedia:Reliable sources/Perennial sources"
local function getWikilinks(str)
local out = {}
for part in str:gmatch("%[%b[]%]") do
table.insert(out, part:sub(3, -3))
end
return out
end
local function uniqueletter(n) -- generates A-Z AA-AZ BA-BZ etc. for discussions
return n > 26 and string.char(64+math.floor((n-1)/26), 65+((n-1)%26)) or string.char(64+n)
end
-- temporary lazy table version
local RSPStatuses = {
gr = "data-sort-value=0|[[File:Yes Check Circle.svg|20px|Generally reliable|link=%s#Generally reliable]]",
nc = "data-sort-value=1|[[File:Achtung-orange.svg|20px|No consensus|link=%s#No consensus]]",
gu = "data-sort-value=2|[[File:Argentina - NO symbol.svg|20px|Generally unreliable|link=%s#Generally unreliable]]",
d = "data-sort-value=3|[[File:Stop hand.svg|20px|Deprecated|link=%s#Deprecated]]",
}
RSPStatuses.m = RSPStatuses.nc -- alias
-- Experimental tetmplate-entry testing
function p.status(frame)
local args = require("Module:Arguments").getArgs(frame)
local status = args[1] or args.status
local blacklisted = args.b or args.blacklisted
local full_link = mw.title.getCurrentTitle().prefixedText == TopLevelPage and "" or TopLevelPage
local class = blacklisted and "b" or status
local status_str = RSPStatuses[status]:format(full_link)
if blacklisted then
local blacklist_image = ("[[File:X-circle.svg|20px|Blacklisted|link=%s#Blacklisted]] "):format(full_link)
-- super stupid way of doing this for now
status_str = status_str:gsub("data%-sort%-value=(%d)|", "data-sort-value=1%1|" .. blacklist_image)
end
return status_str
end
local EmittedShortcutStyle = false
local function RSPShortcut(title)
local templatestyle = ""
if not EmittedShortcutStyle then
local frame = mw.getCurrentFrame()
templatestyle = frame:extensionTag({name="templatestyles", args={src="Wikipedia:Reliable sources/Perennial sources/Shortcut/styles.css"}})
EmittedShortcutStyle = true
end
local shortcut_url = tostring(mw.uri.fullUrl(title, {redirect="no"}))
local shortcut_link = "<span class=\"plainlinks\">["..shortcut_url.." "..title.."]</span><span style=\"display: none\">[["..title.."]]</span>"
return "<br/>" .. templatestyle .. "<span class=\"wp-rsp-sc\">" .. shortcut_link .. " ๐</span>"
end
-- Experimental tetmplate-entry testing
function p.shortcut(frame)
local args = require("Module:Arguments").getArgs(frame)
return RSPShortcut(args[1] or args.title)
end
local function GatherDiscussions(rfcs, discussions)
local discussion_lists = {}
if rfcs then
local segment = {}
local rfc_image = "[[File:Treffpunkt.svg|20px|Request for comment|link=]] "
local blacklist_image = "[[File:X-circle.svg|20px|alt=Spam blacklist request|link=]] "
for i, rfc in ipairs(rfcs) do
-- Check for the convenience RSN shorthand
if rfc:match("^/Archive[ _]%d+") or rfc:match("^#") then
rfc = "WP:Reliable sources/Noticeboard" .. rfc
end
local image = rfc_image
-- Check if it's for the spam blacklist
if rfc:match("^/%a+[ _]2%d%d%d#") then
rfc = "MediaWiki talk:Spam-blacklist/archives" .. rfc
image = blacklist_image
elseif rfc:match("^/archives/") then
rfc = "MediaWiki talk:Spam-blacklist" .. rfc
image = blacklist_image
elseif rfc:match(":Spam-blacklist/") then
image = blacklist_image
end
table.insert(segment, image .. "[[" .. rfc .. "]]")
end
table.insert(discussion_lists, table.concat(segment, " "))
end
if discussions then
local segment = {}
local rsn_count = 0
local other_count = 0
for i, discussion in ipairs(discussions) do
discussion = discussion:match("^(.-)|") or discussion -- ignore user-provided piping
-- Check if it's an RSN discussion
local is_rsn = false
if discussion:match("^/Archive[ _]%d+") or discussion:match("^#") then
discussion = "WP:Reliable sources/Noticeboard" .. discussion
is_rsn = true
elseif discussion:match(":Reliable[ _]sources/Noticeboard") or discussion:match(":RSN") then
is_rsn = true
end
if is_rsn then
rsn_count = rsn_count + 1
discussion = discussion .. "|" .. rsn_count
else
other_count = other_count + 1
discussion = discussion .. "|" .. uniqueletter(other_count)
end
table.insert(segment, "[[" .. discussion .. "]]")
end
if #discussions >= 8 then
local combined = table.concat(segment, " ")
local frame = mw.getCurrentFrame()
-- TODO: Provide a simple name here instead of just saying "oh look more discussions!"
local ref_text = frame:extensionTag({name="ref", content="See also these discussions: " .. combined, args={group="lower-alpha"}})
table.insert(discussion_lists, "+"..#discussions .. ref_text)
else
table.insert(discussion_lists, table.concat(segment, " "))
end
end
return table.concat(discussion_lists, "\n")
end
-- Experimental tetmplate-entry testing
function p.discussions(frame)
local args = require("Module:Arguments").getArgs(frame)
return GatherDiscussions(getWikilinks(args.rfcs or ""), getWikilinks(args.discussions or ""))
end
local function RSPLast(year, inprogress, stale)
if not year then
return "data-sort-value=0|(Unknown)"
end
inprogress = inprogress and inprogress ~= ""
stale = stale or "auto"
local full_link = mw.title.getCurrentTitle().prefixedText == TopLevelPage and "" or TopLevelPage
local out = "data-sort-value=" .. (inprogress and "1" or "") .. year .. "|"
if inprogress then
out = out .. "[[File:Pictogram voting wait.svg|20px|Discussion in progress|link="..full_link.."#Discussion in progress]]"
else
local cur_year = os.date("*t").year
local is_stale = stale == "y" or (stale ~= "n" and cur_year-3 > tonumber(year))
if is_stale then
out = out .. "[[File:Farm-Fresh hourglass delete.png|20px|Stale discussions|link=" ..full_link.."#Stale discussions]]"
end
end
return out .. "\n" .. year
end
-- Experimental tetmplate-entry testing
function p.last(frame)
local args = require("Module:Arguments").getArgs(frame)
return RSPLast(args[1] or args.year, args.inprogress, args.stale)
end
local function DomainUses(domains)
local out = {}
for i, domain in ipairs(domains) do
local encoded = mw.uri.encode(domain, "PATH")
table.insert(out,
"[[Special:Search/insource:\""..domain.."\"|"..i.."]] " ..
"[[File:OOjs UI icon link-ltr.svg|16px|Links|link=Special:Linksearch/*."..encoded.."|class=skin-invert]] " ..
"[[File:OOjs UI icon check.svg|16px|Spamcheck|link=https://spamcheck.toolforge.org/by-domain?q="..encoded.."|class=skin-invert]]"
)
end
out = table.concat(out, "<br>")
if #domains >= 4 then
-- TODO: this is a lazy solution :(
local frame = mw.getCurrentFrame()
out = frame:preprocess("{{show begin}}") .. '<div class="center" style="width:auto;margin-left:auto;margin-right:auto;clear:both">' .. out .. '</div></div></div>'
end
return out
end
-- Experimental tetmplate-entry testing
function p.domains(frame)
local args = require("Module:Arguments").getArgs(frame)
local domains = {}
local i = 1
while true do
if not args[i] then
break
end
domains[i] = args[i]
i = i + 1
end
return DomainUses(domains)
end
-- Module entry point for generating a row
function p._row(args)
assert(args.name, "A name is required")
assert(args.status and RSPStatuses[args.status], "A valid status is required")
assert(args.id, "An id is required")
assert(args.summary, "A summary is required")
-- Create shortcut if it exists
local shortcut_text = args.shortcut and " " .. RSPShortcut(args.shortcut) or ""
-- Handle the status info
local full_link = mw.title.getCurrentTitle().prefixedText == TopLevelPage and "" or TopLevelPage
local class = args.blacklisted and "b" or args.status
local status = RSPStatuses[args.status]:format(full_link)
if args.blacklisted then
local blacklist_image = ("[[File:X-circle.svg|20px|Blacklisted|link=%s#Blacklisted]] "):format(full_link)
-- super stupid way of doing this for now
status = status:gsub("data%-sort%-value=(%d)|", "data-sort-value=1%1|" .. blacklist_image)
end
-- Gather discussion links
local discussion_text = args.discussions_raw -- fallback, just in case
if not discussion_text then
discussion_text = GatherDiscussions(args.rfcs, args.discussions)
end
-- Add a name sort if specified
local sort_value = args.sort and "data-sort-value=\"" .. args.sort .. "\"|" or ""
-- Sort domain links
local domain_text = args.domains and DomainUses(args.domains) or ""
-- Put it all together
local row_text =
"|- class=\"s-" .. class .. "\" id=\"" .. args.id .. "\"" ..
"\n| " .. sort_value .. args.name .. shortcut_text ..
"\n| " .. status ..
"\n| " .. discussion_text ..
"\n| " .. RSPLast(args.last or args.year, args.inprogress, args.stale) ..
"\n| " .. args.summary ..
"\n| " .. domain_text
-- Mark deprecated entries with a <section> tag
if args.status == "d" then
local frame = mw.getCurrentFrame()
local section_begin = frame:extensionTag({name="section", args={begin="deprecated"}})
local section_end = frame:extensionTag({name="section", args={['end']="deprecated"}})
row_text = section_begin .. "\n" .. row_text .. "\n" .. section_end
end
return row_text
end
-- Template entry point for generating a row
function p.row(frame)
local args = require("Module:Arguments").getArgs(frame)
-- turn string arguments into a table form
args.domains = args.domains and mw.text.split(args.domains, ", ?\n?")
args.rfcs = getWikilinks(args.rfcs or "")
args.discussions = getWikilinks(args.discussions or "")
return p._row(args)
end
return p