Diferencia entre revisiones de «Módulo:Excerpt»

De Hispanopedia
imported>Leoncastro
m ops
 
imported>Sophivorus
Update from master using Synchronizer #synchronizer
 
(No se muestran 2 ediciones intermedias del mismo usuario)
Línea 1: Línea 1:
-- Copied from https://en.wikipedia.org/wiki/Module:Excerpt.
-- Module:Excerpt implements the Excerpt template
-- This module is rated as alpha.
-- 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
 
local Transcluder = require( 'Module:Transcluder' )
 
local yesno = require( 'Module:Yesno' )
 
local ok, config = pcall( require, 'Module:Excerpt/config' )
if not ok then config = {} end


local p = {}
local p = {}
local mRedirect = require('Module:Redirección')


-- Entry point for Lua callers
-- Helper function to get arguments
-- Returns a string value: text of the lead of a page
local args
function p._lead(pagenames, options)
local function getArg( key, default )
if not pagenames or #pagenames < 1 then return "" end -- Return blank text rather than an error splurge
local value = args[ key ]
local pagename = pagenames[1]
if value and mw.text.trim( value ) ~= '' then
if #pagenames > 1 then -- we could do this even with one page, but it would be inefficient
return value
math.randomseed(os.time())
end
pagename = pagenames[math.random(#pagenames)] --pick a random title
return default
end
 
-- Helper function to handle errors
local function getError( message, value )
if type( message ) == 'string' then
message = Transcluder.getError( message, value )
end
end
pagename = mw.ustring.match(pagename, "%[%[%s*(.-)[]|#]") or pagename -- "[[Foo|Bar]]" → "Foo"
if config.categories and config.categories.errors and mw.title.getCurrentTitle().isContentPage then
pagename = mw.ustring.match(pagename, "%S.*%S") -- strip leading and trailing white space
message:node( '[[Category:' .. config.categories.errors .. ']]' )
end
return message
end
 
-- Helper function to get localized messages
local function getMessage( key )
local ok, TNT = pcall( require, 'Module:TNT' )
if not ok then return key end
return TNT.format( 'I18n/Module:Excerpt.tab', key )
end
 
-- Main entry point for templates
function p.main( frame )
args = Transcluder.parseArgs( frame )


local title = mw.title.new(pagename) -- Find the lead section of the named page
-- Make sure the requested page exists
if not title then return "" end
local page = getArg( 1 )
local redir = mRedirect.getTarget(title)
if not page or page == '{{{1}}}' then return getError( 'no-page' ) end
if redir then title = mw.title.new(redir) end
local title = mw.title.new(page)
if not title then return getError( 'invalid-title', page ) end
if title.isRedirect then title = title.redirectTarget end
if not title.exists then return getError( 'page-not-found', page ) end
page = title.prefixedText


local text = title:getContent() or ""
-- Set variables from the template parameters
text = mw.ustring.gsub(text, "%c%s*==.*","") -- remove first heading and everything after it
local section = getArg( 2, mw.ustring.match( getArg( 1 ), '[^#]+#(.+)' ) )
text = mw.ustring.gsub(text, "<noinclude>.-</noinclude>", "") -- remove noinclude bits
local hat = yesno( getArg( 'hat', true ) )
if not options.refs or options.refs == "false" then
local edit = yesno( getArg( 'edit', true ) )
text = mw.ustring.gsub(text, "<[Rr][Ee][Ff][^>]-/>", "") -- remove refs cited elsewhere
local this = getArg( 'this' )
text = mw.ustring.gsub(text, "<[Rr][Ee][Ff].->.-</[Rr][Ee][Ff]%s*>", "") -- remove refs
local only = getArg( 'only' )
for _, t in pairs {"[Hh]arvnp", "[Rr]efn", "[Ss]fnm?", "#[Tt][Aa][Gg]:%s*[Rr][Ee][Ff]"} do
local files = getArg( 'files', getArg( 'file', ( only == 'file' and 1 ) ) )
text = mw.ustring.gsub(text, "{{%s*" .. t .. "%s*|.-}}", "") -- remove ref and footnote templates
local lists = getArg( 'lists', getArg( 'list', ( only == 'list' and 1 ) ) )
local tables = getArg( 'tables', getArg( 'table', ( only == 'table' and 1 ) ) )
local templates = getArg( 'templates', getArg( 'template', ( only == 'template' and 1 ) ) )
local paragraphs = getArg( 'paragraphs', getArg( 'paragraph', ( only == 'paragraph' and 1 ) ) )
local references = getArg( 'references' )
local subsections = not yesno( getArg( 'subsections' ) )
local noLinks = not yesno( getArg( 'links', true ) )
local noBold = not yesno( getArg( 'bold' ) )
local onlyFreeFiles = yesno( getArg( 'onlyfreefiles', true ) )
local briefDates = yesno( getArg( 'briefdates', false ) )
local inline = yesno( getArg( 'inline' ) )
local quote = yesno( getArg( 'quote' ) )
local more = yesno( getArg( 'more' ) )
local class = getArg( 'class' )
local displaytitle = getArg( 'displaytitle' ) or page
 
-- Build the hatnote
if hat and not inline then
if this then
hat = this
elseif quote then
hat = getMessage( 'this' )
elseif only then
hat = getMessage( only )
else
hat = getMessage( 'section' )
end
hat = hat .. ' ' .. getMessage( 'excerpt' ) .. ' '
if section then
hat = hat .. '[[:' .. page .. '#' .. mw.uri.anchorEncode( section ) .. '|' .. displaytitle
.. ' § ' .. mw.ustring.gsub( section, '%[%[([^]|]+)|?[^]]*%]%]', '%1' ) .. ']].' -- remove nested links
else
hat = hat .. '[[:' .. page .. '|' .. displaytitle .. ']].'
end
if edit then
hat = hat .. '<span class="mw-editsection-like plainlinks"><span class="mw-editsection-bracket">[</span>['
hat = hat .. title:fullUrl( 'action=edit' ) .. ' ' .. mw.message.new( 'editsection' ):plain()
hat = hat .. ']<span class="mw-editsection-bracket">]</span></span>'
end
end
if config.hat then
hat = config.hat .. hat .. '}}'
hat = frame:preprocess( hat )
else
hat = mw.html.create( 'div' ):addClass( 'dablink excerpt-hat' ):wikitext( hat )
end
else
hat = nil
end
-- Build the "Read more" link
if more and not inline then
more = "'''[[" .. page .. '#' .. ( section or '' ) .. "|" .. getMessage( 'more' ) .. "]]'''"
more = mw.html.create( 'div' ):addClass( 'noprint excerpt-more' ):wikitext( more )
else
more = nil
end
end
text = mw.ustring.gsub(text, "%s*{{%s*([Cc]ontenido|[Tt](?:ocright|OC(?:001| ?derecha| ?limit))).-}}", "") -- remove most common tables of contents


local allparas = true -- keep all paragraphs?
-- Build the options for Module:Transcluder out of the template parameters and the desired defaults
if options.paraflags then
local options = {
for _, v in pairs(options.paraflags) do
files = files,
if v then allparas = false end -- if any para specifically requested, don't keep all
lists = lists,
tables = tables,
paragraphs = paragraphs,
sections = subsections,
categories = 0,
references = references,
only = only and mw.text.trim( only, 's' ) .. 's',
noLinks = noLinks,
noBold = noBold,
noSelfLinks = true,
noNonFreeFiles = onlyFreeFiles,
noBehaviorSwitches = true,
fixReferences = true,
linkBold = true,
}
 
-- Get the excerpt itself
local title = page .. '#' .. ( section or '' )
local ok, excerpt = pcall( Transcluder.get, title, options )
if not ok then return getError( excerpt ) end
if mw.text.trim( excerpt ) == '' and not only then
if section then return getError( 'section-empty', section ) else return getError( 'lead-empty' ) end
end
 
-- Fix birth and death dates, but only in the first paragraph
if briefDates then
local startpos = 1 -- skip initial templates
local s
local e = 0
repeat
startpos = e + 1
s, e = mw.ustring.find( excerpt, "%s*%b{}%s*", startpos )
until not s or s > startpos
s, e = mw.ustring.find( excerpt, "%b()", startpos ) -- get (...), which may be (year–year)
if s and s < startpos + 100 then -- look only near the start
local year1, conjunction, year2 = mw.ustring.match( mw.ustring.sub( excerpt, s, e ), '(%d%d%d+)(.-)(%d%d%d+)' )
if year1 and year2 and (mw.ustring.match( conjunction, '[%-–—]' ) or mw.ustring.match( conjunction, '{{%s*[sS]nd%s*}}' )) then
local y1 = tonumber(year1)
local y2 = tonumber(year2)
if y2 > y1 and y2 < y1 + 125 and y1 <= tonumber( os.date( "%Y" )) then
excerpt = mw.ustring.sub( excerpt, 1, s ) .. year1 .. "–" .. year2 .. mw.ustring.sub( excerpt, e )
end
end
end
end
end
end


-- a basic parser to trim down the lead
-- If no file was found, try to get one from the infobox
local inlead = false -- have we found some text yet?
local fileNamespaces = Transcluder.getNamespaces( 'File' )
local t = "" -- the stripped down output text
if ( ( only == 'file' or only == 'files' ) or ( not only and ( files ~= '0' or not files ) ) ) and -- caller asked for files
local files = 0 -- how many [[Image: or [[File: so far
not Transcluder.matchAny( excerpt, '%[%[', fileNamespaces, ':' ) and -- and there are no files in Transcluder's output
local paras = 0 -- how many paragraphs so far
config.captions -- and we have the config option required to try finding files in templates
 
then
text = mw.ustring.gsub(text,"^%s*","") -- remove initial white space
-- We cannot distinguish the infobox from the other templates so we search them all
repeat -- loop around parsing a comment, template, image or paragraph
local infobox = Transcluder.getTemplates( excerpt );
local token = mw.ustring.match(text, "^%s*<!%-%-.-%-%->%s*") -- <!--HTML comment-->
infobox = table.concat( infobox )
or mw.ustring.match(text, "^%b{}%s*") or false -- or {{Template}}
local parameters = Transcluder.getParameters( infobox )
if token then
local file, captions, caption
if inlead then t = t .. token end -- keep comments and templates only within text body
for _, pair in pairs( config.captions ) do
else
file = pair[1]
token = mw.ustring.match(text, "^%[%[%s*([Aa]rchivo|[Ff]ile|[Ii]mage)%s*:") -- [[File: ...
file = parameters[file]
if token then
if file and Transcluder.matchAny( file, '^.*%.', { '[Jj][Pp][Ee]?[Gg]', '[Pp][Nn][Gg]', '[Gg][Ii][Ff]', '[Ss][Vv][Gg]' }, '.*' ) then
token = mw.ustring.match(text, "^%b[]%s*") -- match [[...]] to handle nesting
file = mw.ustring.match( file, '%[?%[?.-:([^{|]+)%]?%]?' ) or file -- [[File:Example.jpg{{!}}upright=1.5]] to Example.jpg
files = files + 1
captions = pair[2]
if options.fileflags and options.fileflags[files] then t = t .. token end
for _, p in pairs( captions ) do
else -- got a paragraph, which ends at a file, image, blank line or end of text
if parameters[ p ] then caption = parameters[ p ] break end
local afterend = mw.ustring.len(text) + 1
end
local blankpos = mw.ustring.find(text, "\n%s*\n") or afterend
excerpt = '[[File:' .. file .. '|thumb|' .. ( caption or '' ) .. ']]' .. excerpt
local endpos = math.min(
if ( onlyFreeFiles ) then
mw.ustring.find(text, "%[%[%s*([Aa]rchivo|[Ff]ile|[Ii]mage)%s*:") or afterend,
excerpt = Transcluder.removeNonFreeFiles( excerpt )
mw.ustring.find(text, "%[%[%s*([Aa]rchivo|[Ff]ile|[Ii]mage)%s*:") or afterend,
blankpos)
token = mw.ustring.sub(text, 1, endpos-1)
if blankpos < afterend and blankpos == endpos then -- paragraph ends with a blank line
token = token .. mw.ustring.match(text, "\n%s*\n", blankpos)
end
end
inlead = true
break
paras = paras + 1
if allparas or (options.paraflags and options.paraflags[paras]) then t = t .. token end
end
end
end
end
end


if token then text = mw.ustring.sub(text, mw.ustring.len(token)+1) end
-- Unlike other elements, templates are filtered here
until not text or text == "" or not token or token == ""
-- because we had to search the infoboxes for files
local trash
if only and ( only == 'template' or only == 'templates' ) then
trash, excerpt = Transcluder.getTemplates( excerpt, templates );
else -- Remove blacklisted templates
local blacklist = config.blacklist and table.concat( config.blacklist, ',' ) or ''
if templates then
if string.sub( templates, 1, 1 ) == '-' then --Unwanted templates. Append to blacklist
blacklist = templates .. ',' .. blacklist
else --Wanted templates. Replaces blacklist and acts as whitelist
blacklist = templates
end
else
blacklist = '-' .. blacklist
end
trash, excerpt = Transcluder.getTemplates( excerpt, blacklist );
end


text = mw.ustring.gsub(t, "\n+$", "") -- remove  trailing line feeds, so "{{Transclude text excerpt|Foo}} more" flows on one line
-- Remove extra line breaks but leave one before and after so the parser interprets lists, tables, etc. correctly
excerpt = mw.text.trim( excerpt )
excerpt = string.gsub( excerpt, '\n\n\n+', '\n\n' )
excerpt = '\n' .. excerpt .. '\n'


if options.more then text = text .. " '''[[" .. pagename .. "|" .. options.more .. "]]'''" end
-- Remove nested categories
return text
excerpt = frame:preprocess( excerpt )
end
local categories, excerpt = Transcluder.getCategories( excerpt, options.categories )


-- Convert a comma-separated list of numbers or min-max ranges into a list of booleans, e.g. "1,3-5" → {1=true,2=false,3=true,4=true,5=true}
-- Add tracking categories
function p.numberflags(str)
if config.categories then
local ranges = mw.text.split(str, ",") -- parse ranges, e.g. "1,3-5" → {"1","3-5"}
local contentCategory = config.categories.content
local flags = {}
if contentCategory and mw.title.getCurrentTitle().isContentPage then
for _, r in pairs(ranges) do
excerpt = excerpt .. '[[Category:' .. contentCategory .. ']]'
local min, max = mw.ustring.match(r, "^%s*(%d+)%s*%-%s*(%d+)%s*$") -- "3-5" → min=3 max=5
end
if not max then min, max = mw.ustring.match(r, "^%s*((%d+))%s*$") end -- "1" → min=1 max=1
local namespaceCategory = config.categories[ mw.title.getCurrentTitle().namespace ]
if max then
if namespaceCategory then
for p = min, max do flags[p] = true end
excerpt = excerpt .. '[[Category:' .. namespaceCategory .. ']]'
end
end
end
end
return flags
end


-- Entry point for template callers using #invoke:
-- Load the styles
function p.lead(frame)
local styles
-- args = { 1 = page name, paragraphs = list e.g. "1,3-5", files = list, more = text}
if config.styles then
local args = frame.args -- from calling module
styles = frame:extensionTag( 'templatestyles', '', { src = config.styles } )
local pargs = frame:getParent().args -- from template
end


-- Accept any number of page names.  If more than one, we'll pick one randomly
-- Combine and return the elements
local pagenames = {}
if inline then
for i, p in pairs(args) do
return mw.text.trim( excerpt )
if p and type(i) == 'number' then table.insert(pagenames, p) end
end
end
for i, p in pairs(pargs) do
local tag = 'div'
if p and type(i) == 'number' and not args[i] then table.insert(pagenames, p) end
if quote then
tag = 'blockquote'
end
end
 
excerpt = mw.html.create( 'div' ):addClass( 'excerpt' ):wikitext( excerpt )
local options = {}
local block = mw.html.create( tag ):addClass( 'excerpt-block' ):addClass( class )
options.paraflags = p.numberflags(args["paragraphs"] or pargs["paragraphs"] or "") -- parse paragraphs, e.g. "1,3-5" → {"1","3-5"}
return block:node( styles ):node( hat ):node( excerpt ):node( more )
options.fileflags = p.numberflags(args["files"] or pargs["files"] or "") -- parse file numbers
options.refs = args["refs"] or pargs["refs"]
options.more = args["more"] or pargs["more"]
if options.more and options.more == "" then options.more = "Read more..." end -- more= is short for this default text
 
local text = p._lead(pagenames, options)
return frame:preprocess(text)
end
end


-- Function lead is just function random picking from a list of one article,
-- Entry points for backwards compatibility
-- but we advertise different entry points in case they should differ in future
function p.lead( frame ) return p.main( frame ) end
function p.random(frame)
function p.excerpt( frame ) return p.main( frame ) end
return p.lead(frame)
end


return p
return p

Revisión actual - 17:47 10 jul 2023

La documentación para este módulo puede ser creada en Módulo:Excerpt/doc

-- 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

local Transcluder = require( 'Module:Transcluder' )

local yesno = require( 'Module:Yesno' )

local ok, config = pcall( require, 'Module:Excerpt/config' )
if not ok then config = {} end

local p = {}

-- Helper function to get arguments
local args
local function getArg( key, default )
	local value = args[ key ]
	if value and mw.text.trim( value ) ~= '' then
		return value
	end
	return default
end

-- Helper function to handle errors
local function getError( message, value )
	if type( message ) == 'string' then
		message = Transcluder.getError( message, value )
	end
	if config.categories and config.categories.errors and mw.title.getCurrentTitle().isContentPage then
		message:node( '[[Category:' .. config.categories.errors .. ']]' )
	end
	return message
end

-- Helper function to get localized messages
local function getMessage( key )
	local ok, TNT = pcall( require, 'Module:TNT' )
	if not ok then return key end
	return TNT.format( 'I18n/Module:Excerpt.tab', key )
end

-- Main entry point for templates
function p.main( frame )
	args = Transcluder.parseArgs( frame )

	-- Make sure the requested page exists
	local page = getArg( 1 )
	if not page or page == '{{{1}}}' then return getError( 'no-page' ) end
	local title = mw.title.new(page)
	if not title then return getError( 'invalid-title', page ) end
	if title.isRedirect then title = title.redirectTarget end
	if not title.exists then return getError( 'page-not-found', page ) end
	page = title.prefixedText

	-- Set variables from the template parameters
	local section = getArg( 2, mw.ustring.match( getArg( 1 ), '[^#]+#(.+)' ) )
	local hat = yesno( getArg( 'hat', true ) )
	local edit = yesno( getArg( 'edit', true ) )
	local this = getArg( 'this' )
	local only = getArg( 'only' )
	local files = getArg( 'files', getArg( 'file', ( only == 'file' and 1 ) ) )
	local lists = getArg( 'lists', getArg( 'list', ( only == 'list' and 1 ) ) )
	local tables = getArg( 'tables', getArg( 'table', ( only == 'table' and 1 ) ) )
	local templates = getArg( 'templates', getArg( 'template', ( only == 'template' and 1 ) ) )
	local paragraphs = getArg( 'paragraphs', getArg( 'paragraph', ( only == 'paragraph' and 1 ) ) )
	local references = getArg( 'references' )
	local subsections = not yesno( getArg( 'subsections' ) )
	local noLinks = not yesno( getArg( 'links', true ) )
	local noBold = not yesno( getArg( 'bold' ) )
	local onlyFreeFiles = yesno( getArg( 'onlyfreefiles', true ) )
	local briefDates = yesno( getArg( 'briefdates', false ) )
	local inline = yesno( getArg( 'inline' ) )
	local quote = yesno( getArg( 'quote' ) )
	local more = yesno( getArg( 'more' ) )
	local class = getArg( 'class' )
	local displaytitle = getArg( 'displaytitle' ) or page

	-- Build the hatnote
	if hat and not inline then
		if this then
			hat = this
		elseif quote then
			hat = getMessage( 'this' )
		elseif only then
			hat = getMessage( only )
		else
			hat = getMessage( 'section' )
		end
		hat = hat .. ' ' .. getMessage( 'excerpt' ) .. ' '
		if section then
			hat = hat .. '[[:' .. page .. '#' .. mw.uri.anchorEncode( section ) .. '|' .. displaytitle
				.. ' § ' .. mw.ustring.gsub( section, '%[%[([^]|]+)|?[^]]*%]%]', '%1' ) .. ']].' -- remove nested links
		else
			hat = hat .. '[[:' .. page .. '|' .. displaytitle .. ']].'
		end
		if edit then
			hat = hat .. '<span class="mw-editsection-like plainlinks"><span class="mw-editsection-bracket">[</span>['
			hat = hat .. title:fullUrl( 'action=edit' ) .. ' ' .. mw.message.new( 'editsection' ):plain()
			hat = hat .. ']<span class="mw-editsection-bracket">]</span></span>'
		end
		if config.hat then
			hat = config.hat .. hat .. '}}'
			hat = frame:preprocess( hat )
		else
			hat = mw.html.create( 'div' ):addClass( 'dablink excerpt-hat' ):wikitext( hat )
		end
	else
		hat = nil
	end

	-- Build the "Read more" link
	if more and not inline then
		more = "'''[[" .. page .. '#' .. ( section or '' ) .. "|" .. getMessage( 'more' ) .. "]]'''"
		more = mw.html.create( 'div' ):addClass( 'noprint excerpt-more' ):wikitext( more )
	else
		more = nil
	end

	-- Build the options for Module:Transcluder out of the template parameters and the desired defaults
	local options = {
		files = files,
		lists = lists,
		tables = tables,
		paragraphs = paragraphs,
		sections = subsections,
		categories = 0,
		references = references,
		only = only and mw.text.trim( only, 's' ) .. 's',
		noLinks = noLinks,
		noBold = noBold,
		noSelfLinks = true,
		noNonFreeFiles = onlyFreeFiles,
		noBehaviorSwitches = true,
		fixReferences = true,
		linkBold = true,
	}

	-- Get the excerpt itself
	local title = page .. '#' .. ( section or '' )
	local ok, excerpt = pcall( Transcluder.get, title, options )
	if not ok then return getError( excerpt ) end
	if mw.text.trim( excerpt ) == '' and not only then
		if section then return getError( 'section-empty', section ) else return getError( 'lead-empty' ) end
	end

	-- Fix birth and death dates, but only in the first paragraph
	if briefDates then
		local startpos = 1 -- skip initial templates
		local s
		local e = 0
		repeat
			startpos = e + 1
			s, e = mw.ustring.find( excerpt, "%s*%b{}%s*", startpos )
		until not s or s > startpos
		s, e = mw.ustring.find( excerpt, "%b()", startpos ) -- get (...), which may be (year–year)
		if s and s < startpos + 100 then -- look only near the start
			local year1, conjunction, year2 = mw.ustring.match( mw.ustring.sub( excerpt, s, e ), '(%d%d%d+)(.-)(%d%d%d+)' )
			if year1 and year2 and (mw.ustring.match( conjunction, '[%-–—]' ) or mw.ustring.match( conjunction, '{{%s*[sS]nd%s*}}' )) then
				local y1 = tonumber(year1)
				local y2 = tonumber(year2)
				if y2 > y1 and y2 < y1 + 125 and y1 <= tonumber( os.date( "%Y" )) then
					excerpt = mw.ustring.sub( excerpt, 1, s ) .. year1 .. "–" .. year2 .. mw.ustring.sub( excerpt, e )
				end
			end
		end
	end

	-- If no file was found, try to get one from the infobox
	local fileNamespaces = Transcluder.getNamespaces( 'File' )
	if ( ( only == 'file' or only == 'files' ) or ( not only and ( files ~= '0' or not files ) ) ) and -- caller asked for files
		not Transcluder.matchAny( excerpt, '%[%[', fileNamespaces, ':' ) and -- and there are no files in Transcluder's output
		config.captions -- and we have the config option required to try finding files in templates
	then
		-- We cannot distinguish the infobox from the other templates so we search them all
		local infobox = Transcluder.getTemplates( excerpt );
		infobox = table.concat( infobox )
		local parameters = Transcluder.getParameters( infobox )
		local file, captions, caption
		for _, pair in pairs( config.captions ) do
			file = pair[1]
			file = parameters[file]
			if file and Transcluder.matchAny( file, '^.*%.', { '[Jj][Pp][Ee]?[Gg]', '[Pp][Nn][Gg]', '[Gg][Ii][Ff]', '[Ss][Vv][Gg]' }, '.*' ) then
				file = mw.ustring.match( file, '%[?%[?.-:([^{|]+)%]?%]?' ) or file -- [[File:Example.jpg{{!}}upright=1.5]] to Example.jpg
				captions = pair[2]
				for _, p in pairs( captions ) do
					if parameters[ p ] then caption = parameters[ p ] break end
				end
				excerpt = '[[File:' .. file .. '|thumb|' .. ( caption or '' ) .. ']]' .. excerpt
				if ( onlyFreeFiles ) then
					excerpt = Transcluder.removeNonFreeFiles( excerpt )
				end
				break
			end
		end
	end

	-- Unlike other elements, templates are filtered here
	-- because we had to search the infoboxes for files
	local trash
	if only and ( only == 'template' or only == 'templates' ) then
		trash, excerpt = Transcluder.getTemplates( excerpt, templates );
	else -- Remove blacklisted templates
		local blacklist = config.blacklist and table.concat( config.blacklist, ',' ) or ''
		if templates then
			if string.sub( templates, 1, 1 ) == '-' then --Unwanted templates. Append to blacklist
				blacklist = templates .. ',' .. blacklist
			else --Wanted templates. Replaces blacklist and acts as whitelist
				blacklist = templates
			end
		else
			blacklist = '-' .. blacklist
		end
		trash, excerpt = Transcluder.getTemplates( excerpt, blacklist );
	end

	-- Remove extra line breaks but leave one before and after so the parser interprets lists, tables, etc. correctly
	excerpt = mw.text.trim( excerpt )
	excerpt = string.gsub( excerpt, '\n\n\n+', '\n\n' )
	excerpt = '\n' .. excerpt .. '\n'

	-- Remove nested categories
	excerpt = frame:preprocess( excerpt )
	local categories, excerpt = Transcluder.getCategories( excerpt, options.categories )

	-- Add tracking categories
	if config.categories then
		local contentCategory = config.categories.content
		if contentCategory and mw.title.getCurrentTitle().isContentPage then
			excerpt = excerpt .. '[[Category:' .. contentCategory .. ']]'
		end
		local namespaceCategory = config.categories[ mw.title.getCurrentTitle().namespace ]
		if namespaceCategory then
			excerpt = excerpt .. '[[Category:' .. namespaceCategory .. ']]'
		end
	end

	-- Load the styles
	local styles
	if config.styles then
		styles = frame:extensionTag( 'templatestyles', '', { src = config.styles } )
	end

	-- Combine and return the elements
	if inline then
		return mw.text.trim( excerpt )
	end
	local tag = 'div'
	if quote then
		tag = 'blockquote'
	end
	excerpt = mw.html.create( 'div' ):addClass( 'excerpt' ):wikitext( excerpt )
	local block = mw.html.create( tag ):addClass( 'excerpt-block' ):addClass( class )
	return block:node( styles ):node( hat ):node( excerpt ):node( more )
end

-- Entry points for backwards compatibility
function p.lead( frame ) return p.main( frame ) end
function p.excerpt( frame ) return p.main( frame ) end

return p