Jump to content
Wikipedia The Free Encyclopedia

Module:Transcluder

From Wikipedia, the free encyclopedia
Module documentation[view] [edit] [history] [purge]
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.
Page template-protected This module is currently protected from editing.
See the protection policy and protection log for more details. Please discuss any changes on the talk page; you may submit an edit request to ask an administrator to make an edit if it is uncontroversial or supported by consensus. You may also request that this page be unprotected.
Warning This Lua module is used on approximately 5,100 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 is a general-purpose transclusion engine, able to transclude any part of any page and with many options that normal transclusion doesn't provide.

Usage

Modules

The main entry point for modules is the get method.

  • get( 'Title' ) — Get the requested page (exact same result as normal transclusion)
  • get( 'Title#' ) — Get the lead section of the requested page
  • get( 'Title#Section' ) — Get the requested section or <section> tag (includes any subsections)

<noinclude> and <onlyinclude> tags are handled the usual way and there's also an optional second parameter to exclude various elements from the result:

  • get( 'Title#Section', { files = 0 } ) — Exclude all files
  • get( 'Title#Section', { files = 1 } ) — Exclude all files except the first
  • get( 'Title#Section', { files = 2 } ) — Exclude all files except the second
  • get( 'Title#Section', { files = '1,2' } ) — Exclude all files except the first and second
  • get( 'Title#Section', { files = '1-3' } ) — Exclude all files except the first, second and third
  • get( 'Title#Section', { files = '1,3-5' } ) — Exclude all files except the first, third, fourth and fifth
  • get( 'Title#Section', { files = -2 } ) — Exclude the second file
  • get( 'Title#Section', { files = '-2,3' } ) — Exclude the second and third files
  • get( 'Title#Section', { files = '-1,3-5' } ) — Exclude the first, third, fourth and fifth files
  • get( 'Title#Section', { files = 'A.png' } ) — Exclude all files except A.png
  • get( 'Title#Section', { files = '-A.png' } ) — Exclude A.png
  • get( 'Title#Section', { files = 'A.png, B.jpg, C.gif' } ) — Exclude all files except A.png, B.jpg and C.gif
  • get( 'Title#Section', { files = '-A.png, B.jpg, C.gif' } ) — Exclude A.png, B.jpg and C.gif
  • get( 'Title#Section', { files = { [1] = true, [3] = true } } ) — Exclude all files except the first and third
  • get( 'Title#Section', { files = { [1] = false, [3] = false } } ) — Exclude the first and third files
  • get( 'Title#Section', { files = { ['A.png'] = false, ['B.jpg'] = false } } ) — Exclude A.png and B.jpg
  • get( 'Title#Section', { files = '.+%.png' } ) — Exclude all files except PNG files (see Lua patterns)
  • get( 'Title#Section', { files = '-.+%.png' } ) — Exclude all PNG files

The very same syntax can be used to exclude many other elements:

  • get( 'Title#Section', { sections = 0 } ) — Exclude all subsections
  • get( 'Title#Section', { sections = 'History, Causes' } ) — Exclude all subsections except 'History' and 'Causes'
  • get( 'Title#Section', { lists = 1 } ) — Exclude all lists except the first
  • get( 'Title#Section', { tables = 'stats' } ) — Exclude all tables except the one with id 'stats'
  • get( 'Title#Section', { paragraphs = '1-3' } ) — Exclude all paragraphs except the first, second and third
  • get( 'Title#Section', { references = 0 } ) — Exclude all references
  • get( 'Title#Section', { categories = '0' } ) — Exclude all categories
  • get( 'Title#Section', { templates = '-.+infobox' } ) — Exclude infobox templates
  • get( 'Title#Section', { parameters = 'image' } ) — Exclude all parameters from all templates except the one named 'image'

Options can be combined at will. For example:

  • get( 'Title#Section', { sections = 0, files = 1, paragraphs = '1-3' } ) — Exclude all subsections, all files except the first, and all paragraphs except the first three

You can also get only some elements like so:

  • get( 'Title#Section', { only = 'files' } ) — Get only the files
  • get( 'Title#Section', { only = 'lists', lists = 1 } ) — Get only the first list
  • get( 'Title#Section', { only = 'tables', tables = 'stats' } ) — Get only the table with id 'stats'
  • get( 'Title#Section', { only = 'paragraphs', paragraphs = '1,3-5' } ) — Get only the first, third, fourth and fifth paragraph
  • get( 'Title#Section', { only = 'templates', templates = 'Infobox' } ) — Get only the infobox
  • get( 'Title#Section', { only = 'parameters', parameters = 'abstract', references = 0 } ) — Get only the parameter called 'abstract' and remove all references from it

