Check out https://en.wikipedia.org/wiki/Module:Example - which is probably linked from elsewhere but shouldn't be forgotten as a resource.
local p = {} -- p stands for package as you saw in Module:Example
function p.main( frame ) -- frame holds the "stuff" from the user
-- tArgs stands for template args - there's some "magic"
-- where the frame.args is the stuff inside of the invoke, and
-- frame:getParent().args are the args passed to the template
-- that contains the invoke
-- so Template:Hello says {{#invoke:Example|main|foo=bar}}
-- and you say {{Hello|world=kittens}}
-- then frame.args.foo=bar and frame:getParent().args.world=kittens
-- so here we're gonna get the parent args
-- normally this is all encapsulated by some helper module
-- for example, Module:Arguments or Module:GetArguments
-- on my wiki I call it Module:ArgsUtil
-- for the purposes of not having dependencies, they put it into the code here
-- which okay cool so your example has no dependencies yay
-- but this just needlessly makes your example confusing af
-- the need to understand frame/args/etc is one of the WORST parts
-- about Scribunto. copy someone else's ProcessArgs or whatever and be done with it
-- also just to be clear this is a GIANT MISNOMER
-- tArgs is a FRAME OBJECT!!! NOT ARGS!!!!
-- tARgs.args ARE THE ARGS!!!!!!!!!!!!
local tArgs = frame:getParent()
-- if {{{1|}}} is defined then tArgs.args[1] is not nil, and this code doesn't execute
if not(tArgs.args[1]) then
-- so if {{{1|}}} is NOT defined, then we know that
-- there's nothing passed via the parent frame
-- so instead we'll give the code the opportunity the chance to
-- pass something via the direct frame
-- (i.e. the one via #invoke, that held foo=bar above)
tArgs = frame
end
-- tbh at this point idk why im even bothering to keep commenting this
-- this is not a tutorial example
-- none of this makes any sense for a beginner to read
-- or even bother trying to understand
-- so we now have a frame object which is either the frame or the parent frame
-- which confusingly, we have named tArgs
-- the args are retrieved via tArgs.args
-- and tArgs.args[1] == {{{1|}}} in wikitext
-- so our sText is, args[1]
local sText = tArgs.args[1]
-- action to do if it's true is args[2] aka {{{2|}}}
-- or we could also put this as |true=
local sTrueAction = tArgs.args[2] or tArgs.args["true"]
-- and similarly, action to do if it's false is args[3] aka {{{3|}}}
-- or |false= aka {{{false|}}} aka args["false"] aka args.false
local sFalseAction = tArgs.args[3] or tArgs.args["false"]
-- NOW STARTING HERE IS OUR ACTUAL LOGIC
if sText == nil or sText == "" then
-- mw.getCurrentFrame():preprocess() means,
-- "this may be random wikitext shit that we don't know how to process"
-- for example, maybe sFalseAction is {{SomeOtherTemplate}}
-- if we just return that, then the interpreter will print
-- the literal string {{SomeOtherTemplate}}
-- so wrapping in preprocess forces the MW interpreter
-- to actually render this as MW text
-- even though it's coming from Lua
sText = mw.getCurrentFrame():preprocess(sFalseAction)
else
sText = mw.getCurrentFrame():preprocess(sTrueAction)
end
return sText
end
return p