คุณอาจจะต้องการสร้างคู่มือการใช้งานของนี้ ผู้เขียนสามารถทำการทดลองได้ที่กระบะทราย (สร้าง | คัดลอก) และชุดทดสอบ (สร้าง) ของมอดูลนี้ โปรดเพิ่มหมวดหมู่ไปที่หน้าย่อย |
local util = { empty = function( s ) return s == nil or type( s ) == 'string' and mw.text.trim( s ) == '' end , extract_options = function ( frame, optionsPrefix ) optionsPrefix = optionsPrefix or 'options' local options, n, more = {} if frame.args['module_options'] then local module_options = mw.loadData( frame.args['module_options'] ) if type( module_options ) ~= 'table' then return {} end local title = mw.title.getCurrentTitle() local local_ptions = module_options[ title.namespace ] or module_options[ title.nsText ] or {} for k, v in pairs( local_ptions ) do options[k] = v end end repeat ok, more = pcall( mw.text.jsonDecode, frame.args[optionsPrefix .. ( n or '' )] ) if ok and type( more ) == 'table' then for k, v in pairs( more ) do options[k] = v end end n = ( n or 0 ) + 1 until not ok return options end , build_namelist = function ( template_name, sp ) local res = { template_name } if sp then if type( sp ) == 'string' then sp = { sp } end for _, p in ipairs( sp ) do table.insert( res, template_name .. '/' .. p ) end end return res end , table_empty = function( t ) -- normally, test if next(t) is nil, but for some perverse reason, non-empty tables returned by loadData return nil... if type( t ) ~= 'table' then return true end for a, b in pairs( t ) do return false end return true end , } local function _readTemplateData( templateName ) local title = mw.title.makeTitle( 0, templateName ) local templateContent = title and title.exists and title:getContent() -- template's raw content local capture = templateContent and mw.ustring.match( templateContent, '<templatedata%s*>(.*)</templatedata%s*>' ) -- templatedata as text --capture = capture and mw.ustring.gsub( capture, '"(%d+)"', tonumber ) -- convert "1": {} to 1: {}. frame.args uses numerical indexes for order-based params. local trailingComma = capture and mw.ustring.find( capture, ',%s*[%]%}]' ) -- look for ,] or ,} : jsonDecode allows it, but it's verbotten in json if capture and not trailingComma then return pcall( mw.text.jsonDecode, capture ) end return false end local function readTemplateData( templateName ) if type( templateName ) == 'string' then templateName = { templateName, templateName .. '/' .. docSubPage } end if type( templateName ) == "table" then for _, name in ipairs( templateName ) do local td, result = _readTemplateData( name ) if td then return result end end end return nil end -- this is the function to be called by other modules. it expects the frame, and then an optional list of subpages, e.g. { "Documentation" }. -- if second parameter is nil, only tempalte page will be searched for templatedata. function calculateViolations( frame, subpages ) -- used for parameter type validy test. keyed by TD 'type' string. values are function(val) returning bool. local type_validators = { ['number'] = function( s ) return mw.language.getContentLanguage():parseFormattedNumber( s ) end } function compatible( typ, val ) local func = type_validators[typ] return type( func ) ~= 'function' or util.empty( val ) or func( val ) end local t_frame = frame:getParent() local t_args, template_name = t_frame.args, t_frame:getTitle() template_name = mw.ustring.gsub( template_name, '/sandbox', '', 1 ) local td_source = util.build_namelist( template_name, subpages ) if frame.args['td_source'] then table.insert(td_source, frame.args['td_source']) end local templatedata = readTemplateData( td_source ) local td_params = templatedata and templatedata.params local all_aliases, all_series = {}, {} if not td_params then return { ['no-templatedata'] = { [''] = '' } } end -- from this point on, we know templatedata is valid. local res = {} -- before returning to caller, we'll prune empty tables -- allow for aliases for x, p in pairs( td_params ) do for y, alias in ipairs( p.aliases or {} ) do p['primary'] = x td_params[x] = p all_aliases[alias] = p if tonumber(alias) then all_aliases[tonumber(alias)] = p end end end -- handle undeclared and deprecated local already_seen = {} local series = frame.args['series'] for p_name, value in pairs( t_args ) do local tp_param, noval, numeric, table_name = td_params[p_name] or all_aliases[p_name], util.empty( value ), tonumber( p_name ) local hasval = not noval if not tp_param and series then -- 2nd chance. check to see if series for s_name, p in pairs(td_params) do if mw.ustring.match( p_name, '^' .. s_name .. '%d+' .. '$') then -- mw.log('found p_name '.. p_name .. ' s_name:' .. s_name, ' p is:', p) debugging series support tp_param = p end -- don't bother breaking. td always correct. end end if not tp_param then -- not in TD: this is called undeclared -- calculate the relevant table for this undeclared parameter, based on parameter and value types table_name = noval and numeric and 'empty-undeclared-numeric' or noval and not numeric and 'empty-undeclared' or hasval and numeric and 'undeclared-numeric' or 'undeclared' -- tzvototi nishar. else -- in td: test for deprecation and mistype. if deprecated, no further tests table_name = tp_param.deprecated and hasval and 'deprecated' or tp_param.deprecated and noval and 'empty-deprecated' or not compatible( tp_param.type, value ) and 'incompatible' or not series and already_seen[tp_param] and hasval and 'duplicate' if hasval and table_name ~= 'duplicate' then already_seen[tp_param] = p_name end end -- report it. if table_name then res[table_name] = res[table_name] or {} if table_name == 'duplicate' then local primary_param = tp_param['primary'] local primaryData = res[table_name][primary_param] if not primaryData then primaryData = {} table.insert(primaryData, already_seen[tp_param]) end table.insert(primaryData, p_name) res[table_name][primary_param] = primaryData else res[table_name][p_name] = value end end end -- check for empty/missing parameters declared "required" for p_name, param in pairs( td_params ) do if param.required and util.empty( t_args[p_name] ) then local is_alias for _, alias in ipairs( param.aliases or {} ) do is_alias = is_alias or not util.empty( t_args[alias] ) end if not is_alias then res['empty-required'] = res['empty-required'] or {} res['empty-required'][p_name] = '' end end end mw.logObject(res) return res end -- wraps report in hidden frame function wrapReport(report, template_name, options) mw.logObject(report) if util.empty( report ) then return '' end local naked = mw.title.new( template_name )['text'] naked = mw.ustring.gsub(naked, 'Infobox', 'infobox', 1) report = ( options['wrapper-prefix'] or "<div class = 'paramvalidator-wrapper'><span class='paramvalidator-error'>" ) .. report .. ( options['wrapper-suffix'] or "</span></div>" ) report = mw.ustring.gsub( report, 'tname_naked', naked ) report = mw.ustring.gsub( report, 'templatename', template_name ) return report end -- this is the "user" version, called with {{#invoke:}} returns a string, as defined by the options parameter function validateParams( frame ) local options, report, template_name = util.extract_options( frame ), '', frame:getParent():getTitle() local ignore = function( p_name ) for _, pattern in ipairs( options['ignore'] or {} ) do if mw.ustring.match( p_name, '^' .. pattern .. '$' ) then return true end end return false end local replace_macros = function( error_type, s, param_names ) function concat_and_escape( t , sep ) sep = sep or ', ' local s = table.concat( t, sep ) return ( mw.ustring.gsub( s, '%%', '%%%%' ) ) end if s and ( type( param_names ) == 'table' ) then local k_ar, kv_ar = {}, {} for k, v in pairs( param_names ) do table.insert( k_ar, k ) if type(v) == 'table' then v = table.concat(v, ', ') end if error_type == 'duplicate' then table.insert( kv_ar, v) else table.insert( kv_ar, k .. ': ' .. v) end end s = mw.ustring.gsub( s, 'paramname', concat_and_escape( k_ar ) ) s = mw.ustring.gsub( s, 'paramandvalue', concat_and_escape( kv_ar, ' AND ' ) ) if mw.getCurrentFrame():preprocess( "{{REVISIONID}}" ) ~= "" then s = mw.ustring.gsub( s, "<div.*<%/div>", "", 1 ) end end return s end local report_params = function( key, param_names ) local res = replace_macros( key, options[key], param_names ) res = frame:preprocess(res or '') report = report .. ( res or '' ) return res end -- no option no work. if util.table_empty( options ) then return '' end -- get the errors. local violations = calculateViolations( frame, options['doc-subpage'] ) -- special request of bora: use skip_empty_numeric if violations['empty-undeclared-numeric'] then for i = 1, tonumber( options['skip-empty-numeric'] ) or 0 do violations['empty-undeclared-numeric'][i] = nil end end -- handle ignore list, and prune empty violations - in that order! local offenders = 0 for name, tab in pairs( violations ) do -- remove ignored parameters from all violations for pname in pairs( tab ) do if ignore( pname ) then tab[pname] = nil end end -- prune empty violations if util.table_empty( tab ) then violations[name] = nil end -- WORK IS DONE. report the errors. -- if report then count it. if violations[name] and report_params( name, tab ) then offenders = offenders + 1 end end if offenders > 1 then report_params( 'multiple' ) end if offenders ~= 0 then report_params( 'any' ) end -- could have tested for empty( report ), but since we count them anyway... return wrapReport(report, template_name, options) end return { ['validateparams'] = validateParams, ['calculateViolations'] = calculateViolations, ['wrapReport'] = wrapReport }
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 util empty function s return s nil or type s string and mw text trim s end extract options function frame optionsPrefix optionsPrefix optionsPrefix or options local options n more if frame args module options then local module options mw loadData frame args module options if type module options table then return end local title mw title getCurrentTitle local local ptions module options title namespace or module options title nsText or for k v in pairs local ptions do options k v end end repeat ok more pcall mw text jsonDecode frame args optionsPrefix n or if ok and type more table then for k v in pairs more do options k v end end n n or 0 1 until not ok return options end build namelist function template name sp local res template name if sp then if type sp string then sp sp end for p in ipairs sp do table insert res template name p end end return res end table empty function t normally test if next t is nil but for some perverse reason non empty tables returned by loadData return nil if type t table then return true end for a b in pairs t do return false end return true end local function readTemplateData templateName local title mw title makeTitle 0 templateName local templateContent title and title exists and title getContent template s raw content local capture templateContent and mw ustring match templateContent lt templatedata s gt lt templatedata s gt templatedata as text capture capture and mw ustring gsub capture d tonumber convert 1 to 1 frame args uses numerical indexes for order based params local trailingComma capture and mw ustring find capture s look for or jsonDecode allows it but it s verbotten in json if capture and not trailingComma then return pcall mw text jsonDecode capture end return false end local function readTemplateData templateName if type templateName string then templateName templateName templateName docSubPage end if type templateName table then for name in ipairs templateName do local td result readTemplateData name if td then return result end end end return nil end this is the function to be called by other modules it expects the frame and then an optional list of subpages e g Documentation if second parameter is nil only tempalte page will be searched for templatedata function calculateViolations frame subpages used for parameter type validy test keyed by TD type string values are function val returning bool local type validators number function s return mw language getContentLanguage parseFormattedNumber s end function compatible typ val local func type validators typ return type func function or util empty val or func val end local t frame frame getParent local t args template name t frame args t frame getTitle template name mw ustring gsub template name sandbox 1 local td source util build namelist template name subpages if frame args td source then table insert td source frame args td source end local templatedata readTemplateData td source local td params templatedata and templatedata params local all aliases all series if not td params then return no templatedata end from this point on we know templatedata is valid local res before returning to caller we ll prune empty tables allow for aliases for x p in pairs td params do for y alias in ipairs p aliases or do p primary x td params x p all aliases alias p if tonumber alias then all aliases tonumber alias p end end end handle undeclared and deprecated local already seen local series frame args series for p name value in pairs t args do local tp param noval numeric table name td params p name or all aliases p name util empty value tonumber p name local hasval not noval if not tp param and series then 2nd chance check to see if series for s name p in pairs td params do if mw ustring match p name s name d then mw log found p name p name s name s name p is p debugging series support tp param p end don t bother breaking td always correct end end if not tp param then not in TD this is called undeclared calculate the relevant table for this undeclared parameter based on parameter and value types table name noval and numeric and empty undeclared numeric or noval and not numeric and empty undeclared or hasval and numeric and undeclared numeric or undeclared tzvototi nishar else in td test for deprecation and mistype if deprecated no further tests table name tp param deprecated and hasval and deprecated or tp param deprecated and noval and empty deprecated or not compatible tp param type value and incompatible or not series and already seen tp param and hasval and duplicate if hasval and table name duplicate then already seen tp param p name end end report it if table name then res table name res table name or if table name duplicate then local primary param tp param primary local primaryData res table name primary param if not primaryData then primaryData table insert primaryData already seen tp param end table insert primaryData p name res table name primary param primaryData else res table name p name value end end end check for empty missing parameters declared required for p name param in pairs td params do if param required and util empty t args p name then local is alias for alias in ipairs param aliases or do is alias is alias or not util empty t args alias end if not is alias then res empty required res empty required or res empty required p name end end end mw logObject res return res end wraps report in hidden frame function wrapReport report template name options mw logObject report if util empty report then return end local naked mw title new template name text naked mw ustring gsub naked Infobox infobox 1 report options wrapper prefix or lt div class paramvalidator wrapper gt lt span class paramvalidator error gt report options wrapper suffix or lt span gt lt div gt report mw ustring gsub report tname naked naked report mw ustring gsub report templatename template name return report end this is the user version called with invoke returns a string as defined by the options parameter function validateParams frame local options report template name util extract options frame frame getParent getTitle local ignore function p name for pattern in ipairs options ignore or do if mw ustring match p name pattern then return true end end return false end local replace macros function error type s param names function concat and escape t sep sep sep or local s table concat t sep return mw ustring gsub s end if s and type param names table then local k ar kv ar for k v in pairs param names do table insert k ar k if type v table then v table concat v end if error type duplicate then table insert kv ar v else table insert kv ar k v end end s mw ustring gsub s paramname concat and escape k ar s mw ustring gsub s paramandvalue concat and escape kv ar AND if mw getCurrentFrame preprocess REVISIONID then s mw ustring gsub s lt div lt div gt 1 end end return s end local report params function key param names local res replace macros key options key param names res frame preprocess res or report report res or return res end no option no work if util table empty options then return end get the errors local violations calculateViolations frame options doc subpage special request of bora use skip empty numeric if violations empty undeclared numeric then for i 1 tonumber options skip empty numeric or 0 do violations empty undeclared numeric i nil end end handle ignore list and prune empty violations in that order local offenders 0 for name tab in pairs violations do remove ignored parameters from all violations for pname in pairs tab do if ignore pname then tab pname nil end end prune empty violations if util table empty tab then violations name nil end WORK IS DONE report the errors if report then count it if violations name and report params name tab then offenders offenders 1 end end if offenders gt 1 then report params multiple end if offenders 0 then report params any end could have tested for empty report but since we count them anyway return wrapReport report template name options end return validateparams validateParams calculateViolations calculateViolations wrapReport wrapReport