<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://the-democratika.com/wiki/index.php?action=history&amp;feed=atom&amp;title=Module%3AStr_find_word</id>
	<title>Module:Str find word - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://the-democratika.com/wiki/index.php?action=history&amp;feed=atom&amp;title=Module%3AStr_find_word"/>
	<link rel="alternate" type="text/html" href="https://the-democratika.com/wiki/index.php?title=Module:Str_find_word&amp;action=history"/>
	<updated>2026-04-04T14:52:05Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.0</generator>
	<entry>
		<id>https://the-democratika.com/wiki/index.php?title=Module:Str_find_word&amp;diff=6634&amp;oldid=prev</id>
		<title>&gt;Lemondoge: Undid revision 1147915801 by Lemondoge (talk): oh dear. I checked with testcases - don&#039;t know how this goofed</title>
		<link rel="alternate" type="text/html" href="https://the-democratika.com/wiki/index.php?title=Module:Str_find_word&amp;diff=6634&amp;oldid=prev"/>
		<updated>2023-04-03T00:35:55Z</updated>

		<summary type="html">&lt;p&gt;Undid revision 1147915801 by &lt;a href=&quot;/wiki/index.php/Special:Contributions/Lemondoge&quot; title=&quot;Special:Contributions/Lemondoge&quot;&gt;Lemondoge&lt;/a&gt; (&lt;a href=&quot;/wiki/index.php?title=User_talk:Lemondoge&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;User talk:Lemondoge (page does not exist)&quot;&gt;talk&lt;/a&gt;): oh dear. I checked with testcases - don&amp;#039;t know how this goofed&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;require(&amp;#039;strict&amp;#039;)&lt;br /&gt;
