Anda dapat membuat halaman dokumentasi untuk buat pada modul Scribunto ini.
Penyunting dapat melakukan uji coba pada halaman bak pasir (buat | cermin) dan kasus uji (buat) modul ini.
Subhalaman modul ini.
Penyunting dapat melakukan uji coba pada halaman bak pasir (buat | cermin) dan kasus uji (buat) modul ini.
Subhalaman modul ini.
localutil={ empty=function(s) returns==nilortype(s)=='string'andmw.text.trim(s)=='' end , extract_options=function(frame,optionsPrefix) optionsPrefix=optionsPrefixor'options' localoptions,n,more={} ifframe.args['module_options']then localmodule_options=mw.loadData(frame.args['module_options']) iftype(module_options)~='table'thenreturn{}end localtitle=mw.title.getCurrentTitle() locallocal_ptions=module_options[title.namespace]ormodule_options[title.nsText]or{} fork,vinpairs(local_ptions)dooptions[k]=vend end repeat ok,more=pcall(mw.text.jsonDecode,frame.args[optionsPrefix..(nor'')]) ifokandtype(more)=='table'then fork,vinpairs(more)dooptions[k]=vend end n=(nor0)+1 untilnotok returnoptions end , build_namelist=function(template_name,sp) localres={template_name} ifspthen iftype(sp)=='string'thensp={sp}end for_,pinipairs(sp)dotable.insert(res,template_name..'/'..p)end end returnres 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... iftype(t)~='table'thenreturntrueend fora,binpairs(t)doreturnfalseend returntrue end , } localfunction_readTemplateData(templateName) localtitle=mw.title.makeTitle(0,templateName) localtemplateContent=titleandtitle.existsandtitle:getContent()-- template's raw content localcapture=templateContentandmw.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. localtrailingComma=captureandmw.ustring.find(capture,',%s*[%]%}]')-- look for ,] or ,} : jsonDecode allows it, but it's verbotten in json ifcaptureandnottrailingCommathenreturnpcall(mw.text.jsonDecode,capture)end returnfalse end localfunctionreadTemplateData(templateName) iftype(templateName)=='string'then templateName={templateName,templateName..'/'..docSubPage} end iftype(templateName)=="table"then for_,nameinipairs(templateName)do localtd,result=_readTemplateData(name) iftdthenreturnresultend end end returnnil 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. functioncalculateViolations(frame,subpages) -- used for parameter type validy test. keyed by TD 'type' string. values are function(val) returning bool. localtype_validators={ ['number']=function(s)returnmw.language.getContentLanguage():parseFormattedNumber(s)end } functioncompatible(typ,val) localfunc=type_validators[typ] returntype(func)~='function'orutil.empty(val)orfunc(val) end localt_frame=frame:getParent() localt_args,template_name=t_frame.args,t_frame:getTitle() template_name=mw.ustring.gsub(template_name,'/sandbox','',1) localtd_source=util.build_namelist(template_name,subpages) ifframe.args['td_source']then table.insert(td_source,frame.args['td_source']) end localtemplatedata=readTemplateData(td_source) localtd_params=templatedataandtemplatedata.params localall_aliases,all_series={},{} ifnottd_paramsthenreturn{['no-templatedata']={['']=''}}end -- from this point on, we know templatedata is valid. localres={}-- before returning to caller, we'll prune empty tables -- allow for aliases forx,pinpairs(td_params)dofory,aliasinipairs(p.aliasesor{})do p['primary']=x td_params[x]=p all_aliases[alias]=p iftonumber(alias)thenall_aliases[tonumber(alias)]=pend endend -- handle undeclared and deprecated localalready_seen={} localseries=frame.args['series'] forp_name,valueinpairs(t_args)do localtp_param,noval,numeric,table_name=td_params[p_name]orall_aliases[p_name],util.empty(value),tonumber(p_name) localhasval=notnoval ifnottp_paramandseriesthen-- 2nd chance. check to see if series fors_name,pinpairs(td_params)do ifmw.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 ifnottp_paramthen-- not in TD: this is called undeclared -- calculate the relevant table for this undeclared parameter, based on parameter and value types table_name= novalandnumericand'empty-undeclared-numeric'or novalandnotnumericand'empty-undeclared'or hasvalandnumericand'undeclared-numeric'or 'undeclared'-- tzvototi nishar. else-- in td: test for deprecation and mistype. if deprecated, no further tests table_name=tp_param.deprecatedandhasvaland'deprecated' ortp_param.deprecatedandnovaland'empty-deprecated' ornotcompatible(tp_param.type,value)and'incompatible' ornotseriesandalready_seen[tp_param]andhasvaland'duplicate' ifhasvalandtable_name~='duplicate'then already_seen[tp_param]=p_name end end -- report it. iftable_namethen res[table_name]=res[table_name]or{} iftable_name=='duplicate'then localprimary_param=tp_param['primary'] localprimaryData=res[table_name][primary_param] ifnotprimaryDatathen 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" forp_name,paraminpairs(td_params)do ifparam.requiredandutil.empty(t_args[p_name])then localis_alias for_,aliasinipairs(param.aliasesor{})dois_alias=is_aliasornotutil.empty(t_args[alias])end ifnotis_aliasthen res['empty-required']=res['empty-required']or{} res['empty-required'][p_name]='' end end end mw.logObject(res) returnres end -- wraps report in hidden frame functionwrapReport(report,template_name,options) mw.logObject(report) ifutil.empty(report)thenreturn''end localnaked=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) returnreport end -- this is the "user" version, called with {{#invoke:}} returns a string, as defined by the options parameter functionvalidateParams(frame) localoptions,report,template_name=util.extract_options(frame),'',frame:getParent():getTitle() localignore=function(p_name) for_,patterninipairs(options['ignore']or{})do ifmw.ustring.match(p_name,'^'..pattern..'$')thenreturntrueend end returnfalse end localreplace_macros=function(error_type,s,param_names) functionconcat_and_escape(t,sep) sep=sepor', ' locals=table.concat(t,sep) return(mw.ustring.gsub(s,'%%','%%%%')) end ifsand(type(param_names)=='table')then localk_ar,kv_ar={},{} fork,vinpairs(param_names)do table.insert(k_ar,k) iftype(v)=='table'then v=table.concat(v,', ') end iferror_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 ')) ifmw.getCurrentFrame():preprocess("{{REVISIONID}}")~=""then s=mw.ustring.gsub(s,"<div.*<%/div>","",1) end end returns end localreport_params=function(key,param_names) localres=replace_macros(key,options[key],param_names) res=frame:preprocess(resor'') report=report..(resor'') returnres end -- no option no work. ifutil.table_empty(options)thenreturn''end -- get the errors. localviolations=calculateViolations(frame,options['doc-subpage']) -- special request of bora: use skip_empty_numeric ifviolations['empty-undeclared-numeric']then fori=1,tonumber(options['skip-empty-numeric'])or0do violations['empty-undeclared-numeric'][i]=nil end end -- handle ignore list, and prune empty violations - in that order! localoffenders=0 forname,tabinpairs(violations)do -- remove ignored parameters from all violations forpnameinpairs(tab)doifignore(pname)thentab[pname]=nilendend -- prune empty violations ifutil.table_empty(tab)thenviolations[name]=nilend -- WORK IS DONE. report the errors. -- if report then count it. ifviolations[name]andreport_params(name,tab)thenoffenders=offenders+1end end ifoffenders>1thenreport_params('multiple')end ifoffenders~=0thenreport_params('any')end-- could have tested for empty( report ), but since we count them anyway... returnwrapReport(report,template_name,options) end return{ ['validateparams']=validateParams, ['calculateViolations']=calculateViolations, ['wrapReport']=wrapReport }