คุณอาจจะต้องการสร้างคู่มือการใช้งานของนี้ ผู้เขียนสามารถทำการทดลองได้ที่กระบะทราย (สร้าง | คัดลอก) และชุดทดสอบ (สร้าง) ของมอดูลนี้ โปรดเพิ่มหมวดหมู่ไปที่หน้าย่อย |
local TemplatePar = { serial = "2023-03-20", suite = "TemplatePar", item = 15393417, globals = { DateTime = 20652535, FileMedia = 24765326, Multilingual = 47541920, TemplUtl = 52364930, URLutil = 10859193 } } --[=[ Template parameter utility * assert * check * count * countNotEmpty * downcase() * duplicates * match * valid * verify() * TemplatePar() * failsafe() ]=] local Local = { frame = false } local Failsafe = TemplatePar local GlobalMod = Local -- Module globals Local.messagePrefix = "lua-module-TemplatePar-" Local.L10nDef = {} Local.L10nDef.en = { badPattern = "#invoke:TemplatePar pattern syntax error", dupOpt = "#invoke:TemplatePar repeated optional parameter", dupRule = "#invoke:TemplatePar conflict key/pattern", empty = "Error in template * undefined value for mandatory", invalid = "Error in template * invalid parameter", invalidPar = "#invoke:TemplatePar invalid parameter", minmax = "#invoke:TemplatePar min > max", missing = "#invoke:TemplatePar missing library", multiSpell = "Error in template * multiple spelling of parameter", noMSGnoCAT = "#invoke:TemplatePar neither message nor category", noname = "#invoke:TemplatePar missing parameter name", notFound = "Error in template * missing page", tooLong = "Error in template * parameter too long", tooShort = "Error in template * parameter too short", unavailable = "Error in template * parameter name missing", undefined = "Error in template * mandatory parameter missing", unknown = "Error in template * unknown parameter name", unknownRule = "#invoke:TemplatePar unknown rule" } Local.patterns = { [ "ASCII" ] = "^[ -~]*$", [ "ASCII+" ] = "^[ -~]+$", [ "ASCII+1" ] = "^[!-~]+$", [ "n" ] = "^[%-]?[0-9]*$", [ "n>0" ] = "^[0-9]*[1-9][0-9]*$", [ "N+" ] = "^[%-]?[1-9][0-9]*$", [ "N>0" ] = "^[1-9][0-9]*$", [ "x" ] = "^[0-9A-Fa-f]*$", [ "x+" ] = "^[0-9A-Fa-f]+$", [ "X" ] = "^[0-9A-F]*$", [ "X+" ] = "^[0-9A-F]+$", [ "0,0" ] = "^[%-]?[0-9]*,?[0-9]*$", [ "0,0+" ] = "^[%-]?[0-9]+,[0-9]+$", [ "0,0+?" ] = "^[%-]?[0-9]+,?[0-9]*$", [ "0.0" ] = "^[%-]?[0-9]*[%.]?[0-9]*$", [ "0.0+" ] = "^[%-]?[0-9]+%.[0-9]+$", [ "0.0+?" ] = "^[%-]?[0-9]+[%.]?[0-9]*$", [ ".0+" ] = "^[%-]?[0-9]*[%.]?[0-9]+$", [ "ID" ] = "^[A-Za-z]?[A-Za-z_0-9]*$", [ "ID+" ] = "^[A-Za-z][A-Za-z_0-9]*$", [ "ABC" ] = "^[A-Z]*$", [ "ABC+" ] = "^[A-Z]+$", [ "Abc" ] = "^[A-Z]*[a-z]*$", [ "Abc+" ] = "^[A-Z][a-z]+$", [ "abc" ] = "^[a-z]*$", [ "abc+" ] = "^[a-z]+$", [ "aBc+" ] = "^[a-z]+[A-Z][A-Za-z]*$", [ "w" ] = "^%S*$", [ "w+" ] = "^%S+$", [ "base64" ] = "^[A-Za-z0-9%+/]*$", [ "base64+" ] = "^[A-Za-z0-9%+/]+$", [ "aa" ] = "[%a%a].*[%a%a]", [ "pagename" ] = string.format( "^[^#<>%%[%%]|{}%c-%c%c]+$", 1, 31, 127 ), [ "ref" ] = string.format( "%c'%c`UNIQ%s%sref%s%s%sQINU`%c'%c", 127, 34, "%-", "%-", "%-", "%x+", "%-", 34, 127 ), [ "+" ] = "%S" } Local.boolean = { ["1"] = true, ["true"] = true, y = true, yes = true, on = true, ["0"] = true, ["false"] = true, ["-"] = true, n = true, no = true, off = true } Local.patternCJK = false local foreignModule = function ( access, advanced, append, alt, alert ) -- Fetch global module -- Precondition: -- access -- string, with name of base module -- advanced -- true, for require(); else mw.loadData() -- append -- string, with subpage part, if any; or false -- alt -- number, of wikidata item of root; or false -- alert -- true, for throwing error on data problem -- Postcondition: -- Returns whatever, probably table -- 2020-01-01 local storage = access local finer = function () if append then storage = string.format( "%s/%s", storage, append ) end end local fun, lucky, r, suited if advanced then fun = require else fun = mw.loadData end GlobalMod.globalModules = GlobalMod.globalModules or { } suited = GlobalMod.globalModules[ access ] if not suited then finer() lucky, r = pcall( fun, "Module:" .. storage ) end if not lucky then if not suited and type( alt ) == "number" and alt > 0 then suited = string.format( "Q%d", alt ) suited = mw.wikibase.getSitelink( suited ) GlobalMod.globalModules[ access ] = suited or true end if type( suited ) == "string" then storage = suited finer() lucky, r = pcall( fun, storage ) end if not lucky and alert then error( "Missing or invalid page: " .. storage ) end end return r end -- foreignModule() local function Foreign( access ) -- Access standardized library -- Precondition: -- access -- string, with name of base module -- Postcondition: -- Return library table, or not -- Uses: local r if Local[ access ] then r = Local[ access ] else local bib = foreignModule( access, true, false, TemplatePar.globals[ access ], false ) if type( bib ) == "table" and type( bib[ access ] ) == "function" then bib = bib[ access ]() if type( bib ) == "table" then r = bib Local[ access ] = bib end end end return r end -- Foreign() local function containsCJK( analyse ) -- Is any CJK character present? -- Precondition: -- analyse -- string -- Postcondition: -- Return false iff no CJK present -- Uses: -- >< Local.patternCJK -- mw.ustring.char() -- mw.ustring.match() local r = false if not Local.patternCJK then Local.patternCJK = mw.ustring.char( 91, 13312, 45, 40959, 131072, 45, 178207, 93 ) end if mw.ustring.match( analyse, Local.patternCJK ) then r = true end return r end -- containsCJK() local function facility( accept, attempt ) -- Check string as possible file name or other source page -- Precondition: -- accept -- string; requirement -- file -- file+ -- file: -- file:+ -- image -- image+ -- image: -- image:+ -- attempt -- string; to be tested -- Postcondition: -- Return error keyword, or false -- Uses: -- Module:FileMedia -- Foreign() -- FileMedia.isFile() -- FileMedia.isType() local r if attempt and attempt ~= "" then local FileMedia = Foreign( "FileMedia" ) if FileMedia and type( FileMedia.isFile ) == "function" and type( FileMedia.isType ) == "function" then local s, live = accept:match( "^([a-z]+)(:?)%+?$" ) if live then if FileMedia.isType( attempt, s ) then if FileMedia.isFile( attempt ) then r = false else r = "notFound" end else r = "invalid" end elseif FileMedia.isType( attempt, s ) then r = false else r = "invalid" end else r = "missing" end elseif accept:match( "%+$" ) then r = "empty" else r = false end return r end -- facility() local function factory( say ) -- Retrieve localized message string in content language -- Precondition: -- say -- string; message ID -- Postcondition: -- Return some message string -- Uses: -- > Local.messagePrefix -- > Local.L10nDef -- mw.message.new() -- mw.language.getContentLanguage() -- Module:Multilingual -- Foreign() -- TemplatePar.framing() -- Multilingual.tabData() local m = mw.message.new( Local.messagePrefix .. say ) local r = false if m:isBlank() then local c = mw.language.getContentLanguage():getCode() local l10n = Local.L10nDef[ c ] if l10n then r = l10n[ say ] else local MultiL = Foreign( "Multilingual" ) if MultiL and type( MultiL.tabData ) == "function" then local lang r, lang = MultiL.tabData( "I18n/Module:TemplatePar", say, false, TemplatePar.framing() ) end end if not r then r = Local.L10nDef.en[ say ] end else m:inLanguage( c ) r = m:plain() end if not r then r = string.format( "(((%s)))", say ) end return r end -- factory() local function faculty( accept, attempt ) -- Check string as possible boolean -- Precondition: -- accept -- string; requirement -- boolean -- boolean+ -- attempt -- string; to be tested -- Postcondition: -- Return error keyword, or false -- Uses: -- Module:TemplUtl -- Foreign() -- TemplUtl.faculty() local r r = mw.text.trim( attempt ):lower() if r == "" then if accept == "boolean+" then r = "empty" else r = false end elseif Local.boolean[ r ] or r:match( "^[01%-]+$" ) then r = false else local TemplUtl = Foreign( "TemplUtl" ) if TemplUtl and type( TemplUtl.faculty ) == "function" then r = TemplUtl.faculty( r, "-" ) if r == "-" then r = "invalid" else r = false end else r = "invalid" end end return r end -- faculty() local function failure( spec, suspect, options ) -- Submit localized error message -- Precondition: -- spec -- string; message ID -- suspect -- string or nil; additional information -- options -- table or nil; optional details -- options.template -- Postcondition: -- Return string -- Uses: -- factory() local r = factory( spec ) if type( options ) == "table" then if type( options.template ) == "string" then if #options.template > 0 then r = string.format( "%s (%s)", r, options.template ) end end end if suspect then r = string.format( "%s: %s", r, suspect ) end return r end -- failure() local function fair( story, scan ) -- Test for match (possibly user-defined with syntax error) -- Precondition: -- story -- string; parameter value -- scan -- string; pattern -- Postcondition: -- Return nil, if not matching, else non-nil -- Uses: -- mw.ustring.match() return mw.ustring.match( story, scan ) end -- fair() local function familiar( accept, attempt ) -- Check string as possible language name or list -- Precondition: -- accept -- string; requirement -- lang -- langs -- langW -- langsW -- lang+ -- langs+ -- langW+ -- langsW+ -- attempt -- string; to be tested -- Postcondition: -- Return error keyword, or false -- Uses: -- Module:Multilingual -- Foreign() -- Multilingual.isLang() local r if attempt and attempt ~= "" then local MultiL = Foreign( "Multilingual" ) if MultiL and type( MultiL.isLang ) == "function" then local lazy = accept:find( "W", 1, true ) if accept:find( "s", 1, true ) then local group = mw.text.split( attempt, "%s+" ) r = false for i = 1, #group do if not MultiL.isLang( group[ i ], lazy ) then r = "invalid" break -- for i end end -- for i elseif MultiL.isLang( attempt, lazy ) then r = false else r = "invalid" end else r = "missing" end elseif accept:find( "+", 1, true ) then r = "empty" else r = false end return r end -- familiar() local function far( accept, attempt ) -- Check string as possible URL -- Precondition: -- accept -- string; requirement -- url -- url+ -- attempt -- string; to be tested -- Postcondition: -- Return error keyword, or false -- Uses: -- Module:URLutil -- Foreign() -- URLutil.isWebURL() local r if attempt and attempt ~= "" then local URLutil = Foreign( "URLutil" ) if URLutil and type( URLutil.isWebURL ) == "function" then if URLutil.isWebURL( attempt ) then r = false else r = "invalid" end else r = "missing" end elseif accept:find( "+", 1, true ) then r = "empty" else r = false end return r end -- far() local function fast( accept, attempt ) -- Check string as possible date or time -- Precondition: -- accept -- string; requirement -- datetime -- datetime+ -- datetime/y -- datetime/y+ -- datetime/ym -- datetime/ym+ -- datetime/ymd -- datetime/ymd+ -- attempt -- string; to be tested -- Postcondition: -- Return error keyword, or false -- Uses: -- Module:DateTime -- Foreign() -- DateTime.DateTime() local r r = mw.text.trim( attempt ) if r == "" then if accept:find( "+", 1, true ) then r = "empty" else r = false end else local DateTime = Foreign( "DateTime" ) if type( DateTime ) == "table" then local d = DateTime( attempt ) if type( d ) == "table" then if accept:find( "/", 1, true ) then r = "invalid" if accept:sub( 1, 10 ) == "datetime/y" then if d.year then r = false if accept:sub( 1, 11 ) == "datetime/ym" then if d.month then if accept:sub( 1, 12 ) == "datetime/ymd" then if not d.dom then r = "invalid" end end else r = "invalid" end end end end else r = false end else r = "invalid" end else r = "invalid" end end return r end -- fast() local function fault( store, key ) -- Add key to collection string and insert separator -- Precondition: -- store -- string or nil or false; collection string -- key -- string or number; to be appended -- Postcondition: -- Return string; extended local r local s if type( key ) == "number" then s = tostring( key ) else s = key end if store then r = string.format( "%s; %s", store, s ) else r = s end return r end -- fault() local function feasible( analyze, options, abbr ) -- Check content of a value -- Precondition: -- analyze -- string to be analyzed -- options -- table or nil; optional details -- options.pattern -- options.key -- options.say -- abbr -- true: abbreviated error message -- Postcondition: -- Return string with error message as configured; -- false if valid or no answer permitted -- Uses: -- > Local.patterns -- failure() -- mw.text.trim() -- faculty() -- fast() -- facility() -- familiar() -- far() -- fair() -- containsCJK() local r = false local s = false local show = nil local scan = false local stuff = mw.text.trim( analyze ) if type( options.pattern ) == "string" then if options.key then r = failure( "dupRule", false, options ) else scan = options.pattern end else if type( options.key ) == "string" then s = mw.text.trim( options.key ) else s = "+" end if s ~= "*" then scan = Local.patterns[ s ] end if type( scan ) == "string" then if s == "n" or s == "0,0" or s == "0.0" then if not stuff:match( "[0-9]" ) and not stuff:match( "^%s*$" ) then scan = false if options.say then show = string.format( ""%s"", options.say ) end if abbr then r = show else r = failure( "invalid", show, options ) end end end elseif s ~= "*" then local op, n, plus = s:match( "([<!=>]=?)([-0-9][%S]*)(+?)" ) if op then n = tonumber( n ) if n then local i = tonumber( stuff ) if i then if op == "<" then i = ( i < n ) elseif op == "<=" then i = ( i <= n ) elseif op == ">" then i = ( i > n ) elseif op == ">=" then i = ( i >= n ) elseif op == "==" then i = ( i == n ) elseif op == "!=" then i = ( i ~= n ) else n = false end end if not i then r = "invalid" end elseif plus then r = "undefined" end elseif s:match( "^boolean%+?$" ) then r = faculty( s, stuff ) n = true elseif s:match( "^datetime/?y?m?d?%+?$" ) then r = fast( s, stuff ) n = true elseif s:match( "^image%+?:?$" ) or s:match( "^file%+?:?$" ) then r = facility( s, stuff ) n = true elseif s:match( "langs?W?%+?" ) then r = familiar( s, stuff ) n = true elseif s:match( "url%+?" ) then r = far( s, stuff ) n = true end -- datetime+ -- iso8631+ -- line+ if not n and not r then r = "unknownRule" end if r then if options.say then show = string.format( ""%s" %s", options.say, s ) else show = s end if abbr then r = show else r = failure( r, show, options ) end end end end if scan then local legal, got = pcall( fair, stuff, scan ) if legal then if not got then if s == "aa" then got = containsCJK( stuff ) end if not got then if options.say then show = string.format( ""%s"", options.say ) end if abbr then r = show else r = failure( "invalid", show, options ) end end end else r = failure( "badPattern", string.format( "%s *** %s", scan, got ), options ) end end return r end -- feasible() local function fed( haystack, needle ) -- Find needle in haystack map -- Precondition: -- haystack -- table; map of key values -- needle -- any; identifier -- Postcondition: -- Return true iff found local k, v, r for k, v in pairs( haystack ) do if k == needle then r = true end end -- for k, v return r or false end -- fed() local function fetch( light, options ) -- Return regular table with all parameters -- Precondition: -- light -- true: template transclusion; false: #invoke -- options -- table; optional details -- options.low -- Postcondition: -- Return table; whitespace-only values as false -- Uses: -- TemplatePar.downcase() -- TemplatePar.framing() -- frame:getParent() local g, k, v local r = { } if options.low then g = TemplatePar.downcase( options ) else g = TemplatePar.framing() if light then g = g:getParent() end g = g.args end if type( g ) == "table" then r = { } for k, v in pairs( g ) do if type( v ) == "string" then if v:match( "^%s*$" ) then v = false end else v = false end if type( k ) == "number" then k = tostring( k ) end r[ k ] = v end -- for k, v else r = g end return r end -- fetch() local function figure( append, options ) -- Extend options by rule from #invoke strings -- Precondition: -- append -- string or nil; requested rule -- options -- table; details -- ++ .key -- ++ .pattern -- Postcondition: -- Return sequence table local r = options if type( append ) == "string" then local story = mw.text.trim( append ) local sub = story:match( "^/(.*%S)/$" ) if type( sub ) == "string" then sub = sub:gsub( "%%!", "|" ) :gsub( "%%%(%(", "{{" ) :gsub( "%%%)%)", "}}" ) :gsub( "\\n", string.char( 10 ) ) options.pattern = sub options.key = nil else options.key = story options.pattern = nil end end return r end -- figure() local function fill( specified ) -- Split requirement string separated by '=' -- Precondition: -- specified -- string or nil; requested parameter set -- Postcondition: -- Return sequence table -- Uses: -- mw.text.split() local r if specified then local i, s r = mw.text.split( specified, "%s*=%s*" ) for i = #r, 1, -1 do s = r[ i ] if #s == 0 then table.remove( r, i ) end end -- for i, -1 else r = { } end return r end -- fill() local function finalize( submit, options ) -- Finalize message -- Precondition: -- submit -- string or false or nil; non-empty error message -- options -- table or nil; optional details -- options.format -- options.preview -- options.cat -- options.template -- Postcondition: -- Return string or false -- Uses: -- TemplatePar.framing() -- factory() local r = false if submit then local lazy = false local learn = false local show = false local opt, s if type( options ) == "table" then opt = options show = opt.format lazy = ( show == "" or show == "0" or show == "-" ) s = opt.preview if type( s ) == "string" and s ~= "" and s ~= "0" and s ~= "-" then local sniffer = "{{REVISIONID}}" if lazy then show = "" lazy = false end if TemplatePar.framing():preprocess( sniffer ) == "" then if s == "1" then show = "*" else show = s end learn = true end end else opt = { } end if lazy then if not opt.cat then r = string.format( "%s %s", submit, factory( "noMSGnoCAT" ) ) end else r = submit end if r and not lazy then local i if not show or show == "*" then local e = mw.html.create( "span" ) :attr( "class", "error" ) :wikitext( "@@@" ) if learn then local max = 1000000000 local id = math.floor( os.clock() * max ) local sign = string.format( "error_%d", id ) local btn = mw.html.create( "span" ) local top = mw.html.create( "div" ) e:attr( "id", sign ) btn:css( { ["background"] = "#FFFF00", ["border"] = "#FF0000 3px solid", ["font-weight"] = "bold", ["padding"] = "2px", ["text-decoration"] = "none" } ) :wikitext( ">>>" ) sign = string.format( "[[#%s|%s]]", sign, tostring( btn ) ) top:wikitext( sign, " ", submit ) mw.addWarning( tostring( top ) ) end show = tostring( e ) end i = show:find( "@@@", 1, true ) if i then -- No gsub() since r might contain "%3" (e.g. URL) r = string.format( "%s%s%s", show:sub( 1, i - 1 ), r, show:sub( i + 3 ) ) else r = show end end if learn and r then -- r = fatal( r ) end s = opt.cat if type( s ) == "string" then local link if opt.errNS then local ns = mw.title.getCurrentTitle().namespace local st = type( opt.errNS ) if st == "string" then local space = string.format( ".*%%s%d%%s.*", ns ) local spaces = string.format( " %s ", opt.errNS ) if spaces:match( space ) then link = true end elseif st == "table" then for i = 1, #opt.errNS do if opt.errNS[ i ] == ns then link = true break -- for i end end -- for i end else link = true end if link then local cats, i if not r then r = "" end if s:find( "@@@" ) then if type( opt.template ) == "string" then s = s:gsub( "@@@", opt.template ) end end cats = mw.text.split( s, "%s*#%s*" ) for i = 1, #cats do s = mw.text.trim( cats[ i ] ) if #s > 0 then r = string.format( "%s[[Category:%s]]", r, s ) end end -- for i end end end return r end -- finalize() local function finder( haystack, needle ) -- Find needle in haystack sequence -- Precondition: -- haystack -- table; sequence of key names, downcased if low -- needle -- any; key name -- Postcondition: -- Return true iff found local i for i = 1, #haystack do if haystack[ i ] == needle then return true end end -- for i return false end -- finder() local function fix( valid, duty, got, options ) -- Perform parameter analysis -- Precondition: -- valid -- table; unique sequence of known parameters -- duty -- table; sequence of mandatory parameters -- got -- table; sequence of current parameters -- options -- table or nil; optional details -- Postcondition: -- Return string as configured; empty if valid -- Uses: -- finder() -- fault() -- failure() -- fed() local r = false local lack for k, v in pairs( got ) do if k == "" then lack = true break -- for k, v elseif not finder( valid, k ) then r = fault( r, k ) end end -- for k, v if lack then r = failure( "unavailable", false, options ) elseif r then r = failure( "unknown", string.format( ""%s"", r ), options ) else -- all names valid local i, s for i = 1, #duty do s = duty[ i ] if not fed( got, s ) then r = fault( r, s ) end end -- for i if r then r = failure( "undefined", r, options ) else -- all mandatory present for i = 1, #duty do s = duty[ i ] if not got[ s ] then r = fault( r, s ) end end -- for i if r then r = failure( "empty", r, options ) end end end return r end -- fix() local function flat( collection, options ) -- Return all table elements with downcased string -- Precondition: -- collection -- table; k=v pairs -- options -- table or nil; optional messaging details -- Postcondition: -- Return table, may be empty; or string with error message. -- Uses: -- mw.ustring.lower() -- fault() -- failure() local k, v local r = { } local e = false for k, v in pairs( collection ) do if type ( k ) == "string" then k = mw.ustring.lower( k ) if r[ k ] then e = fault( e, k ) end end r[ k ] = v end -- for k, v if e then r = failure( "multiSpell", e, options ) end return r end -- flat() local function fold( options ) -- Merge two tables, create new sequence if both not empty -- Precondition: -- options -- table; details -- options.mandatory sequence to keep unchanged -- options.optional sequence to be appended -- options.low downcased expected -- Postcondition: -- Return merged table, or message string if error -- Uses: -- finder() -- fault() -- failure() -- flat() local i, e, r, s local base = options.mandatory local extend = options.optional if #base == 0 then if #extend == 0 then r = { } else r = extend end else if #extend == 0 then r = base else e = false for i = 1, #extend do s = extend[ i ] if finder( base, s ) then e = fault( e, s ) end end -- for i if e then r = failure( "dupOpt", e, options ) else r = { } for i = 1, #base do table.insert( r, base[ i ] ) end -- for i for i = 1, #extend do table.insert( r, extend[ i ] ) end -- for i end end end if options.low and type( r ) == "table" then r = flat( r, options ) end return r end -- fold() local function form( light, options, frame ) -- Run parameter analysis on current environment -- Precondition: -- light -- true: template transclusion; false: #invoke -- options -- table or nil; optional details -- options.mandatory -- options.optional -- frame -- object; #invoke environment, or false -- Postcondition: -- Return string with error message as configured; -- false if valid -- Uses: -- TemplatePar.framing() -- fold() -- fetch() -- fix() -- finalize() local duty, r if frame then TemplatePar.framing( frame ) end if type( options ) == "table" then if type( options.mandatory ) ~= "table" then options.mandatory = { } end duty = options.mandatory if type( options.optional ) ~= "table" then options.optional = { } end r = fold( options ) else options = { } duty = { } r = { } end if type( r ) == "table" then local got = fetch( light, options ) if type( got ) == "table" then r = fix( r, duty, got, options ) else r = got end end return finalize( r, options ) end -- form() local function format( analyze, options ) -- Check validity of a value -- Precondition: -- analyze -- string to be analyzed -- options -- table or nil; optional details -- options.say -- options.min -- options.max -- Postcondition: -- Return string with error message as configured; -- false if valid or no answer permitted -- Uses: -- feasible() -- failure() local r = feasible( analyze, options, false ) local show if options.min and not r then if type( options.min ) == "number" then if type( options.max ) == "number" then if options.max < options.min then r = failure( "minmax", string.format( "%d > %d", options.min, options.max ), options ) end end if #analyze < options.min and not r then show = " <" .. options.min if options.say then show = string.format( "%s "%s"", show, options.say ) end r = failure( "tooShort", show, options ) end else r = failure( "invalidPar", "min", options ) end end if options.max and not r then if type( options.max ) == "number" then if #analyze > options.max then show = " >" .. options.max if options.say then show = string.format( "%s "%s"", show, options.say ) end r = failure( "tooLong", show, options ) end else r = failure( "invalidPar", "max", options ) end end return r end -- format() local function formatted( assignment, access, options ) -- Check validity of one particular parameter in a collection -- Precondition: -- assignment -- collection -- access -- id of parameter in collection -- options -- table or nil; optional details -- Postcondition: -- Return string with error message as configured; -- false if valid or no answer permitted -- Uses: -- mw.text.trim() -- format() -- failure() local r = false if type( assignment ) == "table" then local story = assignment.args[ access ] or "" if type( access ) == "number" then story = mw.text.trim( story ) end if type( options ) ~= "table" then options = { } end options.say = access r = format( story, options ) end return r end -- formatted() local function furnish( frame, action ) -- Prepare #invoke evaluation of .assert() or .valid() -- Precondition: -- frame -- object; #invoke environment -- action -- "assert" or "valid" -- Postcondition: -- Return string with error message or "" -- Uses: -- form() -- failure() -- finalize() -- TemplatePar.valid() -- TemplatePar.assert() local options = { mandatory = { "1" }, optional = { "2", "cat", "errNS", "low", "max", "min", "format", "preview", "template" }, template = string.format( "#invoke:%s|%s|", "TemplatePar", action ) } local r = form( false, options, frame ) if not r then local s options = { cat = frame.args.cat, errNS = frame.args.errNS, low = frame.args.low, format = frame.args.format, preview = frame.args.preview, template = frame.args.template } options = figure( frame.args[ 2 ], options ) if type( frame.args.min ) == "string" then s = frame.args.min:match( "^%s*([0-9]+)%s*$" ) if s then options.min = tonumber( s ) else r = failure( "invalidPar", "min=" .. frame.args.min, options ) end end if type( frame.args.max ) == "string" then s = frame.args.max:match( "^%s*([1-9][0-9]*)%s*$" ) if s then options.max = tonumber( s ) else r = failure( "invalidPar", "max=" .. frame.args.max, options ) end end if r then r = finalize( r, options ) else s = frame.args[ 1 ] or "" r = tonumber( s ) if ( r ) then s = r end if action == "valid" then r = TemplatePar.valid( s, options ) elseif action == "assert" then r = TemplatePar.assert( s, "", options ) end end end return r or "" end -- furnish() TemplatePar.assert = function ( analyze, append, options ) -- Perform parameter analysis on a single string -- Precondition: -- analyze -- string to be analyzed -- append -- string: append error message, prepending <br /> -- false or nil: throw error with message -- options -- table; optional details -- Postcondition: -- Return string with error message as configured; -- false if valid -- Uses: -- format() local r = format( analyze, options ) if ( r ) then if ( type( append ) == "string" ) then if ( append ~= "" ) then r = string.format( "%s<br /> %s", append, r ) end else error( r, 0 ) end end return r end -- TemplatePar.assert() TemplatePar.check = function ( options ) -- Run parameter analysis on current template environment -- Precondition: -- options -- table or nil; optional details -- options.mandatory -- options.optional -- Postcondition: -- Return string with error message as configured; -- false if valid -- Uses: -- form() return form( true, options, false ) end -- TemplatePar.check() TemplatePar.count = function () -- Return number of template parameters -- Postcondition: -- Return number, starting at 0 -- Uses: -- mw.getCurrentFrame() -- frame:getParent() local k, v local r = 0 local t = mw.getCurrentFrame():getParent() local o = t.args for k, v in pairs( o ) do r = r + 1 end -- for k, v return r end -- TemplatePar.count() TemplatePar.countNotEmpty = function () -- Return number of template parameters with more than whitespace -- Postcondition: -- Return number, starting at 0 -- Uses: -- mw.getCurrentFrame() -- frame:getParent() local k, v local r = 0 local t = mw.getCurrentFrame():getParent() local o = t.args for k, v in pairs( o ) do if not v:match( "^%s*$" ) then r = r + 1 end end -- for k, v return r end -- TemplatePar.countNotEmpty() TemplatePar.downcase = function ( options ) -- Return all template parameters with downcased name -- Precondition: -- options -- table or nil; optional messaging details -- Postcondition: -- Return table, may be empty; or string with error message. -- Uses: -- mw.getCurrentFrame() -- frame:getParent() -- flat() local t = mw.getCurrentFrame():getParent() return flat( t.args, options ) end -- TemplatePar.downcase() TemplatePar.valid = function ( access, options ) -- Check validity of one particular template parameter -- Precondition: -- access -- id of parameter in template transclusion -- string or number -- options -- table or nil; optional details -- Postcondition: -- Return string with error message as configured; -- false if valid or no answer permitted -- Uses: -- mw.text.trim() -- TemplatePar.downcase() -- TemplatePar.framing() -- frame:getParent() -- formatted() -- failure() -- finalize() local r = type( access ) if r == "string" then r = mw.text.trim( access ) if #r == 0 then r = false end elseif r == "number" then r = access else r = false end if r then local params if type( options ) ~= "table" then options = { } end if options.low then params = TemplatePar.downcase( options ) else params = TemplatePar.framing():getParent() end r = formatted( params, access, options ) else r = failure( "noname", false, options ) end return finalize( r, options ) end -- TemplatePar.valid() TemplatePar.verify = function ( options ) -- Perform #invoke parameter analysis -- Precondition: -- options -- table or nil; optional details -- Postcondition: -- Return string with error message as configured; -- false if valid -- Uses: -- form() return form( false, options, false ) end -- TemplatePar.verify() TemplatePar.framing = function( frame ) -- Ensure availability of frame object -- Precondition: -- frame -- object; #invoke environment, or false -- Postcondition: -- Return frame object -- Uses: -- >< Local.frame if not Local.frame then if type( frame ) == "table" and type( frame.args ) == "table" and type( frame.getParent ) == "function" and type( frame:getParent() ) == "table" and type( frame:getParent().getParent ) == "function" and type( frame:getParent():getParent() ) == "nil" then Local.frame = frame else Local.frame = mw.getCurrentFrame() end end return Local.frame end -- TemplatePar.framing() Failsafe.failsafe = function ( atleast ) -- Retrieve versioning and check for compliance -- Precondition: -- atleast -- string, with required version -- or wikidata|item|~|@ or false -- Postcondition: -- Returns string -- with queried version/item, also if problem -- false -- if appropriate -- 2020-08-17 local since = atleast local last = ( since == "~" ) local linked = ( since == "@" ) local link = ( since == "item" ) local r if last or link or linked or since == "wikidata" then local item = Failsafe.item since = false if type( item ) == "number" and item > 0 then local suited = string.format( "Q%d", item ) if link then r = suited else local entity = mw.wikibase.getEntity( suited ) if type( entity ) == "table" then local seek = Failsafe.serialProperty or "P348" local vsn = entity:formatPropertyValues( seek ) if type( vsn ) == "table" and type( vsn.value ) == "string" and vsn.value ~= "" then if last and vsn.value == Failsafe.serial then r = false elseif linked then if mw.title.getCurrentTitle().prefixedText == mw.wikibase.getSitelink( suited ) then r = false else r = suited end else r = vsn.value end end end end end end if type( r ) == "nil" then if not since or since <= Failsafe.serial then r = Failsafe.serial else r = false end end return r end -- Failsafe.failsafe() -- Provide external access local p = {} function p.assert( frame ) -- Perform parameter analysis on some single string -- Precondition: -- frame -- object; #invoke environment -- Postcondition: -- Return string with error message or "" -- Uses: -- furnish() return furnish( frame, "assert" ) end -- p.assert() function p.check( frame ) -- Check validity of template parameters -- Precondition: -- frame -- object; #invoke environment -- Postcondition: -- Return string with error message or "" -- Uses: -- form() -- fill() local options = { optional = { "all", "opt", "cat", "errNS", "low", "format", "preview", "template" }, template = "#invoke:TemplatePar|check|" } local r = form( false, options, frame ) if not r then options = { mandatory = fill( frame.args.all ), optional = fill( frame.args.opt ), cat = frame.args.cat, errNS = frame.args.errNS, low = frame.args.low, format = frame.args.format, preview = frame.args.preview, template = frame.args.template } r = form( true, options, frame ) end return r or "" end -- p.check() function p.count( frame ) -- Count number of template parameters -- Postcondition: -- Return string with digits including "0" -- Uses: -- TemplatePar.count() return tostring( TemplatePar.count() ) end -- p.count() function p.countNotEmpty( frame ) -- Count number of template parameters which are not empty -- Postcondition: -- Return string with digits including "0" -- Uses: -- TemplatePar.countNotEmpty() return tostring( TemplatePar.countNotEmpty() ) end -- p.countNotEmpty() function p.match( frame ) -- Combined analysis of parameters and their values -- Precondition: -- frame -- object; #invoke environment -- Postcondition: -- Return string with error message or "" -- Uses: -- TemplatePar.framing() -- mw.text.trim() -- mw.ustring.lower() -- failure() -- form() -- TemplatePar.downcase() -- figure() -- feasible() -- fault() -- finalize() local r = false local options = { cat = frame.args.cat, errNS = frame.args.errNS, low = frame.args.low, format = frame.args.format, preview = frame.args.preview, template = frame.args.template } local k, v, s local params = { } TemplatePar.framing( frame ) for k, v in pairs( frame.args ) do if type( k ) == "number" then s, v = v:match( "^ *([^=]+) *= *(%S.*%S*) *$" ) if s then s = mw.text.trim( s ) if s == "" then s = false end end if s then if options.low then s = mw.ustring.lower( s ) end if params[ s ] then s = params[ s ] s[ #s + 1 ] = v else params[ s ] = { v } end else r = failure( "invalidPar", tostring( k ), options ) break -- for k, v end end end -- for k, v if not r then s = { } for k, v in pairs( params ) do s[ #s + 1 ] = k end -- for k, v options.optional = s r = form( true, options, frame ) end if not r then local errMiss, errValues, lack, rule local targs = frame:getParent().args options.optional = nil if options.low then targs = TemplatePar.downcase() else targs = frame:getParent().args end errMiss = false errValues = false for k, v in pairs( params ) do options.say = k s = targs[ k ] if s then if s == "" then lack = true else lack = false end else s = "" lack = true end for r, rule in pairs( v ) do options = figure( rule, options ) r = feasible( s, options, true ) if r then if lack then if errMiss then s = "%s, "%s"" errMiss = string.format( s, errMiss, k ) else errMiss = string.format( ""%s"", k ) end elseif not errMiss then errValues = fault( errValues, r ) end break -- for r, rule end end -- for s, rule end -- for k, v r = ( errMiss or errValues ) if r then if errMiss then r = failure( "undefined", errMiss, options ) else r = failure( "invalid", errValues, options ) end r = finalize( r, options ) end end return r or "" end -- p.match() function p.valid( frame ) -- Check validity of one particular template parameter -- Precondition: -- frame -- object; #invoke environment -- Postcondition: -- Return string with error message or "" -- Uses: -- furnish() return furnish( frame, "valid" ) end -- p.valid() p.failsafe = function ( frame ) -- Versioning interface local s = type( frame ) local since if s == "table" then since = frame.args[ 1 ] elseif s == "string" then since = frame end if since then since = mw.text.trim( since ) if since == "" then since = false end end return Failsafe.failsafe( since ) or "" end -- p.failsafe function p.TemplatePar() -- Retrieve function access for modules -- Postcondition: -- Return table with functions return TemplatePar end -- p.TemplatePar() setmetatable( p, { __call = function ( func, ... ) setmetatable( p, nil ) return Failsafe end } ) return p
wikipedia, แบบไทย, วิกิพีเดีย, วิกิ หนังสือ, หนังสือ, ห้องสมุด, บทความ, อ่าน, ดาวน์โหลด, ฟรี, ดาวน์โหลดฟรี, mp3, วิดีโอ, mp4, 3gp, jpg, jpeg, gif, png, รูปภาพ, เพลง, เพลง, หนัง, หนังสือ, เกม, เกม, มือถือ, โทรศัพท์, Android, iOS, Apple, โทรศัพท์โมบิล, Samsung, iPhone, Xiomi, Xiaomi, Redmi, Honor, Oppo, Nokia, Sonya, MI, PC, พีซี, web, เว็บ, คอมพิวเตอร์
khumuxkarichnganmxdul srang khunxaccatxngkarsrangkhumuxkarichngankhxngmxdulni phuekhiynsamarththakarthdlxngidthikrabathray srang khdlxk aelachudthdsxb srang khxngmxdulni oprdephimhmwdhmuipthihnayxy hnayxykhxngmxdulnilocal TemplatePar serial 2023 03 20 suite TemplatePar item 15393417 globals DateTime 20652535 FileMedia 24765326 Multilingual 47541920 TemplUtl 52364930 URLutil 10859193 Template parameter utility assert check count countNotEmpty downcase duplicates match valid verify TemplatePar failsafe local Local frame false local Failsafe TemplatePar local GlobalMod Local Module globals Local messagePrefix lua module TemplatePar Local L10nDef Local L10nDef en badPattern amp 35 invoke TemplatePar pattern syntax error dupOpt amp 35 invoke TemplatePar repeated optional parameter dupRule amp 35 invoke TemplatePar conflict key pattern empty Error in template undefined value for mandatory invalid Error in template invalid parameter invalidPar amp 35 invoke TemplatePar invalid parameter minmax amp 35 invoke TemplatePar min gt max missing amp 35 invoke TemplatePar missing library multiSpell Error in template multiple spelling of parameter noMSGnoCAT amp 35 invoke TemplatePar neither message nor category noname amp 35 invoke TemplatePar missing parameter name notFound Error in template missing page tooLong Error in template parameter too long tooShort Error in template parameter too short unavailable Error in template parameter name missing undefined Error in template mandatory parameter missing unknown Error in template unknown parameter name unknownRule amp 35 invoke TemplatePar unknown rule Local patterns ASCII ASCII ASCII 1 n 0 9 n gt 0 0 9 1 9 0 9 N 1 9 0 9 N gt 0 1 9 0 9 x 0 9A Fa f x 0 9A Fa f X 0 9A F X 0 9A F 0 0 0 9 0 9 0 0 0 9 0 9 0 0 0 9 0 9 0 0 0 9 0 9 0 0 0 9 0 9 0 0 0 9 0 9 0 0 9 0 9 ID A Za z A Za z 0 9 ID A Za z A Za z 0 9 ABC A Z ABC A Z Abc A Z a z Abc A Z a z abc a z abc a z aBc a z A Z A Za z w S w S base64 A Za z0 9 base64 A Za z0 9 aa a a a a pagename string format lt gt c c c 1 31 127 ref string format c c UNIQ s sref s s sQINU c c 127 34 x 34 127 S Local boolean 1 true true true y true yes true on true 0 true false true true n true no true off true Local patternCJK false local foreignModule function access advanced append alt alert Fetch global module Precondition access string with name of base module advanced true for require else mw loadData append string with subpage part if any or false alt number of wikidata item of root or false alert true for throwing error on data problem Postcondition Returns whatever probably table 2020 01 01 local storage access local finer function if append then storage string format s s storage append end end local fun lucky r suited if advanced then fun require else fun mw loadData end GlobalMod globalModules GlobalMod globalModules or suited GlobalMod globalModules access if not suited then finer lucky r pcall fun Module storage end if not lucky then if not suited and type alt number and alt gt 0 then suited string format Q d alt suited mw wikibase getSitelink suited GlobalMod globalModules access suited or true end if type suited string then storage suited finer lucky r pcall fun storage end if not lucky and alert then error Missing or invalid page storage end end return r end foreignModule local function Foreign access Access standardized library Precondition access string with name of base module Postcondition Return library table or not Uses local r if Local access then r Local access else local bib foreignModule access true false TemplatePar globals access false if type bib table and type bib access function then bib bib access if type bib table then r bib Local access bib end end end return r end Foreign local function containsCJK analyse Is any CJK character present Precondition analyse string Postcondition Return false iff no CJK present Uses gt lt Local patternCJK mw ustring char mw ustring match local r false if not Local patternCJK then Local patternCJK mw ustring char 91 13312 45 40959 131072 45 178207 93 end if mw ustring match analyse Local patternCJK then r true end return r end containsCJK local function facility accept attempt Check string as possible file name or other source page Precondition accept string requirement file file file file image image image image attempt string to be tested Postcondition Return error keyword or false Uses Module FileMedia Foreign FileMedia isFile FileMedia isType local r if attempt and attempt then local FileMedia Foreign FileMedia if FileMedia and type FileMedia isFile function and type FileMedia isType function then local s live accept match a z if live then if FileMedia isType attempt s then if FileMedia isFile attempt then r false else r notFound end else r invalid end elseif FileMedia isType attempt s then r false else r invalid end else r missing end elseif accept match then r empty else r false end return r end facility local function factory say Retrieve localized message string in content language Precondition say string message ID Postcondition Return some message string Uses gt Local messagePrefix gt Local L10nDef mw message new mw language getContentLanguage Module Multilingual Foreign TemplatePar framing Multilingual tabData local m mw message new Local messagePrefix say local r false if m isBlank then local c mw language getContentLanguage getCode local l10n Local L10nDef c if l10n then r l10n say else local MultiL Foreign Multilingual if MultiL and type MultiL tabData function then local lang r lang MultiL tabData I18n Module TemplatePar say false TemplatePar framing end end if not r then r Local L10nDef en say end else m inLanguage c r m plain end if not r then r string format s say end return r end factory local function faculty accept attempt Check string as possible boolean Precondition accept string requirement boolean boolean attempt string to be tested Postcondition Return error keyword or false Uses Module TemplUtl Foreign TemplUtl faculty local r r mw text trim attempt lower if r then if accept boolean then r empty else r false end elseif Local boolean r or r match 01 then r false else local TemplUtl Foreign TemplUtl if TemplUtl and type TemplUtl faculty function then r TemplUtl faculty r if r then r invalid else r false end else r invalid end end return r end faculty local function failure spec suspect options Submit localized error message Precondition spec string message ID suspect string or nil additional information options table or nil optional details options template Postcondition Return string Uses factory local r factory spec if type options table then if type options template string then if options template gt 0 then r string format s s r options template end end end if suspect then r string format s s r suspect end return r end failure local function fair story scan Test for match possibly user defined with syntax error Precondition story string parameter value scan string pattern Postcondition Return nil if not matching else non nil Uses mw ustring match return mw ustring match story scan end fair local function familiar accept attempt Check string as possible language name or list Precondition accept string requirement lang langs langW langsW lang langs langW langsW attempt string to be tested Postcondition Return error keyword or false Uses Module Multilingual Foreign Multilingual isLang local r if attempt and attempt then local MultiL Foreign Multilingual if MultiL and type MultiL isLang function then local lazy accept find W 1 true if accept find s 1 true then local group mw text split attempt s r false for i 1 group do if not MultiL isLang group i lazy then r invalid break for i end end for i elseif MultiL isLang attempt lazy then r false else r invalid end else r missing end elseif accept find 1 true then r empty else r false end return r end familiar local function far accept attempt Check string as possible URL Precondition accept string requirement url url attempt string to be tested Postcondition Return error keyword or false Uses Module URLutil Foreign URLutil isWebURL local r if attempt and attempt then local URLutil Foreign URLutil if URLutil and type URLutil isWebURL function then if URLutil isWebURL attempt then r false else r invalid end else r missing end elseif accept find 1 true then r empty else r false end return r end far local function fast accept attempt Check string as possible date or time Precondition accept string requirement datetime datetime datetime y datetime y datetime ym datetime ym datetime ymd datetime ymd attempt string to be tested Postcondition Return error keyword or false Uses Module DateTime Foreign DateTime DateTime local r r mw text trim attempt if r then if accept find 1 true then r empty else r false end else local DateTime Foreign DateTime if type DateTime table then local d DateTime attempt if type d table then if accept find 1 true then r invalid if accept sub 1 10 datetime y then if d year then r false if accept sub 1 11 datetime ym then if d month then if accept sub 1 12 datetime ymd then if not d dom then r invalid end end else r invalid end end end end else r false end else r invalid end else r invalid end end return r end fast local function fault store key Add key to collection string and insert separator Precondition store string or nil or false collection string key string or number to be appended Postcondition Return string extended local r local s if type key number then s tostring key else s key end if store then r string format s s store s else r s end return r end fault local function feasible analyze options abbr Check content of a value Precondition analyze string to be analyzed options table or nil optional details options pattern options key options say abbr true abbreviated error message Postcondition Return string with error message as configured false if valid or no answer permitted Uses gt Local patterns failure mw text trim faculty fast facility familiar far fair containsCJK local r false local s false local show nil local scan false local stuff mw text trim analyze if type options pattern string then if options key then r failure dupRule false options else scan options pattern end else if type options key string then s mw text trim options key else s end if s then scan Local patterns s end if type scan string then if s n or s 0 0 or s 0 0 then if not stuff match 0 9 and not stuff match s then scan false if options say then show string format amp quot s amp quot options say end if abbr then r show else r failure invalid show options end end end elseif s then local op n plus s match lt gt 0 9 S if op then n tonumber n if n then local i tonumber stuff if i then if op lt then i i lt n elseif op lt then i i lt n elseif op gt then i i gt n elseif op gt then i i gt n elseif op then i i n elseif op then i i n else n false end end if not i then r invalid end elseif plus then r undefined end elseif s match boolean then r faculty s stuff n true elseif s match datetime y m d then r fast s stuff n true elseif s match image or s match file then r facility s stuff n true elseif s match langs W then r familiar s stuff n true elseif s match url then r far s stuff n true end datetime iso8631 line if not n and not r then r unknownRule end if r then if options say then show string format amp quot s amp quot s options say s else show s end if abbr then r show else r failure r show options end end end end if scan then local legal got pcall fair stuff scan if legal then if not got then if s aa then got containsCJK stuff end if not got then if options say then show string format amp quot s amp quot options say end if abbr then r show else r failure invalid show options end end end else r failure badPattern string format s s scan got options end end return r end feasible local function fed haystack needle Find needle in haystack map Precondition haystack table map of key values needle any identifier Postcondition Return true iff found local k v r for k v in pairs haystack do if k needle then r true end end for k v return r or false end fed local function fetch light options Return regular table with all parameters Precondition light true template transclusion false invoke options table optional details options low Postcondition Return table whitespace only values as false Uses TemplatePar downcase TemplatePar framing frame getParent local g k v local r if options low then g TemplatePar downcase options else g TemplatePar framing if light then g g getParent end g g args end if type g table then r for k v in pairs g do if type v string then if v match s then v false end else v false end if type k number then k tostring k end r k v end for k v else r g end return r end fetch local function figure append options Extend options by rule from invoke strings Precondition append string or nil requested rule options table details key pattern Postcondition Return sequence table local r options if type append string then local story mw text trim append local sub story match S if type sub string then sub sub gsub gsub gsub gsub n string char 10 options pattern sub options key nil else options key story options pattern nil end end return r end figure local function fill specified Split requirement string separated by Precondition specified string or nil requested parameter set Postcondition Return sequence table Uses mw text split local r if specified then local i s r mw text split specified s s for i r 1 1 do s r i if s 0 then table remove r i end end for i 1 else r end return r end fill local function finalize submit options Finalize message Precondition submit string or false or nil non empty error message options table or nil optional details options format options preview options cat options template Postcondition Return string or false Uses TemplatePar framing factory local r false if submit then local lazy false local learn false local show false local opt s if type options table then opt options show opt format lazy show or show 0 or show s opt preview if type s string and s and s 0 and s then local sniffer REVISIONID if lazy then show lazy false end if TemplatePar framing preprocess sniffer then if s 1 then show else show s end learn true end end else opt end if lazy then if not opt cat then r string format s s submit factory noMSGnoCAT end else r submit end if r and not lazy then local i if not show or show then local e mw html create span attr class error wikitext if learn then local max 1000000000 local id math floor os clock max local sign string format error d id local btn mw html create span local top mw html create div e attr id sign btn css background FFFF00 border FF0000 3px solid font weight bold padding 2px text decoration none wikitext amp gt amp gt amp gt sign string format s s sign tostring btn top wikitext sign amp 160 submit mw addWarning tostring top end show tostring e end i show find 1 true if i then No gsub since r might contain 3 e g URL r string format s s s show sub 1 i 1 r show sub i 3 else r show end end if learn and r then r fatal r end s opt cat if type s string then local link if opt errNS then local ns mw title getCurrentTitle namespace local st type opt errNS if st string then local space string format s d s ns local spaces string format s opt errNS if spaces match space then link true end elseif st table then for i 1 opt errNS do if opt errNS i ns then link true break for i end end for i end else link true end if link then local cats i if not r then r end if s find then if type opt template string then s s gsub opt template end end cats mw text split s s s for i 1 cats do s mw text trim cats i if s gt 0 then r string format s Category s r s end end for i end end end return r end finalize local function finder haystack needle Find needle in haystack sequence Precondition haystack table sequence of key names downcased if low needle any key name Postcondition Return true iff found local i for i 1 haystack do if haystack i needle then return true end end for i return false end finder local function fix valid duty got options Perform parameter analysis Precondition valid table unique sequence of known parameters duty table sequence of mandatory parameters got table sequence of current parameters options table or nil optional details Postcondition Return string as configured empty if valid Uses finder fault failure fed local r false local lack for k v in pairs got do if k then lack true break for k v elseif not finder valid k then r fault r k end end for k v if lack then r failure unavailable false options elseif r then r failure unknown string format amp quot s amp quot r options else all names valid local i s for i 1 duty do s duty i if not fed got s then r fault r s end end for i if r then r failure undefined r options else all mandatory present for i 1 duty do s duty i if not got s then r fault r s end end for i if r then r failure empty r options end end end return r end fix local function flat collection options Return all table elements with downcased string Precondition collection table k v pairs options table or nil optional messaging details Postcondition Return table may be empty or string with error message Uses mw ustring lower fault failure local k v local r local e false for k v in pairs collection do if type k string then k mw ustring lower k if r k then e fault e k end end r k v end for k v if e then r failure multiSpell e options end return r end flat local function fold options Merge two tables create new sequence if both not empty Precondition options table details options mandatory sequence to keep unchanged options optional sequence to be appended options low downcased expected Postcondition Return merged table or message string if error Uses finder fault failure flat local i e r s local base options mandatory local extend options optional if base 0 then if extend 0 then r else r extend end else if extend 0 then r base else e false for i 1 extend do s extend i if finder base s then e fault e s end end for i if e then r failure dupOpt e options else r for i 1 base do table insert r base i end for i for i 1 extend do table insert r extend i end for i end end end if options low and type r table then r flat r options end return r end fold local function form light options frame Run parameter analysis on current environment Precondition light true template transclusion false invoke options table or nil optional details options mandatory options optional frame object invoke environment or false Postcondition Return string with error message as configured false if valid Uses TemplatePar framing fold fetch fix finalize local duty r if frame then TemplatePar framing frame end if type options table then if type options mandatory table then options mandatory end duty options mandatory if type options optional table then options optional end r fold options else options duty r end if type r table then local got fetch light options if type got table then r fix r duty got options else r got end end return finalize r options end form local function format analyze options Check validity of a value Precondition analyze string to be analyzed options table or nil optional details options say options min options max Postcondition Return string with error message as configured false if valid or no answer permitted Uses feasible failure local r feasible analyze options false local show if options min and not r then if type options min number then if type options max number then if options max lt options min then r failure minmax string format d gt d options min options max options end end if analyze lt options min and not r then show lt options min if options say then show string format s amp quot s amp quot show options say end r failure tooShort show options end else r failure invalidPar min options end end if options max and not r then if type options max number then if analyze gt options max then show gt options max if options say then show string format s amp quot s amp quot show options say end r failure tooLong show options end else r failure invalidPar max options end end return r end format local function formatted assignment access options Check validity of one particular parameter in a collection Precondition assignment collection access id of parameter in collection options table or nil optional details Postcondition Return string with error message as configured false if valid or no answer permitted Uses mw text trim format failure local r false if type assignment table then local story assignment args access or if type access number then story mw text trim story end if type options table then options end options say access r format story options end return r end formatted local function furnish frame action Prepare invoke evaluation of assert or valid Precondition frame object invoke environment action assert or valid Postcondition Return string with error message or Uses form failure finalize TemplatePar valid TemplatePar assert local options mandatory 1 optional 2 cat errNS low max min format preview template template string format amp 35 invoke s s TemplatePar action local r form false options frame if not r then local s options cat frame args cat errNS frame args errNS low frame args low format frame args format preview frame args preview template frame args template options figure frame args 2 options if type frame args min string then s frame args min match s 0 9 s if s then options min tonumber s else r failure invalidPar min frame args min options end end if type frame args max string then s frame args max match s 1 9 0 9 s if s then options max tonumber s else r failure invalidPar max frame args max options end end if r then r finalize r options else s frame args 1 or r tonumber s if r then s r end if action valid then r TemplatePar valid s options elseif action assert then r TemplatePar assert s options end end end return r or end furnish TemplatePar assert function analyze append options Perform parameter analysis on a single string Precondition analyze string to be analyzed append string append error message prepending lt br gt false or nil throw error with message options table optional details Postcondition Return string with error message as configured false if valid Uses format local r format analyze options if r then if type append string then if append then r string format s lt br gt s append r end else error r 0 end end return r end TemplatePar assert TemplatePar check function options Run parameter analysis on current template environment Precondition options table or nil optional details options mandatory options optional Postcondition Return string with error message as configured false if valid Uses form return form true options false end TemplatePar check TemplatePar count function Return number of template parameters Postcondition Return number starting at 0 Uses mw getCurrentFrame frame getParent local k v local r 0 local t mw getCurrentFrame getParent local o t args for k v in pairs o do r r 1 end for k v return r end TemplatePar count TemplatePar countNotEmpty function Return number of template parameters with more than whitespace Postcondition Return number starting at 0 Uses mw getCurrentFrame frame getParent local k v local r 0 local t mw getCurrentFrame getParent local o t args for k v in pairs o do if not v match s then r r 1 end end for k v return r end TemplatePar countNotEmpty TemplatePar downcase function options Return all template parameters with downcased name Precondition options table or nil optional messaging details Postcondition Return table may be empty or string with error message Uses mw getCurrentFrame frame getParent flat local t mw getCurrentFrame getParent return flat t args options end TemplatePar downcase TemplatePar valid function access options Check validity of one particular template parameter Precondition access id of parameter in template transclusion string or number options table or nil optional details Postcondition Return string with error message as configured false if valid or no answer permitted Uses mw text trim TemplatePar downcase TemplatePar framing frame getParent formatted failure finalize local r type access if r string then r mw text trim access if r 0 then r false end elseif r number then r access else r false end if r then local params if type options table then options end if options low then params TemplatePar downcase options else params TemplatePar framing getParent end r formatted params access options else r failure noname false options end return finalize r options end TemplatePar valid TemplatePar verify function options Perform invoke parameter analysis Precondition options table or nil optional details Postcondition Return string with error message as configured false if valid Uses form return form false options false end TemplatePar verify TemplatePar framing function frame Ensure availability of frame object Precondition frame object invoke environment or false Postcondition Return frame object Uses gt lt Local frame if not Local frame then if type frame table and type frame args table and type frame getParent function and type frame getParent table and type frame getParent getParent function and type frame getParent getParent nil then Local frame frame else Local frame mw getCurrentFrame end end return Local frame end TemplatePar framing Failsafe failsafe function atleast Retrieve versioning and check for compliance Precondition atleast string with required version or wikidata item or false Postcondition Returns string with queried version item also if problem false if appropriate 2020 08 17 local since atleast local last since local linked since local link since item local r if last or link or linked or since wikidata then local item Failsafe item since false if type item number and item gt 0 then local suited string format Q d item if link then r suited else local entity mw wikibase getEntity suited if type entity table then local seek Failsafe serialProperty or P348 local vsn entity formatPropertyValues seek if type vsn table and type vsn value string and vsn value then if last and vsn value Failsafe serial then r false elseif linked then if mw title getCurrentTitle prefixedText mw wikibase getSitelink suited then r false else r suited end else r vsn value end end end end end end if type r nil then if not since or since lt Failsafe serial then r Failsafe serial else r false end end return r end Failsafe failsafe Provide external access local p function p assert frame Perform parameter analysis on some single string Precondition frame object invoke environment Postcondition Return string with error message or Uses furnish return furnish frame assert end p assert function p check frame Check validity of template parameters Precondition frame object invoke environment Postcondition Return string with error message or Uses form fill local options optional all opt cat errNS low format preview template template amp 35 invoke TemplatePar check local r form false options frame if not r then options mandatory fill frame args all optional fill frame args opt cat frame args cat errNS frame args errNS low frame args low format frame args format preview frame args preview template frame args template r form true options frame end return r or end p check function p count frame Count number of template parameters Postcondition Return string with digits including 0 Uses TemplatePar count return tostring TemplatePar count end p count function p countNotEmpty frame Count number of template parameters which are not empty Postcondition Return string with digits including 0 Uses TemplatePar countNotEmpty return tostring TemplatePar countNotEmpty end p countNotEmpty function p match frame Combined analysis of parameters and their values Precondition frame object invoke environment Postcondition Return string with error message or Uses TemplatePar framing mw text trim mw ustring lower failure form TemplatePar downcase figure feasible fault finalize local r false local options cat frame args cat errNS frame args errNS low frame args low format frame args format preview frame args preview template frame args template local k v s local params TemplatePar framing frame for k v in pairs frame args do if type k number then s v v match S S if s then s mw text trim s if s then s false end end if s then if options low then s mw ustring lower s end if params s then s params s s s 1 v else params s v end else r failure invalidPar tostring k options break for k v end end end for k v if not r then s for k v in pairs params do s s 1 k end for k v options optional s r form true options frame end if not r then local errMiss errValues lack rule local targs frame getParent args options optional nil if options low then targs TemplatePar downcase else targs frame getParent args end errMiss false errValues false for k v in pairs params do options say k s targs k if s then if s then lack true else lack false end else s lack true end for r rule in pairs v do options figure rule options r feasible s options true if r then if lack then if errMiss then s s amp quot s amp quot errMiss string format s errMiss k else errMiss string format amp quot s amp quot k end elseif not errMiss then errValues fault errValues r end break for r rule end end for s rule end for k v r errMiss or errValues if r then if errMiss then r failure undefined errMiss options else r failure invalid errValues options end r finalize r options end end return r or end p match function p valid frame Check validity of one particular template parameter Precondition frame object invoke environment Postcondition Return string with error message or Uses furnish return furnish frame valid end p valid p failsafe function frame Versioning interface local s type frame local since if s table then since frame args 1 elseif s string then since frame end if since then since mw text trim since if since then since false end end return Failsafe failsafe since or end p failsafe function p TemplatePar Retrieve function access for modules Postcondition Return table with functions return TemplatePar end p TemplatePar setmetatable p call function func setmetatable p nil return Failsafe end return p