local p = {}&lt;br /&gt;
local getArgs = require(&amp;#039;Module:Arguments&amp;#039;).getArgs&lt;br /&gt;
local str = require(&amp;#039;Module:String&amp;#039;)&lt;br /&gt;
local yesno = require(&amp;#039;Module:Yesno&amp;#039;)&lt;br /&gt;
local defaultSep = &amp;#039;,&amp;#039;&lt;br /&gt;
local iMaxWords = 16&lt;br /&gt;
local warningIMaxWordsReached = nil&lt;br /&gt;
local xpLitWordCount = 0&lt;br /&gt;
local report -- to be initinated when explain needed&lt;br /&gt;
&lt;br /&gt;
-- Initialise the /report subpage.&lt;br /&gt;
-- only invoked when &amp;#039;explain&amp;#039; asked&lt;br /&gt;
local function initReport()&lt;br /&gt;
	report = require(&amp;#039;Module:Str find word/report&amp;#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Turn &amp;quot;&amp;amp;#x0041;&amp;quot; into &amp;quot;A&amp;quot; etc. asap&lt;br /&gt;
-- and reduce multi-spaces (including nbsp etc.) into single space&lt;br /&gt;
local function decodeUnicode(str)&lt;br /&gt;
	return mw.ustring.gsub(mw.text.decode(str), &amp;#039;%s+&amp;#039;, &amp;#039; &amp;#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- %-Escape any word (character string) before feeding it into a string pattern function&lt;br /&gt;
-- all punctuation (%p) will be %-escaped&lt;br /&gt;
local function escape_word(word)&lt;br /&gt;
	return str._escapePattern(word)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Reads and parses a word list and returns a table with words (simple array)&lt;br /&gt;
-- words list can be: source, andwords-to-check, orwords-to-check&lt;br /&gt;
-- step 1: when case-insensitive, turn string into lowercase&lt;br /&gt;
-- step 2: read &amp;amp; remove Literals (&amp;quot;..&amp;quot;)&lt;br /&gt;
-- step 3: read comma-separated words&lt;br /&gt;
-- step 4: when booleans=T, change boolean words into true/false (module:yesno rules)&lt;br /&gt;
--		all words returned are trimmed, TODO and all ws into single-plainspace?&lt;br /&gt;
--		only T/F words are edited, other words remain, untouched&lt;br /&gt;
-- return the table (a straight array)&lt;br /&gt;
local function buildWordTable(tArgs, sWordlist)&lt;br /&gt;
local wordTable = {}&lt;br /&gt;
local hitWord	= &amp;#039;&amp;#039;&lt;br /&gt;
local hitCount	= 0&lt;br /&gt;
	if sWordlist == &amp;#039;&amp;#039; then return wordTable end&lt;br /&gt;
&lt;br /&gt;
	-- Step 1: case-sensitive&lt;br /&gt;
	if yesno(tArgs.case, true) == false then&lt;br /&gt;
		sWordlist = string.lower(sWordlist)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Step 2: read &amp;quot;literals&amp;quot;, &lt;br /&gt;
	-- then remove them from the string:&lt;br /&gt;
	-- replaced by single comma; idle &amp;amp; keeps word separation&lt;br /&gt;
	--- if yesno(tArgs.literals, false) then&lt;br /&gt;
	if false then&lt;br /&gt;
		local _, sCount&lt;br /&gt;
		_, sCount = mw.ustring.gsub(sWordlist, &amp;#039;&amp;quot;&amp;#039;, &amp;#039;&amp;#039;)&lt;br /&gt;
		if sCount &amp;gt; 1 then&lt;br /&gt;
			local litWord = &amp;#039;&amp;#039;&lt;br /&gt;
			local i, j&lt;br /&gt;
&lt;br /&gt;
			while sCount &amp;gt; 1 do -- could do here: only when even?&lt;br /&gt;
				i = string.find(sWordlist, &amp;#039;%&amp;quot;&amp;#039;, 1, false)&lt;br /&gt;
				j = string.find(sWordlist, &amp;#039;%&amp;quot;&amp;#039;, i+1, false)&lt;br /&gt;
				litWord = mw.text.trim(string.sub(sWordlist, i+1, j-1))&lt;br /&gt;
				if #litWord &amp;gt; 0 then -- not an empty string or spaces only&lt;br /&gt;
					xpLitWordCount = xpLitWordCount + 1&lt;br /&gt;
					table.insert(wordTable, litWord)&lt;br /&gt;
				end&lt;br /&gt;
				-- remove from source, and do next gsub search:&lt;br /&gt;
				sWordlist = string.gsub(sWordlist, &amp;#039;%&amp;quot;%s*&amp;#039;&lt;br /&gt;
												.. escape_word(litWord) &lt;br /&gt;
												.. &amp;#039;%s*%&amp;quot;&amp;#039;, &amp;#039;,&amp;#039;)&lt;br /&gt;
				_, sCount = mw.ustring.gsub(sWordlist, &amp;#039;&amp;quot;&amp;#039;, &amp;#039;&amp;#039;)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Step 3: parse comma-delimited words&lt;br /&gt;
	hitCount = 0&lt;br /&gt;
	sWordlist = tArgs.sep .. sWordlist .. tArgs.sep&lt;br /&gt;
	local eSep&lt;br /&gt;
	eSep = escape_word(tArgs.sep)&lt;br /&gt;
	local patstring = &amp;#039;%f[^&amp;#039; .. eSep .. &amp;#039;][^&amp;#039; .. eSep .. &amp;#039;]+%f[&amp;#039; .. eSep .. &amp;#039;]&amp;#039;&lt;br /&gt;
	if yesno(tArgs.explain, false) then&lt;br /&gt;
		report.xpMessage(&amp;#039;1.eSep: &amp;#039; .. eSep) -- dev&lt;br /&gt;
		report.xpMessage(&amp;#039;2.pattern: &amp;#039; .. patstring) -- dev&lt;br /&gt;
	end&lt;br /&gt;
 	while hitCount &amp;lt;= iMaxWords do&lt;br /&gt;
		hitCount = hitCount + 1&lt;br /&gt;
		&lt;br /&gt;
		hitWord = str._match(sWordlist, patstring, 1, hitCount, false, tArgs.sep)&lt;br /&gt;
		hitWord = mw.text.trim(hitWord)&lt;br /&gt;
		if hitWord == tArgs.sep then&lt;br /&gt;
			-- no more words found in the string&lt;br /&gt;
			break&lt;br /&gt;
		elseif hitWord ~= &amp;#039;&amp;#039; then&lt;br /&gt;
			table.insert(wordTable, hitWord)&lt;br /&gt;
		end&lt;br /&gt;
 	end&lt;br /&gt;
 	if hitCount &amp;gt; iMaxWords then &lt;br /&gt;
	 	warningIMaxWordsReached = &amp;#039;Max number of words (&amp;#039; .. tostring(iMaxWords) .. &amp;#039;) reached. Extra words are ignored.&amp;#039;&lt;br /&gt;
	 								.. &amp;#039; (&amp;#039; .. mw.ustring.sub(mw.text.trim(sWordlist), 1, 90) .. &amp;#039;&amp;amp;nbsp;...). &amp;#039;&lt;br /&gt;
 	end&lt;br /&gt;
&lt;br /&gt;
	-- Step 4: when read booleans, converse words to true/false&lt;br /&gt;
	-- todo: check parameter here not elsewhere&lt;br /&gt;
	if tArgs.booleans then -- TODO if Yesno(tArgs.booleans) ... &lt;br /&gt;
		local sBool&lt;br /&gt;
		for i, v in ipairs(wordTable) do&lt;br /&gt;
			sBool = yesno(v)&lt;br /&gt;
			if sBool ~= nil then&lt;br /&gt;
				wordTable[i] = tostring(sBool)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return wordTable&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Check whether a single word is in a table (a simple array of words)&lt;br /&gt;
-- returns hitword or nil&lt;br /&gt;
local function findWordInTable(sourceWordTable, word)&lt;br /&gt;
	local bHit = false&lt;br /&gt;
	for i, v in ipairs(sourceWordTable) do&lt;br /&gt;
		if v == word then&lt;br /&gt;
			bHit = true&lt;br /&gt;
			break&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if bHit then&lt;br /&gt;
		return word&lt;br /&gt;
	else&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- AND-logic with andWordTable words: ALL words must be found&lt;br /&gt;
-- returns {T/F, hittable}&lt;br /&gt;
--		T when *all* AND words are found&lt;br /&gt;
--		hittable with all hit words&lt;br /&gt;
-- note 1: when F, the hittable still contains the words that were found&lt;br /&gt;
-- note 2: empty AND-wordlist =&amp;gt; True by logic (because: not falsified)&lt;br /&gt;
local function checkANDwords(sourceWordTable, andWordTable)&lt;br /&gt;
local result1&lt;br /&gt;
local bAND&lt;br /&gt;
local tHits&lt;br /&gt;
&lt;br /&gt;
	bAND = true&lt;br /&gt;
	tHits = {}&lt;br /&gt;
	result1 = nil&lt;br /&gt;
	if #andWordTable &amp;gt; 0 then&lt;br /&gt;
		for i, word in ipairs(andWordTable) do&lt;br /&gt;
			result1 = findWordInTable(sourceWordTable, word) or nil&lt;br /&gt;
			if result1 == nil then&lt;br /&gt;
				bAND = false -- Falsified!&lt;br /&gt;
				-- could break after this logically but &lt;br /&gt;
				-- continue to complete the table (bAND remains false)&lt;br /&gt;
			else&lt;br /&gt;
				table.insert(tHits, result1)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		bAND = true&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return bAND, tHits&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- OR-logic with orWordTable words: at least one word must be found&lt;br /&gt;
-- returns {T/F, hittable}&lt;br /&gt;
--		True when at least one OR word is found&lt;br /&gt;
--		hittable has all hit words&lt;br /&gt;
-- note 1: empty OR-wordlist =&amp;gt; True by logic (because: not falsified)&lt;br /&gt;
-- note 2: while just one hitword is a True result, the hittable contains all words found&lt;br /&gt;
local function checkORwords(sourceWordTable, orWordTable)&lt;br /&gt;
local result1&lt;br /&gt;
local bOR&lt;br /&gt;
local tHits&lt;br /&gt;
&lt;br /&gt;
	bOR = false&lt;br /&gt;
	tHits = {}&lt;br /&gt;
	result1 = nil&lt;br /&gt;
	if #orWordTable &amp;gt; 0 then&lt;br /&gt;
		for i, word in ipairs(orWordTable) do&lt;br /&gt;
			result1 = findWordInTable(sourceWordTable, word) or nil&lt;br /&gt;
			if result1 == nil then&lt;br /&gt;
				-- this one is false; bOR unchanged; do next&lt;br /&gt;
			else&lt;br /&gt;
				bOR = true -- Confirmed!&lt;br /&gt;
				table.insert(tHits, result1)&lt;br /&gt;
				-- could break here logically, but complete the check&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		bOR = true&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return bOR, tHits&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Determine the requested return value (string).&lt;br /&gt;
-- sYeslist is the _main return value (logically defined value)&lt;br /&gt;
-- this function applies tArgs.yes / tArgs.no return value&lt;br /&gt;
-- note: yes=&amp;#039;&amp;#039; implies: blank return value&lt;br /&gt;
-- note: no parameter yes= (that is, yes=nil) implies: by default, return the sYeslist&lt;br /&gt;
local function yesnoReturnstring(tArgs, sYeslist)&lt;br /&gt;
	if sYeslist == &amp;#039;&amp;#039; then -- False &lt;br /&gt;
		return tArgs.no or &amp;#039;&amp;#039;&lt;br /&gt;
	else -- True&lt;br /&gt;
		if tArgs.yes == nil then&lt;br /&gt;
			return sYeslist&lt;br /&gt;
		else -- some |yes= value is entered, could be &amp;#039;&amp;#039;&lt;br /&gt;
			return tArgs.yes&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function isPreview()&lt;br /&gt;
local ifPreview = require(&amp;#039;Module:If preview&amp;#039;)&lt;br /&gt;
	return not (ifPreview._warning( {&amp;#039;is_preview&amp;#039;} ) == &amp;#039;&amp;#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Explain options (=report info), interprets parameter explain=&lt;br /&gt;
-- returns true/false/&amp;#039;testcases&amp;#039;&lt;br /&gt;
-- explain=true =&amp;gt; show report in Preview&lt;br /&gt;
-- explain=testcases =&amp;gt; WHEN in ns: template: or user: AND subpage = &amp;#039;/testcases&amp;#039; THEN show permanently&lt;br /&gt;
local function checkExplain(tArgs)&lt;br /&gt;
	return false  -- never. 22Mar2023 checkExplain(newArgs)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- ===== ===== ===== ===== ===== ===== ===== ===== ===== ===== ===== ===== =====&lt;br /&gt;
-- _main function: check for presence of words in source string&lt;br /&gt;
-- Checks and returns:&lt;br /&gt;
--		when T: the string of all hitwords (default), or the |yes=... input&lt;br /&gt;
--		when F: empty string &amp;#039;&amp;#039; (default), or the |no=... input&lt;br /&gt;
-- steps:&lt;br /&gt;
-- 1. input word strings are prepared (parsed into an array of words)&lt;br /&gt;
-- 2. words checks are made (applying AND-logic, OR-logic)&lt;br /&gt;
-- 3. final conclusion drawn (T/F)&lt;br /&gt;
-- 4. optionally, the preview report is prepared (debug, feedback)&lt;br /&gt;
-- 5. based on T or F status, the return value (string) is established and returned&lt;br /&gt;
-- note 1: each return value (yes=.., no=..) can be &amp;#039;&amp;#039; (nulstring)&lt;br /&gt;
function p._main(tArgs)&lt;br /&gt;
local sourceWordTable	= {}&lt;br /&gt;
local andWordTable		= {}&lt;br /&gt;
local orWordTable		= {}&lt;br /&gt;
local tANDhits&lt;br /&gt;
local tORhits&lt;br /&gt;
-- logical finding:&lt;br /&gt;
local bANDresult	= false&lt;br /&gt;
local bORresult 	= false&lt;br /&gt;
local resultALL 	= false&lt;br /&gt;
local sYeslist		= &amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
	sourceWordTable	= buildWordTable(tArgs, tArgs.source)&lt;br /&gt;
	andWordTable	= buildWordTable(tArgs, tArgs.andString)&lt;br /&gt;
	orWordTable		= buildWordTable(tArgs, tArgs.orString)&lt;br /&gt;
&lt;br /&gt;
	if (#sourceWordTable == 0) or (#andWordTable + #orWordTable == 0) then&lt;br /&gt;
		-- No words to check&lt;br /&gt;
		resultALL = false&lt;br /&gt;
		if yesno(tArgs.explain, false) then&lt;br /&gt;
			report.xpNoWords(tArgs, sourceWordTable, andWordTable, orWordTable)&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		bANDresult, tANDhits	= checkANDwords(sourceWordTable, andWordTable)&lt;br /&gt;
		bORresult, tORhits		= checkORwords(sourceWordTable, orWordTable)&lt;br /&gt;
		resultALL = (bANDresult) and (bORresult)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	sYeslist = &amp;#039;&amp;#039;&lt;br /&gt;
	if resultALL then&lt;br /&gt;
		-- concat the sYeslist (= all hit words; from 2 tables)&lt;br /&gt;
		if bANDresult then&lt;br /&gt;
			sYeslist = sYeslist .. table.concat(tANDhits, tArgs.sep)&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		if #tORhits &amp;gt; 0 then&lt;br /&gt;
			if #tANDhits &amp;gt; 0 then&lt;br /&gt;
				sYeslist = sYeslist .. tArgs.sep&lt;br /&gt;
			end&lt;br /&gt;
			sYeslist = sYeslist .. table.concat(tORhits, tArgs.sep)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if yesno(tArgs.explain, false) then&lt;br /&gt;
		if tArgs.yes ~= nil then&lt;br /&gt;
			if (tArgs.yes == &amp;#039;&amp;#039;) and (tArgs.no == &amp;#039;&amp;#039;) then&lt;br /&gt;
				report.xpYesNoBothBlank()&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		if warningIMaxWordsReached ~= nil then&lt;br /&gt;
			report.xpMessage(warningIMaxWordsReached)&lt;br /&gt;
		end&lt;br /&gt;
		report.xpBuildReport(tArgs, sourceWordTable, &lt;br /&gt;
						bANDresult, andWordTable, tANDhits,&lt;br /&gt;
						bORresult, orWordTable, tORhits,&lt;br /&gt;
						sYeslist, xpLitWordCount)&lt;br /&gt;
	end&lt;br /&gt;
	return yesnoReturnstring(tArgs, sYeslist)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- set wordt separator &lt;br /&gt;
local function setSep(sSep)&lt;br /&gt;
	if sSep == nil then return defaultSep end&lt;br /&gt;
	local msg = &amp;#039;&amp;#039;&lt;br /&gt;
	-- todo what with {{!}}&lt;br /&gt;
	local newSep = defaultSep&lt;br /&gt;
&lt;br /&gt;
	newSep  = sSep&lt;br /&gt;
	sSep = decodeUnicode(sSep)&lt;br /&gt;
	if string.match(sSep, &amp;#039;[%s%w%d]&amp;#039;) ~= nil then -- not ok&lt;br /&gt;
		msg = &amp;#039;Irregular characters in sep: &amp;#039; .. sSep&lt;br /&gt;
		newSep = defaultSep&lt;br /&gt;
	end&lt;br /&gt;
	newSep = string.sub(sSep, 1, 1)&lt;br /&gt;
	if newSep == &amp;#039;&amp;#039; then --- ???&lt;br /&gt;
		newSep = defaultSep&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return newSep&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function concatAndLists(s1, s2, newSep)&lt;br /&gt;
	local tLists = {} -- working table: both s1 and s2 to concat&lt;br /&gt;
	table.insert(tLists, s1)&lt;br /&gt;
	table.insert(tLists, s2)&lt;br /&gt;
	return table.concat(tLists, newSep)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function parseArgs(origArgs)&lt;br /&gt;
local newArgs = {}&lt;br /&gt;
	newArgs[&amp;#039;sep&amp;#039;]		= setSep(origArgs[&amp;#039;sep&amp;#039;]) -- do first, needed below&lt;br /&gt;
	newArgs[&amp;#039;source&amp;#039;]	= decodeUnicode(origArgs[&amp;#039;s&amp;#039;] or origArgs[&amp;#039;source&amp;#039;] or &amp;#039;&amp;#039;)&lt;br /&gt;
	newArgs[&amp;#039;andString&amp;#039;] = decodeUnicode(concatAndLists(&lt;br /&gt;
									origArgs[&amp;#039;w&amp;#039;] or origArgs[&amp;#039;word&amp;#039;] or nil,&lt;br /&gt;
									origArgs[&amp;#039;andw&amp;#039;] or origArgs[&amp;#039;andwords&amp;#039;] or nil, &lt;br /&gt;
									newArgs.sSep)&lt;br /&gt;
									)&lt;br /&gt;
	newArgs[&amp;#039;orString&amp;#039;]	= decodeUnicode(origArgs[&amp;#039;orw&amp;#039;] or origArgs[&amp;#039;orwords&amp;#039;] or &amp;#039;&amp;#039;)&lt;br /&gt;
	-- boolean options: catch both parameters, also handle nil &amp;amp; nonsense input values:&lt;br /&gt;
	newArgs[&amp;#039;case&amp;#039;]		= yesno(origArgs[&amp;#039;case&amp;#039;] or origArgs[&amp;#039;casesensitive&amp;#039;] or true, true) -- defaults to True&lt;br /&gt;
	newArgs[&amp;#039;booleans&amp;#039;]	= yesno(origArgs[&amp;#039;bool&amp;#039;] or origArgs[&amp;#039;booleans&amp;#039;] or false, false) -- defaults to False&lt;br /&gt;
	newArgs[&amp;#039;literals&amp;#039;]	= yesno(origArgs[&amp;#039;literals&amp;#039;] or origArgs[&amp;#039;lit&amp;#039;] or true, true) -- defaults to True&lt;br /&gt;
	newArgs[&amp;#039;yes&amp;#039;]		= origArgs[&amp;#039;yes&amp;#039;] or nil -- nil; default so return sYeslist; keep &amp;#039;&amp;#039; as legal input &amp;amp; return value&lt;br /&gt;
	newArgs[&amp;#039;no&amp;#039;]		= origArgs[&amp;#039;no&amp;#039;] or &amp;#039;&amp;#039;&lt;br /&gt;
	newArgs[&amp;#039;explain&amp;#039;]	= false -- never. 22Mar2023 checkExplain(newArgs)&lt;br /&gt;
&lt;br /&gt;
	newArgs.explain = false -- never. 22Mar2023 checkExplain(newArgs)&lt;br /&gt;
	&lt;br /&gt;
	return newArgs&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.main(frame)&lt;br /&gt;
local origArgs = getArgs(frame)&lt;br /&gt;
local sReturn = &amp;#039;&amp;#039;&lt;br /&gt;
local tArgs = {}&lt;br /&gt;
&lt;br /&gt;
	tArgs = parseArgs(origArgs)&lt;br /&gt;
	if yesno(tArgs.explain, false) then&lt;br /&gt;
		initReport()&lt;br /&gt;
		report.xpListArguments(origArgs)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	sReturn = p._main(tArgs)&lt;br /&gt;
	&lt;br /&gt;
	if warningIMaxWordsReached ~=nil then&lt;br /&gt;
		local preview = require(&amp;#039;Module:If preview&amp;#039;)&lt;br /&gt;
		sReturn = sReturn .. preview._warning({warningIMaxWordsReached})&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if yesno(tArgs.explain, false) then&lt;br /&gt;
		return sReturn .. report.xpPresent(tArgs.explain)&lt;br /&gt;
	else&lt;br /&gt;
		return sReturn&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>&gt;Lemondoge</name></author>
	</entry>
</feed>