Module:Broodkrummels

in Wikipedia, die vrye ensiklopedie

Module om broodkrummels vir navigasie neer te lê. Die module word in {{Broodkrummels}} gebruik.


local p = {}
-- Openingstag voor alle tabellen in de broodkruimel
p.table = '<table cellspacing="1" cellpadding="0">'
-- Curly dinges voor achter vertakkingen
p.curly = '<big>}</big>'
-- Wolkje voor weggelaten categorieen
p.wolkje = '(...)'
-- Maximaal aantal categorieen voor we het voor gezien houden
p.MAX = 50
-- Categorie waar we pagina's met broodkruimelproblemen in zetten
p.probleemcat = 'Wikipedia:Broodkrummelprobleme'

-- We houden bij of we problemen tegenkomen. Het soort probleem
-- geven we aan met een letter die als sorteersleutel in de 
-- probleemcategorie gebruiken. Als er meer problemen zijn, nemen
-- we gewoon de laatste.
--   "P": parameterprobleem: er is een ongeldige waarde voor
--        een parameter opgegeven
--   "L": lege broodkruimel: de categorieboom is te ingewikkeld
--        of de opgegeven pagina heeft geen categorieen
--   "M": we hebben p.MAX bereikt, dus de boom is niet af
p.problemen = ""

--[[
    broodkruimel( frame )

    Maakt een broodkruimelnavigatie voor de categorieen van een pagina.
    Als frame.args[pagina] opgegeven is, wordt die pagina gebruikt.
    Zoniet, en frame.args[1] is opgegeven, dan wordt die pagina gebruikt.
    Als geen van beiden opgegeven is, wordt de huidige pagina gebruikt.
    
]]
function p.broodkrummel( frame )

	-- Voor welke pagina?
	local title = frame.args.bladsy or frame.args[1]
	if ( not title or title == "" ) then
		title = mw.title.getCurrentTitle().prefixedText
	end
	
	-- Hoogte?
	local level = 8
	p.force = false
	if ( frame.args.lengte and frame.args.lengte ~= "" ) then
		n = tonumber( frame.args.lengte )
		if ( n ~= nil and n > 0 ) then
			level = n
			if ( frame.args.forseer and frame.args.forseer ~= "" ) then
				p.force = true
			end
		else
			p.probleem( "P" )
		end
	end
	
	-- Maximale aantal parallelle vertakkingen?
	p.max_branch = 4
	if ( frame.args.maxbranch and frame.args.maxbranch ~= "" ) then
		local n = tonumber( frame.args.maxbranch )
		if ( n ~= nil and n > 0 ) then
			p.max_branch = n
		else
			p.probleem( "P" )
		end
	end
	
	-- Text verkleinen?
	local txtsize = 20
	p.verklein = false
	if ( frame.args.begingrootte and frame.args.begingrootte ~= "" ) then
		p.verklein = true
		local n = tonumber( frame.args.begingrootte ) 
		if ( n ~= nil and n > 0 ) then
			txtsize = 2 * n
		else
			p.probleem( "P" )
		end
	end
		
	-- Maak boom
	local trees = p.createCategoryTree( title, level )
	
	-- Maak kruimel
	local ntitle, ntree = next( trees )
	local kruimel = ""
	if ( type( ntree ) == "table" and next( ntree ) ) then
		kruimel = p.createBreadCrumb( ntitle, ntree, txtsize )
	else
		p.probleem( "L" )
	end
	
	return kruimel .. p.printprobleem()
	
end

--[[

	parseCategories( wikitext )

	Zoekt geldige categorieen in wikitext.

]]
function p.parseCategories( txt ) 
	
	if ( txt == nil ) then return {} end
	
	local cats = {}
	
	local pattern = "%[%[%s*[Kk][Aa][Tt][Ee][Gg][Oo][Rr][YyIi][Ee]?%s*:%s*([^|%]]+)[|%]]"
        
	for category in mw.ustring.gmatch( txt, pattern ) do
		-- Spaties aan het eind verwijderen
		category = mw.text.trim( category )
		-- Eerste letter omzetten naar hoofdletter
		category = mw.language.getContentLanguage():ucfirst( category )
		-- Underscores naar spaties
		category = mw.ustring.gsub( category, "_", " " )
		-- Sla categorieen met gekke dingen over: sjablonen e.d. 
		if ( mw.ustring.find( category, "[{}%[%]]" ) == nill) then
			-- Als de naam langer is dan 50 tekens is er waarschijnlijk
			-- iets mis (ontbrekende sluit-]]?)
			if ( mw.ustring.len( category ) < 50 ) then
				cats["Kategorie:" .. category] = ""
				p.branchcount = p.branchcount + 1
			end
		end
	end
	
	return cats
	
