Module:Excerpt/sandbox
Appearance
From Wikipedia, the free encyclopedia
This is the module sandbox page for Module:Excerpt (diff).
See also the companion subpage for test cases.
See also the companion subpage for test cases.
This module is rated as beta. It is considered ready for widespread use, but as it is still relatively new, it should be applied with some caution to ensure results are as expected.
Warning This Lua module is used on approximately 13,000 pages and changes may be widely noticed. Test changes in the module's /sandbox or /testcases subpages, or in your own module sandbox. Consider discussing changes on the talk page before implementing them.
This module depends on the following other modules:
This module implements Template:Excerpt.
- See Template:Excerpt for documentation on the template parameters
- See mw:Module:Excerpt for documentation on this module
- See Module:Excerpt/config for configuration of this module
Portals
[edit ]Portals use a previous version of this module:
- Module:Excerpt/portals / sandbox — Used by:
- {{Transclude lead excerpt }} / sandbox / testcases
- {{Transclude linked excerpt }} / sandbox / testcases
- {{Transclude list item excerpt }} / sandbox / testcases
- {{Transclude random excerpt }} / sandbox / testcases
- {{Transclude selected excerpt }} / sandbox / testcases
- Module:Excerpt slideshow / sandbox — Uses Module:Excerpt/portals and is used by:
- Module:Random slideshow / sandbox — Uses Module:Excerpt/portals and is used by:
- {{Random slideshow }} / sandbox / testcases
- {{Transclude files as random slideshow }} / sandbox / testcases
The above documentation is transcluded from Module:Excerpt/doc. (edit | history)
Editors can experiment in this module's sandbox (edit | diff) and testcases (edit) pages.
Add categories to the /doc subpage. Subpages of this module.
Editors can experiment in this module's sandbox (edit | diff) and testcases (edit) pages.
Add categories to the /doc subpage. Subpages of this module.
-- Module:Excerpt implements the Excerpt template -- Documentation and master version: https://en.wikipedia.org/wiki/Module:Excerpt -- Authors: User:Sophivorus, User:Certes, User:Aidan9382 & others -- License: CC-BY-SA-3.0 localparser=require('Module:WikitextParser/sandbox') localyesno=require('Module:Yesno') localok,config=pcall(require,'Module:Excerpt/config/sandbox') ifnotokthenconfig={}end localExcerpt={} -- Main entry point for templates functionExcerpt.main(frame) -- Make sure the requested page exists and get the wikitext localpage=Excerpt.getArg(1) ifnotpageorpage=='{{{1}}}'thenreturnExcerpt.getError('no-page')end localtitle=mw.title.new(page) ifnottitlethenreturnExcerpt.getError('invalid-title',page)end localfragment=title.fragment-- save for later iftitle.isRedirectthen title=title.redirectTarget iffragment==""then fragment=title.fragment-- page merge potential end end ifnottitle.existsthenreturnExcerpt.getError('page-not-found',page)end page=title.prefixedText localwikitext=title:getContent() -- Get the template params and process them localparams={ hat=yesno(Excerpt.getArg('hat',true)), this=Excerpt.getArg('this'), only=Excerpt.getArg('only'), files=Excerpt.getArg('files',Excerpt.getArg('file')), lists=Excerpt.getArg('lists',Excerpt.getArg('list')), tables=Excerpt.getArg('tables',Excerpt.getArg('table')), templates=Excerpt.getArg('templates',Excerpt.getArg('template')), paragraphs=Excerpt.getArg('paragraphs',Excerpt.getArg('paragraph')), references=yesno(Excerpt.getArg('references',true)), subsections=yesno(Excerpt.getArg('subsections',false)), links=yesno(Excerpt.getArg('links',true)), bold=yesno(Excerpt.getArg('bold',false)), briefDates=yesno(Excerpt.getArg('briefdates',false)), inline=yesno(Excerpt.getArg('inline')), quote=yesno(Excerpt.getArg('quote')), more=yesno(Excerpt.getArg('more')), class=Excerpt.getArg('class'), track=yesno(Excerpt.getArg('track',true)), displayTitle=Excerpt.getArg('displaytitle',page), } -- Make sure the requested section exists and get the excerpt localexcerpt localsection=Excerpt.getArg(2,fragment) section=mw.text.trim(section) ifsection==''thensection=nilend ifsectionthen excerpt=parser.getSectionTag(wikitext,section) ifnotexcerptthen ifparams.subsectionsthen excerpt=parser.getSection(wikitext,section) else localsections=parser.getSections(wikitext) excerpt=sections[section] end end ifnotexcerptthenreturnExcerpt.getError('section-not-found',section)end ifexcerpt==''thenreturnExcerpt.getError('section-empty',section)end else excerpt=parser.getLead(wikitext) ifexcerpt==''thenreturnExcerpt.getError('lead-empty')end end -- Remove noinclude bits excerpt=excerpt:gsub('<[Nn][Oo][Ii][Nn][Cc][Ll][Uu][Dd][Ee]>.-</[Nn][Oo][Ii][Nn][Cc][Ll][Uu][Dd][Ee]>','') -- Filter various elements from the excerpt excerpt=Excerpt.filterFiles(excerpt,params.files) excerpt=Excerpt.filterLists(excerpt,params.lists) excerpt=Excerpt.filterTables(excerpt,params.tables) excerpt=Excerpt.filterParagraphs(excerpt,params.paragraphs) -- If no file is found, try to get one from the infobox if(params.only=='file'orparams.only=='files'ornotparams.onlyand(notparams.filesorparams.files~='0'))-- caller asked for files andnotsection-- and we're in the lead section andconfig.captions-- and we have the config option required to try finding files in infoboxes and#parser.getFiles(excerpt)==0-- and there're no files in the excerpt then excerpt=Excerpt.addInfoboxFile(excerpt) end -- Filter the templates by appending the templates blacklist to the templates filter ifconfig.blacklistthen localblacklist=table.concat(config.blacklist,',') ifparams.templatesthen ifstring.sub(params.templates,1,1)=='-'then params.templates=params.templates..','..blacklist end else params.templates='-'..blacklist end end excerpt=Excerpt.filterTemplates(excerpt,params.templates) -- Leave only the requested elements ifparams.only=='file'orparams.only=='files'then localfiles=parser.getFiles(excerpt) excerpt=params.only=='file'andfiles[1]ortable.concat(files,'\n\n') end ifparams.only=='list'orparams.only=='lists'then locallists=parser.getLists(excerpt) excerpt=params.only=='list'andlists[1]ortable.concat(lists,'\n\n') end ifparams.only=='table'orparams.only=='tables'then localtables=parser.getTables(excerpt) excerpt=params.only=='table'andtables[1]ortable.concat(tables,'\n\n') end ifparams.only=='paragraph'orparams.only=='paragraphs'then localparagraphs=parser.getParagraphs(excerpt) excerpt=params.only=='paragraph'andparagraphs[1]ortable.concat(paragraphs,'\n\n') end ifparams.only=='template'orparams.only=='templates'then localtemplates=parser.getTemplates(excerpt) excerpt=params.only=='template'andtemplates[1]ortable.concat(templates,'\n\n') end -- @todo Make more robust and move downwards ifparams.briefDatesthen excerpt=Excerpt.fixDates(excerpt) end -- Remove unwanted elements excerpt=Excerpt.removeComments(excerpt) excerpt=Excerpt.removeSelfLinks(excerpt) excerpt=Excerpt.removeNonFreeFiles(excerpt) excerpt=Excerpt.removeBehaviorSwitches(excerpt) -- Fix or remove the references ifparams.referencesthen excerpt=Excerpt.fixReferences(excerpt,page,wikitext) else excerpt=Excerpt.removeReferences(excerpt) end -- Remove wikilinks ifnotparams.linksthen excerpt=Excerpt.removeLinks(excerpt) end -- Link the bold text near the start of most leads and then remove it ifnotsectionthen excerpt=Excerpt.linkBold(excerpt,page) end ifnotparams.boldthen excerpt=Excerpt.removeBold(excerpt) end -- Remove extra line breaks but leave one before and after so the parser interprets lists, tables, etc. correctly excerpt=excerpt:gsub('\n\n\n+','\n\n') excerpt=mw.text.trim(excerpt) excerpt='\n'..excerpt..'\n' -- Remove nested categories excerpt=frame:preprocess(excerpt) excerpt=Excerpt.removeCategories(excerpt) -- Add tracking categories ifparams.trackandconfig.categoriesthen excerpt=Excerpt.addTrackingCategories(excerpt) end -- Build the final output ifparams.inlinethen returnmw.text.trim(excerpt) end localtag=params.quoteand'blockquote'or'div' localblock=mw.html.create(tag):addClass('excerpt-block'):addClass(params.class) ifconfig.stylesthen localstyles=frame:extensionTag('templatestyles','',{src=config.styles}) block:node(styles) end ifparams.hatthen localhat=Excerpt.getHat(page,section,params) block:node(hat) end excerpt=mw.html.create('div'):addClass('excerpt'):wikitext(excerpt) block:node(excerpt) ifparams.morethen localmore=Excerpt.getReadMore(page,section) block:node(more) end returnblock end -- Filter the files in the given wikitext against the given filter functionExcerpt.filterFiles(wikitext,filter) ifnotfilterthenreturnwikitextend localfilters,isBlacklist=Excerpt.parseFilter(filter) localfiles=parser.getFiles(wikitext) forindex,fileinpairs(files)do localname=parser.getFileName(file) ifisBlacklistand(Excerpt.matchFilter(index,filters)orExcerpt.matchFilter(name,filters)) ornotisBlacklistand(notExcerpt.matchFilter(index,filters)andnotExcerpt.matchFilter(name,filters))then wikitext=Excerpt.removeString(wikitext,file) end end returnwikitext end -- Filter the lists in the given wikitext against the given filter functionExcerpt.filterLists(wikitext,filter) ifnotfilterthenreturnwikitextend localfilters,isBlacklist=Excerpt.parseFilter(filter) locallists=parser.getLists(wikitext) forindex,listinpairs(lists)do ifisBlacklistandExcerpt.matchFilter(index,filters) ornotisBlacklistandnotExcerpt.matchFilter(index,filters)then wikitext=Excerpt.removeString(wikitext,list) end end returnwikitext end -- Filter the tables in the given wikitext against the given filter functionExcerpt.filterTables(wikitext,filter) ifnotfilterthenreturnwikitextend localfilters,isBlacklist=Excerpt.parseFilter(filter) localtables=parser.getTables(wikitext) forindex,tableWikitextinpairs(tables)do localid=parser.getTableAttribute(tableWikitext,'id') ifisBlacklistand(Excerpt.matchFilter(index,filters)orExcerpt.matchFilter(id,filters)) ornotisBlacklistand(notExcerpt.matchFilter(index,filters)andnotExcerpt.matchFilter(id,filters))then wikitext=Excerpt.removeString(wikitext,tableWikitext) end end returnwikitext end -- Filter the paragraphs in the given wikitext against the given filter functionExcerpt.filterParagraphs(wikitext,filter) ifnotfilterthenreturnwikitextend localfilters,isBlacklist=Excerpt.parseFilter(filter) localparagraphs=parser.getParagraphs(wikitext) forindex,paragraphinpairs(paragraphs)do ifisBlacklistandExcerpt.matchFilter(index,filters) ornotisBlacklistandnotExcerpt.matchFilter(index,filters)then wikitext=Excerpt.removeString(wikitext,paragraph) end end returnwikitext end -- Filter the templates in the given wikitext against the given filter functionExcerpt.filterTemplates(wikitext,filter) ifnotfilterthenreturnwikitextend localfilters,isBlacklist=Excerpt.parseFilter(filter) localtemplates=parser.getTemplates(wikitext) forindex,templateinpairs(templates)do localname=parser.getTemplateName(template) ifisBlacklistand(Excerpt.matchFilter(index,filters)orExcerpt.matchFilter(name,filters)) ornotisBlacklistand(notExcerpt.matchFilter(index,filters)andnotExcerpt.matchFilter(name,filters))then wikitext=Excerpt.removeString(wikitext,template) end end returnwikitext end functionExcerpt.addInfoboxFile(excerpt) -- We cannot distinguish the infobox from the other templates, so we search them all localtemplates=parser.getTemplates(excerpt) for_,templateinpairs(templates)do localparameters=parser.getTemplateParameters(template) localfile,captions,caption,cssClasses,cssClass for_,pairinpairs(config.captions)do file=pair[1] file=parameters[file] iffileandExcerpt.matchAny(file,'^.*%.',{'[Jj][Pp][Ee]?[Gg]','[Pp][Nn][Gg]','[Gg][Ii][Ff]','[Ss][Vv][Gg]'},'.*')then file=string.match(file,'%[?%[?.-:([^{|]+)%]?%]?')orfile-- [[File:Example.jpg{{!}}upright=1.5]] to Example.jpg captions=pair[2] for_,pinpairs(captions)do ifparameters[p]thencaption=parameters[p]breakend end -- Check for CSS classes -- We opt to use skin-invert-image instead of skin-invert -- in all other cases, the CSS provided in the infobox is used ifpair[3]then cssClasses=pair[3] for_,pinpairs(cssClasses)do ifparameters[p]then cssClass=(parameters[p]=='skin-invert')and'skin-invert-image'orparameters[p] break end end end localclass=cssClassand('|class='..cssClass)or'' return'[[File:'..file..class..'|thumb|'..(captionor'')..']]'..excerpt end end end returnexcerpt end functionExcerpt.removeNonFreeFiles(wikitext) localfiles=parser.getFiles(wikitext) for_,fileinpairs(files)do localfileName='File:'..parser.getFileName(file) localfileTitle=mw.title.new(fileName) iffileTitlethen localfileDescription=fileTitle:getContent() ifnotfileDescriptionorfileDescription==''then localframe=mw.getCurrentFrame() fileDescription=frame:preprocess('{{'..fileName..'}}')-- try Commons end iffileDescriptionandstring.match(fileDescription,'[Nn]on%-free')then wikitext=Excerpt.removeString(wikitext,file) end end end returnwikitext end functionExcerpt.getHat(page,section,params) localhat -- Build the text ifparams.thisthen hat=params.this elseifparams.quotethen hat=Excerpt.getMessage('this') elseifparams.onlythen hat=Excerpt.getMessage(params.only) else hat=Excerpt.getMessage('section') end hat=hat..' '..Excerpt.getMessage('excerpt') -- Build the link ifsectionthen hat=hat..' [[:'..page..'#'..mw.uri.anchorEncode(section)..'|'..params.displayTitle ..' § '..section:gsub('%[%[([^]|]+)|?[^]]*%]%]','%1')..']].'-- remove nested links else hat=hat..' [[:'..page..'|'..params.displayTitle..']].' end -- Build the edit link localtitle=mw.title.new(page) localeditUrl=title:fullUrl('action=edit') hat=hat..'<span class="mw-editsection-like plainlinks"><span class="mw-editsection-bracket">[</span>[' hat=hat..editUrl..' '..mw.message.new('editsection'):plain() hat=hat..']<span class="mw-editsection-bracket">]</span></span>' ifconfig.hatthen localframe=mw.getCurrentFrame() hat=config.hat..hat..'}}' hat=frame:preprocess(hat) else hat=mw.html.create('div'):addClass('dablink excerpt-hat'):wikitext(hat) end returnhat end functionExcerpt.getReadMore(page,section) locallink="'''[["..page ifsectionthen link=link..'#'..section end localtext=Excerpt.getMessage('more') link=link..'|'..text.."]]'''" link=mw.html.create('div'):addClass('noprint excerpt-more'):wikitext(link) returnlink end -- Fix birth and death dates, but only in the first paragraph -- @todo Use parser.getParagraphs() to get the first paragraph functionExcerpt.fixDates(excerpt) localstart=1-- skip initial templates locals locale=0 repeat start=e+1 s,e=mw.ustring.find(excerpt,'%s*%b{}%s*',start) untilnotsors>start s,e=mw.ustring.find(excerpt,'%b()',start)-- get (...), which may be (year–year) ifsands<start+100then-- look only near the start localexcerptStart=mw.ustring.sub(excerpt,s,e) localyear1,conjunction,year2=string.match(excerptStart,'(%d%d%d+)(.-)(%d%d%d+)') ifyear1andyear2and(string.match(conjunction,'[%-–—]')orstring.match(conjunction,'{{%s*[sS]nd%s*}}'))then localy1=tonumber(year1) localy2=tonumber(year2) ify2>y1andy2<y1+125andy1<=tonumber(os.date('%Y'))then excerpt=mw.ustring.sub(excerpt,1,s)..year1..'–'..year2..mw.ustring.sub(excerpt,e) end end end returnexcerpt end -- Replace the first call to each reference defined outside of the excerpt for the full reference, to prevent undefined references -- Then prefix the page title to the reference names to prevent conflicts -- that is, replace <ref name="Foo"> for <ref name="Title of the article Foo"> -- and also <ref name="Foo" /> for <ref name="Title of the article Foo" /> -- also remove reference groups: <ref name="Foo" group="Bar"> for <ref name="Title of the article Foo"> -- and <ref group="Bar"> for <ref> -- @todo The current regex may fail in cases with both kinds of quotes, like <ref name="Darwin's book"> functionExcerpt.fixReferences(excerpt,page,wikitext) localreferences=parser.getReferences(excerpt) localfixed={} for_,referenceinpairs(references)do localname=parser.getTagAttribute(reference,'name') ifnotfixed[name]then-- fix each reference only once localcontent=parser.getTagContent(reference) ifnotcontentthen-- reference is self-closing localfull=parser.getReference(excerpt,name) ifnotfullthen-- the reference is not defined in the excerpt full=parser.getReference(wikitext,name) iffullthen excerpt=excerpt:gsub(Excerpt.escapeString(reference),Excerpt.escapeString(full),1) end table.insert(fixed,name) end end end end -- Prepend the page title to the reference names to prevent conflicts with other references in the transcluding page excerpt=excerpt:gsub('< *[Rr][Ee][Ff][^>]*name *= *["\']?([^"\'>/]+)["\']?[^>/]*(/?) *>','<ref name="'..page:gsub('"','')..' %1"%2>') -- Remove reference groups because they don't apply to the transcluding page excerpt=excerpt:gsub('< *[Rr][Ee][Ff] *group *= *["\']?[^"\'>/]+["\'] *>','<ref>') returnexcerpt end functionExcerpt.removeReferences(excerpt) localreferences=parser.getReferences(excerpt) for_,referenceinpairs(references)do excerpt=Excerpt.removeString(excerpt,reference) end returnexcerpt end functionExcerpt.removeCategories(excerpt) localcategories=parser.getCategories(excerpt) for_,categoryinpairs(categories)do excerpt=Excerpt.removeString(excerpt,category) end returnexcerpt end functionExcerpt.removeBehaviorSwitches(excerpt) returnexcerpt:gsub('__[A-Z]+__','') end functionExcerpt.removeComments(excerpt) returnexcerpt:gsub('<!%-%-.-%-%->','') end functionExcerpt.removeBold(excerpt) returnexcerpt:gsub("'''",'') end functionExcerpt.removeLinks(excerpt) locallinks=parser.getLinks(excerpt) for_,linkinpairs(links)do excerpt=Excerpt.removeString(excerpt,link) end returnexcerpt end -- @todo Use parser.getLinks functionExcerpt.removeSelfLinks(excerpt) locallang=mw.language.getContentLanguage() localpage=Excerpt.escapeString(mw.title.getCurrentTitle().prefixedText) localucpage=lang:ucfirst(page) locallcpage=lang:lcfirst(page) excerpt=excerpt :gsub('%[%[('..ucpage..')%]%]','%1') :gsub('%[%[('..lcpage..')%]%]','%1') :gsub('%[%['..ucpage..'|([^]]+)%]%]','%1') :gsub('%[%['..lcpage..'|([^]]+)%]%]','%1') returnexcerpt end -- Replace the bold title or synonym near the start of the page by a link to the page functionExcerpt.linkBold(excerpt,page) locallang=mw.language.getContentLanguage() localposition=mw.ustring.find(excerpt,"'''"..lang:ucfirst(page).."'''",1,true)-- look for "'''Foo''' is..." (uc) or "A '''foo''' is..." (lc) ormw.ustring.find(excerpt,"'''"..lang:lcfirst(page).."'''",1,true)-- plain search: special characters in page represent themselves ifpositionthen locallength=mw.ustring.len(page) excerpt=mw.ustring.sub(excerpt,1,position+2)..'[['..mw.ustring.sub(excerpt,position+3,position+length+2)..']]'..mw.ustring.sub(excerpt,position+length+3,-1)-- link it else-- look for anything unlinked in bold, assumed to be a synonym of the title (e.g. a person's birth name) excerpt=mw.ustring.gsub(excerpt,"'''(.-'*)'''",function(text) ifnotstring.find(text,'%[')andnotstring.find(text,'%{')then-- if not wikilinked or some weird template return"'''[["..page..'|'..text.."]]'''"-- replace '''Foo''' by '''[[page|Foo]]''' else returnnil-- instruct gsub to make no change end end,1)-- terminates the anonymous replacement function passed to gsub end returnexcerpt end functionExcerpt.addTrackingCategories(excerpt) localcurrentTitle=mw.title.getCurrentTitle() localcontentCategory=config.categories.content ifcontentCategoryandcurrentTitle.isContentPagethen excerpt=excerpt..'[[Category:'..contentCategory..']]' end localnamespaceCategory=config.categories[currentTitle.namespace] ifnamespaceCategorythen excerpt=excerpt..'[[Category:'..namespaceCategory..']]' end returnexcerpt end -- Helper method to match from a list of regular expressions -- Like so: match pre..list[1]..post or pre..list[2]..post or ... functionExcerpt.matchAny(text,pre,list,post,init) localmatch={} fori=1,#listdo match={mw.ustring.match(text,pre..list[i]..post,init)} ifmatch[1]thenreturnunpack(match)end end returnnil end -- Helper function to get arguments -- args from Lua calls have priority over parent args from template functionExcerpt.getArg(key,default) localframe=mw.getCurrentFrame() fork,valueinpairs(frame:getParent().args)do ifk==keyandmw.text.trim(value)~=''then returnvalue end end fork,valueinpairs(frame.args)do ifk==keyandmw.text.trim(value)~=''then returnvalue end end returndefault end -- Helper method to get an error message -- This method also categorizes the current page in one of the configured error categories functionExcerpt.getError(key,value) localmessage=Excerpt.getMessage('error-'..key,value) localmarkup=mw.html.create('div'):addClass('error'):wikitext(message) ifconfig.categoriesandconfig.categories.errorsandmw.title.getCurrentTitle().isContentPagethen markup:node('[[Category:'..config.categories.errors..']]') end returnmarkup end -- Helper method to get a localized message -- This method uses Module:TNT to get localized messages from https://commons.wikimedia.org/wiki/Data:I18n/Module:Excerpt.tab -- If Module:TNT is not available or the localized message does not exist, the key is returned instead functionExcerpt.getMessage(key,value) localok,TNT=pcall(require,'Module:TNT') ifnotokthenreturnkeyend localok2,message=pcall(TNT.format,'I18n/Module:Excerpt.tab',key,value) ifnotok2thenreturnkeyend returnmessage end -- Helper method to escape a string for use in regexes functionExcerpt.escapeString(str) returnstr:gsub('[%^%$%(%)%.%[%]%*%+%-%?%%]','%%%0') end -- Helper method to remove a string from a text -- @param text Text from where to remove the string -- @param str String to remove -- @return The given text with the string removed functionExcerpt.removeString(text,str) localpattern=Excerpt.escapeString(str) if#pattern>9999then-- strings longer than 10000 bytes can't be put into regexes pattern=Excerpt.escapeString(mw.ustring.sub(str,1,999))..'.-'..Excerpt.escapeString(mw.ustring.sub(str,-999)) end returntext:gsub(pattern,'') end -- Helper method to convert a comma-separated list of numbers or min-max ranges into a list of booleans -- @param filter Required. Comma-separated list of numbers or min-max ranges, for example '1,3-5' -- @return Map from integers to booleans, for example {1=true,2=false,3=true,4=true,5=true} -- @return Boolean indicating whether the filters should be treated as a blacklist or not -- @note Merging this into matchFilter is possible, but way too inefficient functionExcerpt.parseFilter(filter) localfilters={} localisBlacklist=false ifstring.sub(filter,1,1)=='-'then isBlacklist=true filter=string.sub(filter,2) end localvalues=mw.text.split(filter,',')-- split values: '1,3-5' to {'1','3-5'} for_,valueinpairs(values)do value=mw.text.trim(value) localmin,max=mw.ustring.match(value,'^(%d+)%s*[-–—]%s*(%d+)$')-- '3-5' to min=3 max=5 ifnotmaxthenmin,max=string.match(value,'^((%d+))$')end-- '1' to min=1 max=1 ifmaxthen fori=min,maxdofilters[i]=trueend else filters[value]=true-- if we reach this point, the string had the form 'a,b,c' rather than '1,2,3' end end localfilter={cache={},terms=filters} returnfilter,isBlacklist end -- Helper function to see if a value matches any of the given filters functionExcerpt.matchFilter(value,filter) ifvalue==nilthen returnfalse elseiftype(value)=="number"then returnfilter.terms[value] else localcached=filter.cache[value] ifcached~=nilthen returncached end locallang=mw.language.getContentLanguage() locallcvalue=lang:lcfirst(value) localucvalue=lang:ucfirst(value) forterminpairs(filter.terms)do ifvalue==tostring(term) ortype(term)=="string"and( lcvalue==term orucvalue==term ormw.ustring.match(value,term) )then filter.cache[value]=true returntrue end end filter.cache[value]=false end end returnExcerpt