Zum Inhalt springen

„Modul:Excerpt“ – Versionsunterschied

aus Wikipedia, der freien Enzyklopädie
[gesichtete Version][ungesichtete Version]
Inhalt gelöscht Inhalt hinzugefügt
Keine Bearbeitungszusammenfassung
Markierungen: Mobile Bearbeitung Mobile Web-Bearbeitung
Resetting page to the current content of mw:Module:Excerpt. (docs)
Zeile 1: Zeile 1:
local Transcluder = require('Module:Transcluder')
local p = {}
local mRedirect = require('Modul:Redirect')


local yesno = require('Module:Yesno')
local errors
-- Return blank text, or an error message if requested
local function err(text)
if errors then error(text, 2) end
return ""
end


local ok, config = pcall(require, 'Module:Excerpt/config')
-- Check image for suitablity
if not ok then config = {} end
local function checkimage(image)
local page = mw.ustring.match(image, "([Ff]ile%s*:[^|%]]*)") -- File:(name) ...
or mw.ustring.match(image, "([Ii]mage%s*:[^|%]]*)") -- or Image:(name) ...
if not page then return nil end


local p = {}
local title = mw.title.new(":" .. page) -- Read description page (for :File:Foo rather than File:Foo)
if not title then return nil end


-- Helper function to get arguments
local redir = mRedirect.getTarget(title)
local args
if redir then title = mw.title.new(redir) end
function getArg(key, default)

value = args[key]
local frame = mw.getCurrentFrame()
if value and mw.text.trim(value) ~= '' then
local desc = frame:preprocess("{{" .. title.prefixedText .. "}}")
return value
return desc and desc ~= "" and not mw.ustring.match(desc, "[Nn]on%-free") -- hide non-free image
end
return default
end
end