end

--[[

	createCategoryTree( title, maxlevel )

	Maakt een boom van de categorieen boven title, tot een afstand van
	maxlevel. Stopt als de boom meer dan p.max_branch takken bevat.

]]
function p.createCategoryTree( title, maxlevel ) 

	local level = 0
	local tree = { [title] = "" } 
	
	p.seen = {}
	p.count = 0
	
	while level < maxlevel do
		level = level + 1
		p.branchcount = 0
		local new_tree = p.addLevel( mw.clone (tree) )
		if ( not p.force and p.branchcount > p.max_branch ) then
			return tree
		elseif ( new_tree == nil ) then
			return tree
		end
		tree = new_tree
	end
	
	return tree
	
end

function p.addLevel ( tree )

	local result = {}
	
	for cat,rest in pairs( tree ) do
		
		if ( rest == "" ) then
			if ( p.seen[cat] ) then
				if ( cat == "Categorie:Alles" ) then
					result[cat] = {}
				else
					result[cat] = { ["..."] = {} }
					p.branchcount = p.branchcount + 1
				end
			else
				p.count = p.count + 1
				if ( p.count > p.MAX ) then
					p.probleem( "M" )
					return nil
				end
				page = mw.title.new( cat )
				local cats = p.parseCategories( page:getContent() )
				result[cat] = cats
				p.seen[cat] = true
			end
		else
			local temp = p.addLevel( rest )
			if ( temp == nil ) then
				return nil
			else
				result[cat] = temp
			end
		end
	end
	
	return result
	
end


--[[

	createBreadCrumb( title, trees, txtsize )

	Maakt een breadcrumb navigatie voor trees.
	title: de titel van de pagina waarvoor de breadcrumb is
	trees: de categoriebomen zoals gemaakt door createCategoryTrees(title)
	txtsize: lettergrootte

]]
function p.createBreadCrumb( title, tree, txtsize )
	
        tree = tree or {}
	local str = ""
	
	if ( p.verklein ) then
		str = str .. '<div style="font-size: ' .. math.floor( txtsize/2 ) .. 'pt">'
	end
	
	str = str .. p.table .. '<tr><td align="right">'
	
	local count = 0
	
	for ntitle, ntree in pairs( tree ) do
		count = count + 1
		if ( ntitle == "..." ) then
			str = str .. p.wolkje
		else
			if ( type( ntree ) == "table" ) then
				str = str .. p.createBreadCrumb( ntitle, ntree, txtsize-1 ) 
			else
				str = str .. p.createBreadCrumb( ntitle, {}, txtsize-1 ) 
			end
		end
	end
	
	str = str .. "</td><td>"
	
	if ( count > 1 ) then
		str = str .. p.curly .. '</td><td align="right">'
	end
	if ( count > 0 ) then
		str = str .. '</td><td>&nbsp;&rarr;&nbsp;</td><td>'
	end
	
	str = str .. "[[:" .. title .. "|" .. p.removeCatNS( title ) .. "]]"
	str = str .. "</td></tr></table>"
	
	if ( p.verklein ) then str = str .. "</div>" end

	return str
	
end

--[[
	removeCatNS( title )

	Verwijdert "Categorie:" of "Category:"
]]
function p.removeCatNS( title )
	title = mw.ustring.gsub( title, "^[Kk][Aa][Tt][Ee][Gg][Oo][Rr][Yy]:", "" )
	title = mw.ustring.gsub( title, "^[Kk][Aa][Tt][Ee][Gg][Oo][Rr][Ii][Ee]:", "" )
	return title
end

function p.printprobleem( )
	
	if ( p.problemen ~= nil and p.problemen ~= "" ) then
		return "[[Kategorie:" .. p.probleemcat .. "|" .. p.problemen .. "]]"
	else
		return ""
	end
end

function p.probleem( letter )
	p.problemen = letter
end

--[[
	pptable( table )

	Maakt een string van een table gemaakt door createCategoryTrees().
	Alleen voor testen en debuggen.
]]
function p.pptable( table ) 
	
	local str = ""
        table = table or {}

	for k,v in pairs( table ) do
		str = str .. k .. ": "
		if ( type( v ) == "string" ) then
		else
			str = str .. "{" .. p.pptable(v) .. "}, "
		end
		
	end
	
	return str
end
	
	
return p