Module:GANList3

-- This module implements.

-- Load modules require('Module:No globals') local yesno = require('Module:Yesno') local data = mw.loadData('Module:GANList3/data') local responseIcons = data.responseIcons local statusIcons = data.statusIcons

-- Template for making collapsed sections. local COLLAPSED_WIKITABLE = [[

-- Template for making uncollapsed sections. local UNCOLLAPSED_WIKITABLE = [[

-- Helper functions

-- Make the given key in args lowercase if when lowercased it equals val. local function makeArgLowerCase(args, key, val) if args[key] and string.lower(args[key]) == val then args[key] = val end end

-- Normalize the args table to make it easier to work with elsewhere in the -- module. local function normalizeArguments(args) -- Consolidate aliases args.nocopyvio = args.nocopyvio or args.plagiarismfree args.plagiarismfree = nil

-- Normalize special values makeArgLowerCase(args, 'picfree', 'fair') makeArgLowerCase(args, 'status', 'wtf') end

-- If any of the keys in the keys array are in the table t, return true; -- otherwise, return false. local function anyKeysInTable(t, keys) for i, key in ipairs(keys) do		if t[key] then return true end end return false end

-- Make a wikitext error message. local function makeWikitextError(msg) return string.format('''&, msg) end

-- Format a user-supplied string for display in error messages. -- This prevents input from being displayed as special wiki markup, converts -- multi-line strings to a single line, and truncates long strings so that they -- are easier to read. local function escapeUserString(s) if #s &#x3e; 28 then s = s:sub(1, 12) .. '...' .. s:sub(-12, -1) end s = s:gsub("\n", " ") return mw.text.nowiki(s) end

-- Make a collapsed wikitable with the given header and content. local function makeCollapsedWikitable(header, content) return string.format(COLLAPSED_WIKITABLE, header, content) end

-- Make an uncollapsed wikitable with the given content. local function makeUncollapsedWikitable(content) return string.format(UNCOLLAPSED_WIKITABLE, content) end

-- Make a bulleted list from an array of strings. local function makeBulletedList(items) local ret = {} for i, item in ipairs(items) do ret[i] = '* ' .. item end return table.concat(ret, '\n') end

-- Make a checklist item from the given issue and status. local function makeChecklistItem(issue, status, defaultMarker) if not status then return string.format('%s: %s', issue, responseIcons.UNKNOWN) elseif yesno(status) then return string.format('%s: %s', issue, responseIcons.YES) else return string.format(			'%s: %s - %s',			issue,			defaultMarker or responseIcons.NO,			status		) end end

-- Return true if all issues have been resolved; return false otherwise. -- mainIssues is an array of tables as passed to makeSection. otherIssues is a -- string value or nil (hold, as passed to makeSection). local function allIssuesAreResolved(mainIssues, otherIssues) if otherIssues then return false end for i, t in ipairs(mainIssues) do		if t.isResolved == false or (				t.isResolved ~= true				and not yesno(t.status)			) then return false end end return true end

-- Assemble a section of the DYK checklist. local function makeSection(options) local issues = {}

-- Add main issues options.mainIssues = options.mainIssues or {} for i, t in ipairs(options.mainIssues) do		local checklistItem if t.isResolved then checklistItem = makeChecklistItem(t.issue, t.status, responseIcons.YES) else checklistItem = makeChecklistItem(t.issue, t.status) end table.insert(issues, checklistItem) end

-- Add other issues if options.otherIssues then table.insert(issues, makeChecklistItem('Other problems', options.otherIssues)) end

-- Make the section output. local content = makeBulletedList(issues) if allIssuesAreResolved(options.mainIssues, options.otherIssues) then return makeCollapsedWikitable(options.resolvedHeader, '\n' .. content) else return options.unresolvedHeader .. '\n' .. content end end

-- Section functions -- Each of these functions makes a single section of the DYK checklist.

local function makeWellWrittenEligibilitySection(args) return makeSection{ unresolvedHeader = "Well written?:", resolvedHeader = "Writing: article reasonably well written", mainIssues = { {				issue = 'Prose', status = args.prose, },			{				issue = 'Copyvio', status = args.nocopyvio, },			{				issue = 'MOS compliance', status = args.moscomply, },		},		otherIssues = args.writingother, } end

local function makeVerifiabilityComplianceSection(args) return makeSection{ unresolvedHeader = "Verifiable?:", resolvedHeader = "Verifiability: Article is factually accurate, verifiable, and contains no original research", mainIssues = { {				issue = 'Reference section', status = args.refsection, },			{				issue = 'Reliable sourcing', status = args.sourcing, },			{				issue = 'Original research', status = args.origresearch, },		},		otherIssues = args.verifyother, } end

local function makeNeutralEligibilitySection(args) -- The Neutrality and Stablity sections are different enough from the others -- that we will just do everything here rather than trying to use the -- makeSection function. local isGood = yesno(args.neutral) if isGood == true then return makeUncollapsedWikitable("Neutral: Acceptable.") else local ret = makeChecklistItem(			"Neutral",			isGood == false and 'Not good' or args.neutral		) return ret .. '&#x3c;br /&#x3e;' end end

local function makeStableEligibilitySection(args) local isStable = yesno(args.stable) if isStable == true then return makeUncollapsedWikitable("Stable: Yes.") else local ret = makeChecklistItem(			"Stable",			isStable == false and 'Not stable' or args.stable		) return ret .. '&#x3c;br /&#x3e;' end end

local function makeImageEligibilitySection(args) -- Deal with nonfree special case for images local imagesUsedStatus, isImageFairUse if args.picfree == 'fair' then imagesUsedStatus = 'Valid fair use image rationale supplied' isImageFairUse = true else imagesUsedStatus = args.picfree isImageFairUse = nil -- use default behaviour end

-- Generate output return makeSection{ unresolvedHeader = "Images?:", resolvedHeader = "Images: Article provides sufficient illustration relevant to topic.", mainIssues = { {				issue = 'Illustrated appropriately', status = args.illustrated, },			{				issue = 'Freely licensed', status = imagesUsedStatus, isResolved = isImageFairUse },			{				issue = 'Relevant with captions', status = args.picused, },		},		otherIssues = args.picother, } end

local function makeStatusSection(args) if not args.status then return makeWikitextError('Review is incomplete - please fill in the "status" field') elseif args.status ~= 'y'		and args.status ~= '?' and args.status ~= 'neu' and args.status ~= 'no' and args.status ~= 'hold' and args.status ~= 'wtf' then return makeWikitextError(string.format( 'Invalid status "%s" - use one of "y", "?", "neu", "no" or "hold"', escapeUserString(args.status) ))	end

local ret = {} table.insert(ret, "Overall: ") local isOK = yesno(args.status) if isOK == true then if args.picfree == 'fair' then table.insert(ret, statusIcons.YES_FAIR) else table.insert(ret, statusIcons.YES) end elseif isOK == false then table.insert(ret, statusIcons.NO) elseif args.status == '?' then table.insert(ret, statusIcons.QUESTION) elseif args.status == 'neutral' then table.insert(ret, statusIcons.NETURAL) elseif args.status == 'hold' then table.insert(ret, statusIcons.HOLD) elseif args.status == 'wtf' then table.insert(ret, statusIcons.CONFUSED) end if args.comments then table.insert(ret, ' ') table.insert(ret, args.comments) end if args.sign then table.insert(ret, ' ') table.insert(ret, args.sign) end return table.concat(ret) end

-- Exports

local p = {}

function p._main(args) -- Normalize the args table to make it easier to work with in other -- functions. normalizeArguments(args)

-- Check whether the review has been started. local params = { 'prose', 'nocopyvio', 'moscomply', 'writingother', 'refsection', 'sourcing', 'origresearch', 'verifyother', 'neutral', 'stable', 'illustrated', 'picfree', 'picused', 'picother', 'picfree', }	if not anyKeysInTable(args, params) then return 'Review not started' end

-- The review has been started, so assemble all the review sections. local funcs = { makeWellWrittenEligibilitySection, makeVerifiabilityComplianceSection, makeNeutralEligibilitySection, makeStableEligibilitySection, makeImageEligibilitySection, makeStatusSection, }	local ret = {} for i, func in ipairs(funcs) do		table.insert(ret, func(args)) end return table.concat(ret, '\n') end

function p.main(frame) local args = require('Module:Arguments').getArgs(frame, {		wrappers = 'Template:GANList3',	}) return p._main(args) end

return p