-- Helper function to handle errors
-- Attempt to parse [[File:...]] or [[Image:...]], either anywhere or at the start
local function parseimage(text, start)
function getError(message, value)
if type(message) == 'string' then
local startre = ""
message = Transcluder.getError(message, value)
if start then startre = "^" end -- a true flag restricts search to start of string
end
local image = mw.ustring.match(text, startre .. "%[%[%s*[Ff]ile%s*:.*") -- [[File: ...
if config.categories and config.categories.errors and mw.title.getCurrentTitle().isContentPage then
or mw.ustring.match(text, startre .. "%[%[%s*[Ii]mage%s*:.*") -- or [[Image: ...
message:node('[[Category:' .. config.categories.errors .. ']]')
if image then
image = mw.ustring.match(image, "%b[]%s*") -- match [[...]] to handle nesting
end
end
return image
return message
end
end


-- Helper function to get localized messages
-- Attempt to construct a [[File:...]] block from {{infobox ... |image= ...}}
local function argimage(text)
function getMessage(key)
local token = nil
local ok, TNT = pcall(require, 'Module:TNT')
if not ok then return key end
if mw.ustring.match(text, "%{%{%s*[Ii]nfobox") then
return TNT.format('I18n/Module:Excerpt.tab', key)
local image = mw.ustring.match(text, "|%s*image%s*=%s*([^%}|]*)") -- parse image= argument...
or mw.ustring.match(text, "|%s*Cover%s*=%s*([^%}|]-)") -- or Cover= from Infobox album
if image then -- add in relevant parameters: caption, alt text and image size
token = "[[File:" .. image
local caption = mw.ustring.match(text, "|%s*[Cc]aption%s*=%s*([^%}|]*)")
if caption then token = token .. "|" .. caption end
local alt = mw.ustring.match(text, "|%s*alt%s*=%s*([^%}|]*)")
if alt then token = token .. "|alt=" .. alt end
local image_size = mw.ustring.match(text, "|%s*image_size%s*=%s*([^%}|]*)")
if image_size then token = token .. "|" .. image_size end
token = mw.ustring.gsub(token, "\n","") .. "]]\n"
end
end

return token
end
end


function p.main(frame)
-- Entry point for Lua callers
args = Transcluder.parseArgs(frame)
-- Returns a string value: text of the lead of a page
function p._lead(pagenames, options)
errors = options.errors


-- Make sure the requested page exists
if not pagenames or #pagenames < 1 then return err("No page names given") end
local pagename
local page = getArg(1)
if not page then return getError('no-page') end
local text
local pagecount = #pagenames
local title = mw.title.new(page)
if not title then return getError('no-page') end
local firstpage = pagenames[1] or "(nil)" -- save for error message, as it the name will be deleted
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
-- read the page, or a random one if multiple pages were provided
local fragment = getArg('fragment')
if pagecount > 1 then math.randomseed(os.time()) end
local section = fragment or getArg(2, getArg('section', mw.ustring.match(getArg(1), '[^#]+#([^#]+)') ) )
while not text and pagecount > 0 do
local hat = yesno( getArg('hat', true) )
local pagenum = 1
local this = getArg('this')
if pagecount > 1 then pagenum = math.random(pagecount) end -- pick a random title
local only = getArg('only')
pagename = pagenames[pagenum]
local files = getArg('files')
if pagename and pagename ~= "" then
local lists = getArg('lists')
pagename = mw.ustring.match(pagename, "%[%[%s*(.-)[]|#]") or pagename -- "[[Foo|Bar]]" → "Foo"
local tables = getArg('tables')
pagename = mw.ustring.match(pagename, "%S.*%S") -- strip leading and trailing white space
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 pagename and pagename ~= "" then
if hat and not inline then
local title = mw.title.new(pagename) -- Find the lead section of the named page
if this then
if not title then return err("No title for page name " .. pagename) end
hat = this
local redir = mRedirect.getTarget(title)
elseif quote then
if redir then title = mw.title.new(redir) end
hat = getMessage('this')

elseif only then
text = title:getContent()
hat = getMessage(only)
end
else
hat = getMessage('section')
end
end
hat = hat .. ' ' .. getMessage('excerpt') .. ' '
if not text then table.remove(pagenames, pagenum) end -- this one didn't work; try another
if section and not fragment then
pagecount = pagecount - 1 -- ensure that we exit the loop eventually
hat = hat .. '[[' .. page .. '#' .. mw.uri.anchorEncode(section) .. '|' .. page
.. ' § ' .. mw.ustring.gsub(section, '%[%[([^]|]+)|?[^]]*%]%]', '%1') .. ']]' -- remove nested links
else
hat = hat .. '[[' .. page .. ']]'
end
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>' .. "''"
local ok, Hatnote = pcall(require, 'Module:Hatnote')
if ok then
hat = Hatnote._hatnote( hat, { extraclasses = 'dablink excerpt-hat', selfref = true } )
else
hat = mw.html.create('div'):addClass('dablink excerpt-hat'):wikitext(hat)
end
else
hat = nil
end
end
if not text then return err("Cannot read a valid page: first name is " .. firstpage) end


-- Build the "Read more" link
text = mw.ustring.gsub(text, "<!%-%-.-%-%->","") -- remove HTML comments
if more and not inline then
text = mw.ustring.gsub(text, "%c%s*==.*","") -- remove first heading and everything after it
more = "'''[[" .. page .. '#' .. (section or '') .. "|" .. getMessage('more') .. "]]'''"
text = mw.ustring.gsub(text, "<noinclude>.-</noinclude>", "") -- remove noinclude bits
more = mw.html.create('div'):addClass('noprint excerpt-more'):wikitext(more)
text = mw.ustring.gsub(text, "<%s*ref[^>]-/%s*>", "") -- remove refs cited elsewhere
else
text = mw.ustring.gsub(text, "<%s*ref.->.-<%s*/%s*ref%s*>", "") -- remove refs
more = nil
text = mw.ustring.gsub(text, "<%s*imagemap.->.-<%s*/%s*imagemap%s*>", "") -- remove imagemaps
for _, t in pairs {"[Ee]fn", "[Ee]fn-la", "[Ee]l[mn]", "[Rr]p?", "[Ss]fn[bp]", "[Ss]f[bn]", "NoteTag", "#[Tt]ag:%s*[Rr]ef",
"[CcDd]n", "Citation needed", "Disambiguation needed"} do
text = mw.ustring.gsub(text, "{{%s*" .. t .. "%s*|.-}}", "") -- remove ref and footnote templates
end
end
text = mw.ustring.gsub(text, "\n%s*{{%s*[Tt][Oo][Cc].-}}", "\n") -- remove most common tables of contents


-- Build the options for Module:Transcluder out of the template arguments and the desired defaults
local allparas = true -- keep all paragraphs?
if options.paraflags then
local options = {
files = files,
for _, v in pairs(options.paraflags) do
lists = lists,
if v then allparas = false end -- if any para specifically requested, don't keep all
tables = tables,
end
paragraphs = paragraphs,
end
templates = templates ~= '' and '-' .. templates,
sections = sections,
categories = 0,
references = references,
only = only and mw.text.trim(only, 's') .. 's',
noBold = noBold,
noSelfLinks = true,
noNonFreeFiles = true,
noBehaviorSwitches = true,
fixReferences = true,
linkBold = true,
}


-- Get the excerpt itself
local maxfile = 0 -- for efficiency, stop checking images after this many have been found
local title = page .. '#' .. (section or '')
if options.fileflags then
local ok, excerpt = pcall(Transcluder.get, title, options)
for k, v in pairs(options.fileflags) do
if v and k > maxfile then maxfile = k end
if not ok then return getError(excerpt) end
if mw.text.trim(excerpt) == '' then
end
if section then return getError('section-empty', section) else return getError('lead-empty') end
end
end


-- Add a line break in case the excerpt starts with a table or list
-- a basic parser to trim down the lead
excerpt = '\n' .. excerpt
local inlead = false -- have we found some text yet?
local t = "" -- the stripped down output text
local files = 0 -- how many [[Image: or [[File: so far
local paras = 0 -- how many paragraphs so far


-- If no file was found, try to excerpt one from the removed infoboxes
text = mw.ustring.gsub(text,"^%s*","") -- remove initial white space
local fileNamespaces = Transcluder.getNamespaces('File')
repeat -- loop around parsing a template, image or paragraph
if (files ~= '0' or not files) and not Transcluder.matchAny(excerpt, '%[%[', fileNamespaces, ':') and config.captions then
local token = mw.ustring.match(text, "^%b{}%s*") or false -- {{Template}}
local templates = Transcluder.get(title, { only = 'templates', templates = templates, fixReferences = true } )
if token then
local parameters = Transcluder.getParameters(templates)
if inlead then -- keep comments and templates only within text body
local file, captions, caption
t = t .. token
for _, pair in pairs(config.captions) do
elseif files < maxfile then -- look for [[File:... embedded in an infobox etc. in the preamble
file = pair[1]
local image = parseimage(token, false) or argimage(token)
file = parameters[file]
if image and checkimage(image) then -- keep comments and templates only within text body
if file and Transcluder.matchAny(file, '^.*%.', {'[Jj][Pp][Ee]?[Gg]','[Pp][Nn][Gg]','[Gg][Ii][Ff]','[Ss][Vv][Gg]'}, '.*') then
files = files + 1
file = mw.ustring.match(file, '%[?%[?.-:([^{|]+)%]?%]?') or file -- [[File:Example.jpg{{!}}upright=1.5]] to Example.jpg
if options.fileflags and options.fileflags[files] then
captions = pair[2]
image = mw.ustring.gsub(image, "|%s*frameless%s*%f[|%]]", "") -- make image a thumbnail, not frameless etc.
for _, p in pairs(captions) do
image = mw.ustring.gsub(image, "|%s*framed?%s*%f[|%]]", "")
if parameters[p] then caption = parameters[p] break end
if not mw.ustring.match(image, "|%s*thumb%s*%f[|%]]")
and not mw.ustring.match(image, "|%s*thumbnail%s*%f[|%]]") then
image = mw.ustring.gsub(image, "(%]%]%s*)$", "|thumb%1")
end
if options.fileargs then image = mw.ustring.gsub(image, "(%]%]%s*)$", "|" .. options.fileargs .. "%1") end
t = t .. image
end
end
end
excerpt = '[[File:' .. file .. '|thumb|' .. (caption or '') .. ']]' .. excerpt
end
else
break
token = parseimage(text, true)
if token then
if files < maxfile and checkimage(token) then
files = files + 1
if options.fileflags and options.fileflags[files] then
local image = token
if options.fileargs then image = mw.ustring.gsub(image, "(%]%]%s*)$", "|" .. options.fileargs .. "%1") end
t = t .. image
end
end
else -- got a paragraph, which ends at a file, image, blank line or end of text
local afterend = mw.ustring.len(text) + 1
local blankpos = mw.ustring.find(text, "\n%s*\n") or afterend
local endpos = math.min(
mw.ustring.find(text, "%[%[%s*[Ff]ile%s*:") or afterend,
mw.ustring.find(text, "%[%[%s*[Ff]ile%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
inlead = true
paras = paras + 1
if allparas or (options.paraflags and options.paraflags[paras]) then t = t .. token end
end
end
end

if token then text = mw.ustring.sub(text, mw.ustring.len(token)+1) end
until not text or text == "" or not token or token == ""

text = mw.ustring.gsub(t, "\n+$", "") -- remove trailing line feeds, so "{{Transclude text excerpt|Foo}} more" flows on one line

if options.more then text = text .. " '''[[" .. pagename .. "|" .. options.more .. "]]'''" end
return text
end

-- 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}
local function numberflags(str)
local ranges = mw.text.split(str, ",") -- parse ranges, e.g. "1,3-5" → {"1","3-5"}
local flags = {}
for _, r in pairs(ranges) do
local min, max = mw.ustring.match(r, "^%s*(%d+)%s*%-%s*(%d+)%s*$") -- "3-5" → min=3 max=5
if not max then min, max = mw.ustring.match(r, "^%s*((%d+))%s*$") end -- "1" → min=1 max=1
if max then
for p = min, max do flags[p] = true end
end
end
end
end
return flags
end


-- Remove nested categories
-- Shared template invocation code for lead and random functions
excerpt = frame:preprocess(excerpt)
local function leadrandom(frame, israndom)
local categories, excerpt = Transcluder.getCategories(excerpt, options.categories)
-- args = { 1,2,... = page names, paragraphs = list e.g. "1,3-5", files = list, more = text}
local args = frame.args -- from calling module
local pargs = frame:getParent().args -- from template


-- Add tracking categories
local pagenames = { args[1] or pargs[1] } -- For lead, ignore all but the first unnamed argument
if israndom then
if config.categories then
local contentCategory = config.categories.content
-- For random, accept any number of page names. If more than one, we'll pick one randomly
if contentCategory and mw.title.getCurrentTitle().isContentPage then
for i, p in pairs(args) do
excerpt = excerpt .. '[[Category:' .. contentCategory .. ']]'
if p and type(i) == 'number' and i > 1 then table.insert(pagenames, p) end
end
end
local namespaceCategory = config.categories[ mw.title.getCurrentTitle().namespace ]
for i, p in pairs(pargs) do
if namespaceCategory then
if p and type(i) == 'number' and i > 1 and not args[i] then table.insert(pagenames, p) end
excerpt = excerpt .. '[[Category:' .. namespaceCategory .. ']]'
end
end
end
end


-- Load the styles
local options = {}
local styles
options.paraflags = numberflags(args["paragraphs"] or pargs["paragraphs"] or "") -- parse paragraphs, e.g. "1,3-5" → {"1","3-5"}
if config.styles then
options.fileflags = numberflags(args["files"] or pargs["files"] or "") -- parse file numbers
styles = frame:extensionTag( 'templatestyles', '', { src = config.styles } )
options.fileargs = args["fileargs"] or pargs["fileargs"]
end
options.more = args["more"] or pargs["more"]
if options.more and options.more == "" then options.more = "weiterlesen..." end -- more= is short for this default text
options.errors = args["errors"] or pargs["errors"]


-- Combine and return the elements
local text = p._lead(pagenames, options)
local tag1 = 'div'
return frame:preprocess(text)
local tag2 = 'div'
if inline then
tag1 = 'span'
tag2 = 'span'
elseif quote then
tag2 = 'blockquote'
end
excerpt = mw.html.create(tag1):addClass('excerpt'):wikitext(excerpt)
local block = mw.html.create(tag2):addClass('excerpt-block'):addClass(class)
return block:node(styles):node(hat):node(excerpt):node(more)
end
end


-- Entry points for template callers using #invoke:
-- Entry points for backwards compatibility
function p.lead(frame) return leadrandom(frame, false) end
function p.lead(frame) return p.main(frame) end
function p.random(frame) return leadrandom(frame, true) end
function p.excerpt(frame) return p.main(frame) end


return p
return p

Version vom 1. September 2020, 17:06 Uhr

Vorlage:Shared Template Warning


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
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:Excerpt.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, getArg('section', 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('excerpt') .. ' '
		if section and not fragment then
			hat = hat .. '[[' .. page .. '#' .. mw.uri.anchorEncode(section) .. '|' .. page
				.. ' § ' .. mw.ustring.gsub(section, '%[%[([^]|]+)|?[^]]*%]%]', '%1') .. ']]' -- remove nested links
		else
			hat = hat .. '[[' .. page .. ']]'
		end
		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>' .. "''"
		local ok, Hatnote = pcall(require, 'Module:Hatnote')
		if ok then
			hat = Hatnote._hatnote( hat, { extraclasses = 'dablink excerpt-hat', selfref = true } )
		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 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,
		noNonFreeFiles = true,
		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) == '' then
		if section then return getError('section-empty', section) else return getError('lead-empty') end
	end

	-- Add a line break in case the excerpt starts with a table or list
	excerpt = '\n' .. excerpt

	-- If no file was found, try to excerpt one from the removed infoboxes
	local fileNamespaces = Transcluder.getNamespaces('File')
	if (files ~= '0' or not files) and not Transcluder.matchAny(excerpt, '%[%[', 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.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
				break
			end
		end
	end

	-- 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
	local tag1 = 'div'
	local tag2 = 'div'
	if inline then
		tag1 = 'span'
		tag2 = 'span'
	elseif quote then
		tag2 = 'blockquote'
	end
	excerpt = mw.html.create(tag1):addClass('excerpt'):wikitext(excerpt)
	local block = mw.html.create(tag2):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