local Transcluder = require('Module:Transcluder')  local yesno = require('Module:Yesno')  local ok, config = pcall(require, 'Module:Extract/config') if not ok then config = {} end  local p = {}  -- Helper function to get arguments local args function getArg(key, default) 	value = args[key] 	if value and mw.text.trim(value) ~=  then 		return value 	end 	return default end  -- Helper function to handle errors 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 function getMessage(key) 	local ok, TNT = pcall(require, 'Module:TNT') 	if not ok then return key end 	return TNT.format('I18n/Module:Extract.tab', key) end  function p.main(frame) 	args = Transcluder.parseArgs(frame)  	-- Make sure the requested page exists 	local page = getArg(1) 	if not page then return getError('no-page') end 	local title = mw.title.new(page) 	if not title then return getError('no-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 	local fragment = getArg('fragment') 	local section = fragment or getArg(2, mw.ustring.match(getArg(1), '[^#]+#([^#]+)')) 	local hat = yesno( getArg('hat', true) ) 	local this = getArg('this') 	local only = getArg('only') 	local files = getArg('files') 	local lists = getArg('lists') 	local tables = getArg('tables') 	local sections = not yesno( getArg('sections') ) 	local templates = table.concat((config.templates or {}), ',') 	local paragraphs = getArg('paragraphs') 	local references = getArg('references') 	local noBold = not yesno( getArg('bold') ) 	local inline = yesno( getArg('inline') ) 	local quote = yesno( getArg('quote') ) 	local more = yesno( getArg('more') ) 	local class = getArg('class')  	-- 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('extract') .. ' ' 		if section and not fragment then 			hat = hat .. '' .. page 				.. ' § ' .. mw.ustring.gsub(section, '%[%[([^]|]+)|?[^*%]%]', '%1') .. ']]' -- remove nested links 		else 			hat = hat .. '' .. page .. '' 		end 		hat = hat .. "" .. '[[' 		hat = hat .. title:fullUrl('action=edit') .. ' ' .. mw.message.new('editsection'):plain() 		hat = hat .. ']]' .. "" 		local ok, Hatnote = pcall(require, 'Module:Hatnote') 		if ok then 			hat = Hatnote._hatnote( hat, { extraclasses = 'dablink extract-hat', selfref = true } ) 		else 			hat = mw.html.create('div'):addClass('dablink extract-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 extract-more'):wikitext(more) 	else 		more = nil 	end  	-- Build the options for Module:Transcluder out of the template arguments and the desired defaults 	local options = { 		files = files, 		lists = lists, 		tables = tables, 		paragraphs = paragraphs, 		templates = templates ~=  and '-' .. templates, 		sections = sections, 		categories = 0, 		references = references, 		only = only and mw.text.trim(only, 's') .. 's', 		noBold = noBold, 		noSelfLinks = true, 		noBehaviorSwitches = true, 		fixReferences = true, 		linkBold = true, 	}  	-- Get the extract itself 	local title = page .. '#' .. (section or ) 	local ok, extract = pcall(Transcluder.get, title, options) 	if not ok then return getError(extract) end 	if mw.text.trim(extract) ==  then 		if section then return getError('section-empty', section) else return getError('lead-empty') end 	end  	-- Add a line break in case the extract starts with a table or list 	extract = '\n' .. extract  	-- If no file was found, try to extract one from the removed infoboxes 	local fileNamespaces = Transcluder.getNamespaces('File') 	if (files ~= '0' or not files) and not Transcluder.matchAny(extract, '%[%[', fileNamespaces, ':') and config.captions then 		local templates = Transcluder.get(title, { only = 'templates', templates = templates, fixReferences = true } ) 		local parameters = Transcluder.getParameters(templates) 		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.jpgupright=1.5 to Example.jpg 				captions = pair[2] 				for _, p in pairs(captions) do 					if parameters[p] then caption = parameters[p] break end 				end 				extract = '[[File:' .. file .. '|thumb|' .. (caption or ) .. ']]' .. extract 				break 			end 		end 	end  	-- Remove nested categories 	extract = frame:preprocess(extract) 	local categories, extract = Transcluder.getCategories(extract, options.categories)  	-- Add tracking categories 	if config.categories then 		local contentCategory = config.categories.content 		if contentCategory and mw.title.getCurrentTitle().isContentPage then 			message:node('Category:' .. contentCategory .. '') 		end 		local namespaceCategory = config.categories[ mw.title.getCurrentTitle().namespace ] 		if namespaceCategory then 			extract = extract .. '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 	local tag1 = 'div' 	local tag2 = 'div' 	if inline then 		tag1 = 'span' 		tag2 = 'span' 	elseif quote then 		tag2 = 'blockquote' 	end 	extract = mw.html.create(tag1):addClass('extract'):wikitext(extract) 	local block = mw.html.create(tag2):addClass('extract-block'):addClass(class) 	return block:node(styles):node(hat):node(extract):node(more) end  return p