The output can be further modified with a few special options:

  • get( 'Title#Section', { noFollow = true } ) — Don't follow redirects
  • get( 'Title#Section', { linkBold = true } ) — Link the bold title or synonym near the start of the text
  • get( 'Title#Section', { noBold = true } ) — Remove bold text
  • get( 'Title#Section', { noComments = true } ) — Remove all HTML comments
  • get( 'Title#Section', { noLinks = true } ) — Remove all links
  • get( 'Title#Section', { noSelfLinks = true } ) — Remove self links
  • get( 'Title#Section', { noBehaviorSwitches = true } ) — Remove behavior switches such as __NOTOC__
  • get( 'Title#Section', { noNonFreeFiles = true } ) — Remove non-free files (identified by having the words "non-free" in their local description or in Commons)
  • get( 'Title#Section', { fixReferences = true } ) — Prefix reference names with 'Title ' to avoid name conflicts when transcluding and rescue references defined outside the requested section to avoid undefined reference errors

Besides the get method, the module exposes several other methods to get specific parts of the wikitext. This allows other modules to combine elements in more advanced ways.

Templates

The main entry point for templates is the main method. It's essentially a wrapper of the get method to make it usable for templates. See the documentation of the get method for more details and options.

  • {{#invoke:Transcluder|main|Title}} — Transclude the requested page
  • {{#invoke:Transcluder|main|Title#}} — Transclude the lead section of the requested page
  • {{#invoke:Transcluder|main|Title#Section}} — Get the requested section or <section> tag (includes any subsections)
  • {{#invoke:Transcluder|main|Title#Section|sections=0}} — Transclude the requested section, excluding subsections
  • {{#invoke:Transcluder|main|Title|only=files|files=1}} — Transclude only the first file of the page
  • {{#invoke:Transcluder|main|Title#Section|only=tables|tables=2}} — Transclude only the second table of the requested section
  • {{#invoke:Transcluder|main|Title#|only=paragraphs|linkBold=yes}} — Transclude only the paragraphs of the lead section and link the bold text

See also

The above documentation is transcluded from Module:Transcluder/doc. (edit | history)
Editors can experiment in this module's sandbox (edit | diff) and testcases (edit | run) pages.
Subpages of this module.

 -- Module:Transcluder is a general-purpose transclusion engine
 -- Documentation and master version: https://en.wikipedia.org/wiki/Module:Transcluder
 -- Authors: User:Sophivorus, User:Certes & others
 -- License: CC-BY-SA-3.0

 localp={}

 -- Helper function to test for truthy and falsy values
 -- @todo Somehow internationalize it
 localfunctiontruthy(value)
 ifnotvalueorvalue==''orvalue==0orvalue=='0'orvalue=='false'orvalue=='no'orvalue=='non'then
 returnfalse
 end
 returntrue
 end

 -- Helper function to match from a list of regular expressions
 -- Like so: match pre..list[1]..post or pre..list[2]..post or ...
 localfunctionmatchAny(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

 -- Like matchAny but for Category/File links with less overhead
 localfunctionmatchAnyLink(text,list)
 localmatch
 for_,vinipairs(list)do
 match=string.match(text,'%[%[%s*'..v..'%s*:.*%]%]')
 ifmatchthenbreakend
 end
 returnmatch
 end

 -- Helper function to escape a string for use in regexes
 localfunctionescapeString(str)
 returnstring.gsub(str,'[%^%$%(%)%.%[%]%*%+%-%?%%]','%%%0')
 end

 -- Helper function to remove a string from a text
 localfunctionremoveString(text,str)
 localpattern=escapeString(str)
 if#pattern>9999then-- strings longer than 10000 bytes can't be put into regexes
 pattern=escapeString(mw.ustring.sub(str,1,999))..'.-'..escapeString(mw.ustring.sub(str,-999))
 end
 returnstring.gsub(text,pattern,'')
 end

 -- Helper function to convert a comma-separated list of numbers or min-max ranges into a list of booleans
 -- @param flags 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 flags should be treated as a blacklist or not
 localfunctionparseFlags(value)
 localflags={}
 localblacklist=false

 ifnotvaluethenreturnnil,falseend

 iftype(value)=='number'then
 ifvalue<0then
 value=-value
 blacklist=true
 end
 flags={[value]=true}

 elseiftype(value)=='string'then
 ifstring.sub(value,1,1)=='-'then
 blacklist=true
 value=string.sub(value,2)
 end
 localranges=mw.text.split(value,',')-- split ranges: '1,3-5' to {'1','3-5'}
 for_,rangeinpairs(ranges)do
 range=mw.text.trim(range)
 localmin,max=mw.ustring.match(range,'^(%d+)%s*[-–—]%s*(%d+)$')-- '3-5' to min=3 max=5
 ifnotmaxthenmin,max=string.match(range,'^((%d+))$')end-- '1' to min=1 max=1
 ifmaxthen
 fori=min,maxdoflags[i]=trueend
 else
 flags[range]=true-- if we reach this point, the string had the form 'a,b,c' rather than '1,2,3'
 end
 end

 -- List has the form { [1] = false, [2] = true, ['c'] = false }
 -- Convert it to { [1] = true, [2] = true, ['c'] = true }
 -- But if ANY value is set to false, treat the list as a blacklist
 elseiftype(value)=='table'then
 fori,vinpairs(value)do
 ifv==falsethenblacklist=trueend
 flags[i]=true
 end
 end

 returnflags,blacklist
 end

 -- Helper function to see if a value matches any of the given flags
 localfunctionmatchFlag(value,flags)
 ifnotvaluethenreturnfalseend
 value=tostring(value)
 locallang=mw.language.getContentLanguage()
 locallcvalue=lang:lcfirst(value)
 localucvalue=lang:ucfirst(value)
 forflaginpairs(flags)do
 ifvalue==tostring(flag)
 orlcvalue==flag
 orucvalue==flag
 or(nottonumber(flag)andmw.ustring.match(value,flag))then
 returntrue
 end
 end
 end

 -- Helper function to convert template arguments into an array of options fit for get()
 localfunctionparseArgs(frame)
 localargs={}
 forkey,valueinpairs(frame:getParent().args)doargs[key]=valueend
 forkey,valueinpairs(frame.args)doargs[key]=valueend-- args from Lua calls have priority over parent args from template
 returnargs
 end

 -- Error handling function
 -- Throws a Lua error or returns an empty string if error reporting is disabled
 localfunctionthrowError(key,value)
 localTNT=require('Module:TNT')
 localok,message=pcall(TNT.format,'I18n/Module:Transcluder.tab','error-'..key,value)
 ifnotokthenmessage=keyend
 error(message,2)
 end

 -- Error handling function
 -- Returns a wiki friendly error or an empty string if error reporting is disabled
 localfunctiongetError(key,value)
 localTNT=require('Module:TNT')
 localok,message=pcall(TNT.format,'I18n/Module:Transcluder.tab','error-'..key,value)
 ifnotokthenmessage=keyend
 message=mw.html.create('div'):addClass('error'):wikitext(message)
 returnmessage
 end

 -- Helper function to get the local name of a namespace and all its aliases
 -- @param name Canonical name of the namespace, for example 'File'
 -- @return Local name of the namespace and all aliases, for example {'File','Image','Archivo','Imagen'}
 localfunctiongetNamespaces(name)
 localnamespaces=mw.clone(mw.site.namespaces[name].aliases)-- Clone because https://en.wikipedia.org/w/index.php?diff=1056921358
 table.insert(namespaces,mw.site.namespaces[name].name)
 table.insert(namespaces,mw.site.namespaces[name].canonicalName)
 returnnamespaces
 end

 -- Get the page wikitext, following redirects
 -- Also returns the page name, or the target page name if a redirect was followed, or false if no page was found
 -- For file pages, returns the content of the file description page
 localfunctiongetText(page,noFollow)
 page=mw.text.decode(page)
 localtitle=mw.title.new(page)
 ifnottitlethenreturnfalse,falseend

 localtarget=title.redirectTarget
 iftargetandnotnoFollowthentitle=targetend

 localtext=title:getContent()
 ifnottextthenreturnfalse,title.prefixedTextend

 -- Remove <noinclude> tags
 text=string.gsub(text,'<[Nn][Oo][Ii][Nn][Cc][Ll][Uu][Dd][Ee]>.-</[Nn][Oo][Ii][Nn][Cc][Ll][Uu][Dd][Ee]>','')-- remove noinclude bits

 -- Keep <onlyinclude> tags
 ifstring.find(text,'onlyinclude')then-- avoid expensive search if possible
 text=text
 :gsub('</onlyinclude>.-<onlyinclude>','')-- remove text between onlyinclude sections
 :gsub('^.-<onlyinclude>','')-- remove text before first onlyinclude section
 :gsub('</onlyinclude>.*','')-- remove text after last onlyinclude section
 end

 returntext,title.prefixedText
 end

 -- Get the requested files from the given wikitext.
 -- @param text Required. Wikitext to parse.
 -- @param flags Range of files to return, for example 2 or '1,3-5'. Omit to return all files.
 -- @return Sequence of strings containing the wikitext of the requested files.
 -- @return Original wikitext minus requested files.
 localfunctiongetFiles(text,flags)
 localfiles={}
 localflags,blacklist=parseFlags(flags)
 localfileNamespaces=getNamespaces('File')
 localname
 localcount=0
 forfileinstring.gmatch(text,'%b[]')do
 ifmatchAnyLink(file,fileNamespaces)then
 name=string.match(file,'%[%[[^:]-:([^]|]+)')
 count=count+1
 ifnotblacklistand(notflagsorflags[count]ormatchFlag(name,flags))
 orblacklistandflagsandnotflags[count]andnotmatchFlag(name,flags)then
 table.insert(files,file)
 else
 text=removeString(text,file)
 end
 end
 end

 returnfiles,text
 end

 -- Get the requested tables from the given wikitext.
 -- @param text Required. Wikitext to parse.
 -- @param flags Range of tables to return, for example 2 or '1,3-5'. Omit to return all tables.
 -- @return Sequence of strings containing the wikitext of the requested tables.
 -- @return Original wikitext minus requested tables.
 localfunctiongetTables(text,flags)
 localtables={}
 localflags,blacklist=parseFlags(flags)
 localid
 localcount=0
 fortinstring.gmatch('\n'..text,'\n%b{}')do
 ifstring.sub(t,1,3)=='\n{|'then
 id=string.match(t,'\n{|[^\n]-id%s*=%s*["\']?([^"\'\n]+)["\']?[^\n]*\n')
 count=count+1
 ifnotblacklistand(notflagsorflags[count]orflags[id])
 orblacklistandflagsandnotflags[count]andnotflags[id]then
 table.insert(tables,t)
 else
 text=removeString(text,t)
 end
 end
 end
 returntables,text
 end

 -- Get the requested templates from the given wikitext.
 -- @param text Required. Wikitext to parse.
 -- @param flags Range of templates to return, for example 2 or '1,3-5'. Omit to return all templates.
 -- @return Sequence of strings containing the wikitext of the requested templates.
 -- @return Original wikitext minus requested templates.
 localfunctiongetTemplates(text,flags)
 localtemplates={}
 localflags,blacklist=parseFlags(flags)
 localname
 localcount=0
 fortemplateinstring.gmatch(text,'{%b{}}')do
 ifstring.sub(template,1,3)~='{{#'then-- skip parser functions like #if
 name=mw.text.trim(string.match(template,'{{([^}|\n]+)')or"")-- get the template name
 ifname~=""then
 count=count+1
 ifnotblacklistand(notflagsorflags[count]ormatchFlag(name,flags))
 orblacklistandflagsandnotflags[count]andnotmatchFlag(name,flags)then
 table.insert(templates,template)
 else
 text=removeString(text,template)
 end
 end
 end
 end
 returntemplates,text
 end

 -- Get the requested template parameters from the given wikitext.
 -- @param text Required. Wikitext to parse.
 -- @param flags Range of parameters to return, for example 2 or '1,3-5'. Omit to return all parameters.
 -- @return Map from parameter name to value, NOT IN THE ORIGINAL ORDER
 -- @return Original wikitext minus requested parameters.
 -- @return Order in which the parameters were parsed.
 localfunctiongetParameters(text,flags)
 localparameters,parameterOrder={},{}
 localflags,blacklist=parseFlags(flags)
 localparams,count,parts,key,value
 fortemplateinstring.gmatch(text,'{%b{}}')do
 params=string.match(template,'{{[^|}]-|(.*)}}')
 ifparamsthen
 count=0
 -- Temporarily replace pipes in subtemplates and links to avoid chaos
 forsubtemplateinstring.gmatch(params,'{%b{}}')do
 params=string.gsub(params,escapeString(subtemplate),string.gsub(subtemplate,".",{["%"]="%%",["|"]="@@:@@",["="]="@@_@@"}))
 end
 forlinkinstring.gmatch(params,'%b[]')do
 params=string.gsub(params,escapeString(link),string.gsub(link,".",{["%"]="%%",["|"]="@@:@@",["="]="@@_@@"}))
 end
 forparameterinmw.text.gsplit(params,'|')do
 parts=mw.text.split(parameter,'=')
 key=mw.text.trim(parts[1])
 if#parts==1then
 value=key
 count=count+1
 key=count
 else
 value=mw.text.trim(table.concat(parts,'=',2))
 end
 value=string.gsub(string.gsub(value,'@@:@@','|'),'@@_@@','=')
 ifnotblacklistand(notflagsormatchFlag(key,flags))
 orblacklistandflagsandnotmatchFlag(key,flags)then
 table.insert(parameterOrder,key)
 parameters[key]=value
 else
 text=removeString(text,parameter)
 end
 end
 end
 end
 returnparameters,text,parameterOrder
 end

 -- Get the requested lists from the given wikitext.
 -- @param text Required. Wikitext to parse.
 -- @param flags Range of lists to return, for example 2 or '1,3-5'. Omit to return all lists.
 -- @return Sequence of strings containing the wikitext of the requested lists.
 -- @return Original wikitext minus requested lists.
 localfunctiongetLists(text,flags)
 locallists={}
 localflags,blacklist=parseFlags(flags)
 localcount=0
 forlistinstring.gmatch('\n'..text..'\n\n','\n([*#].-)\n[^*#]')do
 count=count+1
 ifnotblacklistand(notflagsorflags[count])
 orblacklistandflagsandnotflags[count]then
 table.insert(lists,list)
 else
 text=removeString(text,list)
 end
 end
 returnlists,text
 end

 -- Get the requested paragraphs from the given wikitext.
 -- @param text Required. Wikitext to parse.
 -- @param flags Range of paragraphs to return, for example 2 or '1,3-5'. Omit to return all paragraphs.
 -- @return Sequence of strings containing the wikitext of the requested paragraphs.
 -- @return Original wikitext minus requested paragraphs.
 localfunctiongetParagraphs(text,flags)
 localparagraphs={}
 localflags,blacklist=parseFlags(flags)

 -- Remove non-paragraphs
 localelements
 localtemp='\n'..text..'\n'
 elements,temp=getLists(temp,0)-- remove lists
 elements,temp=getFiles(temp,0)-- remove files
 temp=mw.text.trim((temp
 :gsub('\n%b{} *\n','\n%0\n')-- add spacing between tables and block templates
 :gsub('\n%b{} *\n','\n')-- remove tables and block templates
 :gsub('\n==+[^=]+==+ *\n','\n')-- remove section titles
 ))

 -- Assume that anything remaining is a paragraph
 localcount=0
 forparagraphinmw.text.gsplit(temp,'\n\n+')do
 ifmw.text.trim(paragraph)~=''then
 count=count+1
 ifnotblacklistand(notflagsorflags[count])
 orblacklistandflagsandnotflags[count]then
 table.insert(paragraphs,paragraph)
 else
 text=removeString(text,paragraph)
 end
 end
 end

 returnparagraphs,text
 end

 -- Get the requested categories from the given wikitext.
 -- @param text Required. Wikitext to parse.
 -- @param flags Range of categories to return, for example 2 or '1,3-5'. Omit to return all categories.
 -- @return Sequence of strings containing the wikitext of the requested categories.
 -- @return Original wikitext minus requested categories.
 localfunctiongetCategories(text,flags)
 localcategories={}
 localflags,blacklist=parseFlags(flags)
 localcategoryNamespaces=getNamespaces('Category')
 localname
 localcount=0
 forcategoryinstring.gmatch(text,'%b[]')do
 ifmatchAnyLink(category,categoryNamespaces)then
 name=string.match(category,'%[%[[^:]-:([^]|]+)')
 count=count+1
 ifnotblacklistand(notflagsorflags[count]ormatchFlag(name,flags))
 orblacklistandflagsandnotflags[count]andnotmatchFlag(name,flags)then
 table.insert(categories,category)
 else
 text=removeString(text,category)
 end
 end
 end
 returncategories,text
 end

 -- Get the requested references from the given wikitext.
 -- @param text Required. Wikitext to parse.
 -- @param flags Range of references to return, for example 2 or '1,3-5'. Omit to return all references.
 -- @return Sequence of strings containing the wikitext of the requested references.
 -- @return Original wikitext minus requested references.
 localfunctiongetReferences(text,flags)
 localreferences={}

 -- Remove all references, including citations, when 0 references are requested
 -- This is kind of hacky but currently necessary because the rest of the code
 -- doesn't remove citations like <ref name="Foo" /> if Foo is defined elsewhere
 ifflagsandnottruthy(flags)then
 text=string.gsub(text,'<%s*[Rr][Ee][Ff][^>/]*>.-<%s*/%s*[Rr][Ee][Ff]%s*>','')
 text=string.gsub(text,'<%s*[Rr][Ee][Ff][^>/]*/%s*>','')
 returnreferences,text
 end

 localflags,blacklist=parseFlags(flags)
 localname
 localcount=0
 forreferenceinstring.gmatch(text,'<%s*[Rr][Ee][Ff][^>/]*>.-<%s*/%s*[Rr][Ee][Ff]%s*>')do
 name=string.match(reference,'<%s*[Rr][Ee][Ff][^>]*name%s*=%s*["\']?([^"\'>/]+)["\']?[^>]*%s*>')
 count=count+1
 ifnotblacklistand(notflagsorflags[count]ormatchFlag(name,flags))
 orblacklistandflagsandnotflags[count]andnotmatchFlag(name,flags)then
 table.insert(references,reference)
 else
 text=removeString(text,reference)
 ifnamethen
 forcitationinstring.gmatch(text,'<%s*[Rr][Ee][Ff][^>]*name%s*=%s*["\']?'..escapeString(name)..'["\']?[^/>]*/%s*>')do
 text=removeString(text,citation)
 end
 end
 end
 end
 returnreferences,text
 end

 -- Get the lead section from the given wikitext.
 -- @param text Required. Wikitext to parse.
 -- @return Wikitext of the lead section.
 localfunctiongetLead(text)
 text=string.gsub('\n'..text,'\n==.*','')
 text=mw.text.trim(text)
 ifnottextthenreturnthrowError('lead-empty')end
 returntext
 end

 -- Get the requested sections from the given wikitext.
 -- @param text Required. Wikitext to parse.
 -- @param flags Range of sections to return, for example 2 or '1,3-5'. Omit to return all sections.
 -- @return Sequence of strings containing the wikitext of the requested sections.
 -- @return Original wikitext minus requested sections.
 localfunctiongetSections(text,flags)
 localsections={}
 localflags,blacklist=parseFlags(flags)
 localcount=0
 localprefix,section,suffix
 fortitleinstring.gmatch('\n'..text..'\n==','\n==+%s*([^=]+)%s*==+')do
 count=count+1
 prefix,section,suffix=string.match('\n'..text..'\n==','\n()==+%s*'..escapeString(title)..'%s*==+(.-)()\n==')
 ifnotblacklistand(notflagsorflags[count]ormatchFlag(title,flags))
 orblacklistandflagsandnotflags[count]andnotmatchFlag(title,flags)then
 sections[title]=section
 else
 text=string.sub(text,1,prefix)..string.sub(text,suffix)
 text=string.gsub(text,'\n?==$','')-- remove the trailing \n==
 end
 end
 returnsections,text
 end

 -- Get the requested section or <section> tag from the given wikitext (including subsections).
 -- @param text Required. Wikitext to parse.
 -- @param section Required. Title of the section to get (in wikitext), for example 'History' or 'History of [[Athens]]'.
 -- @return Wikitext of the requested section.
 localfunctiongetSection(text,section)
 section=mw.text.trim(section)
 localescapedSection=escapeString(section)
 -- First check if the section title matches a <section> tag
 ifstring.find(text,'<%s*[Ss]ection%s+begin%s*=%s*["\']?%s*'..escapedSection..'%s*["\']?%s*/>')then-- avoid expensive search if possible
 text=mw.text.trim((text
 :gsub('<%s*[Ss]ection%s+end=%s*["\']?%s*'..escapedSection..'%s*["\']?%s*/>.-<%s*[Ss]ection%s+begin%s*=%s*["\']?%s*'..escapedSection..'%s*["\']?%s*/>','')-- remove text between section tags
 :gsub('^.-<%s*[Ss]ection%s+begin%s*=%s*["\']?%s*'..escapedSection..'%s*["\']?%s*/>','')-- remove text before first section tag
 :gsub('<%s*[Ss]ection%s+end=%s*["\']?%s*'..escapedSection..'%s*["\']?%s*/>.*','')-- remove text after last section tag
 ))
 iftext==''thenreturnthrowError('section-tag-empty',section)end
 returntext
 end
 locallevel,text=string.match('\n'..text..'\n','\n(==+)%s*'..escapedSection..'%s*==.-\n(.*)')
 ifnottextthenreturnthrowError('section-not-found',section)end
 localnextSection='\n=='..string.rep('=?',#level-2)..'[^=].*'
 text=string.gsub(text,nextSection,'')-- remove later sections with headings at this level or higher
 text=mw.text.trim(text)
 iftext==''thenreturnthrowError('section-empty',section)end
 returntext
 end

 -- Replace the first call to each reference defined outside of the text 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">
 localfunctionfixReferences(text,page,full)
 ifnotfullthenfull=getText(page)end
 localrefNames={}
 localrefName
 localrefBody
 localposition=1
 whileposition<mw.ustring.len(text)do
 refName,position=mw.ustring.match(text,'<%s*[Rr][Ee][Ff][^>]*name%s*=%s*["\']?([^"\'>]+)["\']?[^>]*/%s*>()',position)
 ifrefNamethen
 refName=mw.text.trim(refName)
 ifnotrefNames[refName]then-- make sure we process each ref name only once
 table.insert(refNames,refName)
 refName=escapeString(refName)
 refBody=mw.ustring.match(text,'<%s*[Rr][Ee][Ff][^>]*name%s*=%s*["\']?%s*'..refName..'%s*["\']?[^>/]*>.-<%s*/%s*[Rr][Ee][Ff]%s*>')
 ifnotrefBodythen-- the ref body is not in the excerpt
 refBody=mw.ustring.match(full,'<%s*[Rr][Ee][Ff][^>]*name%s*=%s*["\']?%s*'..refName..'%s*["\']?[^/>]*>.-<%s*/%s*[Rr][Ee][Ff]%s*>')
 ifrefBodythen-- the ref body was found elsewhere
 text=mw.ustring.gsub(text,'<%s*[Rr][Ee][Ff][^>]*name%s*=%s*["\']?%s*'..refName..'%s*["\']?[^>]*/?%s*>',mw.ustring.gsub(refBody,'%%','%%%%'),1)
 end
 end
 end
 else
 position=mw.ustring.len(text)
 end
 end
 page=string.gsub(page,'"','')-- remove any quotation marks from the page title
 text=mw.ustring.gsub(text,'<%s*[Rr][Ee][Ff][^>]*name%s*=%s*["\']?([^"\'>/]+)["\']?[^>/]*(/?)%s*>','<ref name="'..page..' %1"%2>')
 text=mw.ustring.gsub(text,'<%s*[Rr][Ee][Ff]%s*group%s*=%s*["\']?[^"\'>/]+["\']%s*>','<ref>')
 returntext
 end

 -- Replace the bold title or synonym near the start of the page by a link to the page
 localfunctionlinkBold(text,page)
 locallang=mw.language.getContentLanguage()
 localposition=mw.ustring.find(text,"'''"..lang:ucfirst(page).."'''",1,true)-- look for "'''Foo''' is..." (uc) or "A '''foo''' is..." (lc)
 ormw.ustring.find(text,"'''"..lang:lcfirst(page).."'''",1,true)-- plain search: special characters in page represent themselves
 ifpositionthen
 locallength=mw.ustring.len(page)
 text=mw.ustring.sub(text,1,position+2).."[["..mw.ustring.sub(text,position+3,position+length+2).."]]"..mw.ustring.sub(text,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)
 text=mw.ustring.gsub(text,"()'''(.-'*)'''",function(a,b)
 ifnotmw.ustring.find(b,"%[")andnotmw.ustring.find(b,"%{")then-- if not wikilinked or some weird template
 return"'''[["..page.."|"..b.."]]'''"-- replace '''Foo''' by '''[[page|Foo]]'''
 else
 returnnil-- instruct gsub to make no change
 end
 end,1)-- "end" here terminates the anonymous replacement function(a, b) passed to gsub
 end
 returntext
 end

 -- Remove non-free files.
 -- @param text Required. Wikitext to clean.
 -- @return Clean wikitext.
 localfunctionremoveNonFreeFiles(text)
 localfileNamespaces=getNamespaces('File')
 localfileName
 localfileDescription
 localframe=mw.getCurrentFrame()
 forfileinstring.gmatch(text,'%b[]')do
 ifmatchAnyLink(file,fileNamespaces)then
 fileName='File:'..string.match(file,'%[%[[^:]-:([^]|]+)')
 fileDescription,fileName=getText(fileName)
 iffileNamethen
 ifnotfileDescriptionorfileDescription==''then
 fileDescription=frame:preprocess('{{'..fileName..'}}')-- try Commons
 end
 iffileDescriptionandstring.match(fileDescription,'[Nn]on%-free')then
 text=removeString(text,file)
 end
 end
 end
 end
 returntext
 end

 -- Remove any self links
 localfunctionremoveSelfLinks(text)
 locallang=mw.language.getContentLanguage()
 localpage=escapeString(mw.title.getCurrentTitle().prefixedText)
 localucpage=lang:ucfirst(page)
 locallcpage=lang:lcfirst(page)
 text=text
 :gsub('%[%[('..ucpage..')%]%]','%1')
 :gsub('%[%[('..lcpage..')%]%]','%1')
 :gsub('%[%['..ucpage..'|([^]]+)%]%]','%1')
 :gsub('%[%['..lcpage..'|([^]]+)%]%]','%1')
 returntext
 end

 -- Remove all wikilinks
 localfunctionremoveLinks(text)
 text=text
 :gsub('%[%[[^%]|]+|([^]]+)%]%]','%1')
 :gsub('%[%[([^]]+)%]%]','%1')
 :gsub('%[[^ ]+ ([^]]+)%]','%1')
 :gsub('%[([^]]+)%]','%1')
 returntext
 end

 -- Remove HTML comments
 localfunctionremoveComments(text)
 text=string.gsub(text,'<!%-%-.-%-%->','')
 returntext
 end

 -- Remove behavior switches, such as __NOTOC__
 localfunctionremoveBehaviorSwitches(text)
 text=string.gsub(text,'__[A-Z]+__','')
 returntext
 end

 -- Remove bold text
 localfunctionremoveBold(text)
 text=string.gsub(text,"'''",'')
 returntext
 end

 -- Main function for modules
 localfunctionget(page,options)
 ifnotoptionsthenoptions={}end

 -- Make sure the page exists
 ifnotpagethenreturnthrowError('no-page')end
 page=mw.text.trim(page)
 page=mw.text.decode(page)
 ifpage==''thenreturnthrowError('no-page')end
 localpage,hash,section=string.match(page,'([^#]+)(#?)(.*)')
 localtext,temp=getText(page,options.noFollow)
 ifnottempthenreturnthrowError('invalid-title',page)end
 page=temp
 ifnottextthenreturnthrowError('page-not-found',page)end
 localfull=text-- save the full text for fixReferences below

 -- Get the requested section
 iftruthy(section)then
 text=getSection(text,section)
 elseiftruthy(hash)then
 text=getLead(text)
 end

 -- Keep only the requested elements
 localelements
 ifoptions.onlythen
 ifoptions.only=='sections'thenelements=getSections(text,options.sections)end
 ifoptions.only=='lists'thenelements=getLists(text,options.lists)end
 ifoptions.only=='files'thenelements=getFiles(text,options.files)end
 ifoptions.only=='tables'thenelements=getTables(text,options.tables)end
 ifoptions.only=='templates'thenelements=getTemplates(text,options.templates)end
 ifoptions.only=='parameters'thenelements=getParameters(text,options.parameters)end
 ifoptions.only=='paragraphs'thenelements=getParagraphs(text,options.paragraphs)end
 ifoptions.only=='categories'thenelements=getCategories(text,options.categories)end
 ifoptions.only=='references'thenelements=getReferences(text,options.references)end
 text=''
 ifelementsthen
 forkey,elementinpairs(elements)do
 text=text..'\n'..element..'\n'
 end
 end
 end

 -- Filter the requested elements
 ifoptions.sectionsandoptions.only~='sections'thenelements,text=getSections(text,options.sections)end
 ifoptions.listsandoptions.only~='lists'thenelements,text=getLists(text,options.lists)end
 ifoptions.filesandoptions.only~='files'thenelements,text=getFiles(text,options.files)end
 ifoptions.tablesandoptions.only~='tables'thenelements,text=getTables(text,options.tables)end
 ifoptions.templatesandoptions.only~='templates'thenelements,text=getTemplates(text,options.templates)end
 ifoptions.parametersandoptions.only~='parameters'thenelements,text=getParameters(text,options.parameters)end
 ifoptions.paragraphsandoptions.only~='paragraphs'thenelements,text=getParagraphs(text,options.paragraphs)end
 ifoptions.categoriesandoptions.only~='categories'thenelements,text=getCategories(text,options.categories)end
 ifoptions.referencesandoptions.only~='references'thenelements,text=getReferences(text,options.references)end

 -- Misc options
 iftruthy(options.fixReferences)thentext=fixReferences(text,page,full)end
 iftruthy(options.linkBold)andnottruthy(section)thentext=linkBold(text,page)end
 iftruthy(options.noBold)thentext=removeBold(text)end
 iftruthy(options.noLinks)thentext=removeLinks(text)end
 iftruthy(options.noSelfLinks)thentext=removeSelfLinks(text)end
 iftruthy(options.noNonFreeFiles)thentext=removeNonFreeFiles(text)end
 iftruthy(options.noBehaviorSwitches)thentext=removeBehaviorSwitches(text)end
 iftruthy(options.noComments)thentext=removeComments(text)end

 -- Remove multiple newlines left over from removing elements
 text=string.gsub(text,'\n\n\n+','\n\n')
 text=mw.text.trim(text)

 returntext
 end

 -- Main invocation function for templates
 localfunctionmain(frame)
 localargs=parseArgs(frame)
 localpage=args[1]
 localok,text=pcall(get,page,args)
 ifnotokthenreturngetError(text)end
 localraw=args['raw']
 ifrawthenreturntextend
 returnframe:preprocess(text)
 end

 -- Entry points for templates
 functionp.main(frame)returnmain(frame)end

 -- Entry points for modules
 functionp.get(page,options)returnget(page,options)end
 functionp.getText(page,noFollow)returngetText(page,noFollow)end
 functionp.getLead(text)returngetLead(text)end
 functionp.getSection(text,section)returngetSection(text,section)end
 functionp.getSections(text,flags)returngetSections(text,flags)end
 functionp.getParagraphs(text,flags)returngetParagraphs(text,flags)end
 functionp.getParameters(text,flags)returngetParameters(text,flags)end
 functionp.getCategories(text,flags)returngetCategories(text,flags)end
 functionp.getReferences(text,flags)returngetReferences(text,flags)end
 functionp.getTemplates(text,flags)returngetTemplates(text,flags)end
 functionp.getTables(text,flags)returngetTables(text,flags)end
 functionp.getLists(text,flags)returngetLists(text,flags)end
 functionp.getFiles(text,flags)returngetFiles(text,flags)end
 functionp.getError(message,value)returngetError(message,value)end

 -- Expose handy methods
 functionp.truthy(value)returntruthy(value)end
 functionp.parseArgs(frame)returnparseArgs(frame)end
 functionp.matchAny(text,pre,list,post,init)returnmatchAny(text,pre,list,post,init)end
 functionp.matchFlag(value,flags)returnmatchFlag(value,flags)end
 functionp.getNamespaces(name)returngetNamespaces(name)end
 functionp.removeBold(text)returnremoveBold(text)end
 functionp.removeLinks(text)returnremoveLinks(text)end
 functionp.removeSelfLinks(text)returnremoveSelfLinks(text)end
 functionp.removeNonFreeFiles(text)returnremoveNonFreeFiles(text)end
 functionp.removeBehaviorSwitches(text)returnremoveBehaviorSwitches(text)end
 functionp.removeComments(text)returnremoveComments(text)end

 returnp

AltStyle によって変換されたページ (->オリジナル) /