Documentatie voor deze module kan aangemaakt worden op de volgende pagina: Module:Koptekst/doc

require( 'strict' )

local p = {}

local getArgs = require('Module:Arguments').getArgs
local vraagWikidata = require('Module:Wikidata Boek').vraagWikidata

local function rangtelwoord(getal)
	local rangtelwoorden = {
		'eerste', 'tweede', 'derde', 'vierde', 'vijfde',
		'zesde', 'zevende', 'achtste', 'negende'
	}
	
	local woord = rangtelwoorden[getal]
	if not woord then
		woord = tostring(getal) .. 'e'
	end
	
	return woord
end

local function tekenAuteurs(auteurs)
	-- auteurs dient een lege tabel te zijn als er geen auteurs zijn, niet nil!
	if #auteurs == 0 then
		return nil
	end

	-- anders concateneren en als wikitext aan een .ws-koptekst-auteur div toevoegen
	local auteurs_tekst = table.concat(auteurs, ', ')
	local auteurs_html = mw.html.create('div')
		:addClass('ws-koptekst-auteur')
		:wikitext(auteurs_tekst)
	return auteurs_html
end

local function tekenTitel(titel)
	-- een titel komt er altijd, desnoods met ''titelloos werk''
	
	local titel_html = mw.html.create('div')
		:addClass('ws-koptekst-volledige-titel')
	
	local titel_tag = titel_html
		:tag('div')
		:addClass('ws-koptekst-titel')

	if titel.titel then
		titel_tag:wikitext(titel.titel)
	else
		titel_tag:node('<i>titelloos werk</i>')
	end
	
	if titel.ondertitel then
		titel_html:tag('div')
			:addClass('ws-koptekst-ondertitel')
			:wikitext(titel.ondertitel)
	end

	return titel_html
end

local function tekenVertalers(vertalers)
	-- vertalers dient een lege tabel te zijn als er geen auteurs zijn, niet nil!
	if #vertalers == 0 then
		return nil
	end

	-- anders concateneren en als wikitext aan een .ws-koptekst-auteur div toevoegen
	local vertalers_tekst = table.concat(vertalers, ', ')
	local vertalers_html = mw.html.create('div')
		:addClass('ws-koptekst-vertaler')
		:wikitext('Vertaald door ' .. vertalers_tekst)
	return vertalers_html
end

local function krijgDruktekst(druk)
	-- als er een oorspronkelijke schrijfwijze is gebruiken we die:
	if druk.schrijfwijze then
		return druk.schrijfwijze
	elseif druk.nummer then
		-- altijd een string, maar misschien een getal
		local druknummer = tonumber(druk.nummer)
		if druknummer then
			local telwoord = rangtelwoord(druknummer)
			local telwoord = string.gsub(telwoord, '^%l', string.upper) -- eerste letter hoofdletter
			return telwoord .. ' druk'
		else
			return druk.nummer
		end
	else
		return error('Onverwachte error: er is info over de druk, maar geen getal.') -- onmogelijk om te komen
	end
end

local function formatteerUitgegeven(drukInfo)
	local tekst = ''

	if drukInfo.plaats then
		tekst = tekst .. drukInfo.plaats .. ': '
	end

	if drukInfo.uitgever then
		tekst = tekst .. drukInfo.uitgever .. ', '
	end

	if drukInfo.jaar then
		tekst = tekst .. drukInfo.jaar .. '.'
	else
		tekst = tekst .. '<i>onbekende datum</i>.'
	end
	
	return tekst
end

local function tekenDrukInfo(drukInfo, eersteDrukInfo)
	local info_html = mw.html.create('table')
		:addClass('ws-koptekst-info')
	
	if not eersteDrukInfo.jaar then
		info_html:attr("style", "max-width: 40%;")
	end
	
	-- de table head rij verschijnt waneer er ofwel bekend is welke druk dit is,
	-- ofwel er een jaar van eerste druk bestaat.
	if drukInfo.druk or eersteDrukInfo.jaar then
		local eerste_rij = info_html:tag('tr')

		local deze_druk_html = eerste_rij
			:tag('th')
			:addClass('ws-koptekst-info-druk')
		
		local druktekst
		if drukInfo.druk then
			druktekst = krijgDruktekst(drukInfo.druk)
		else
			druktekst = 'Deze druk'
		end
		
		if drukInfo.taal then
			druktekst = druktekst .. ' (' .. drukInfo.taal .. ')'
		end
		
		deze_druk_html:wikitext(druktekst)


		if eersteDrukInfo.jaar then
			local eerste_druk_html = eerste_rij
				:tag('th')
				:addClass('ws-koptekst-info-eerste-druk')
			local eerstedruktekst
			if eersteDrukInfo.druk then
				eerstedruktekst = krijgDruktekst(eersteDrukInfo.druk)
			else
				eerstedruktekst = 'Eerste druk'
			end
			
			if eersteDrukInfo.taal then
				eerstedruktekst = eerstedruktekst .. ' (' .. eersteDrukInfo.taal .. ')'
			end

			eerste_druk_html:wikitext(eerstedruktekst)
		end
	end
	
	-- dan de tweede rij. die verschijnt altijd, want zelfs als er niets te
	-- melden is komt er ''onbekende datum'' te staan.
	local tweede_rij = info_html:tag('tr')
	
	local deze_druk_info = tweede_rij:tag('td'):addClass('ws-koptekst-info-druk')
	deze_druk_info:node(formatteerUitgegeven(drukInfo))
	
	if eersteDrukInfo.jaar then
		local eerste_druk_info = tweede_rij:tag('td'):addClass('ws-koptekst-info-eerste-druk')
		eerste_druk_info:node(formatteerUitgegeven(eersteDrukInfo))
	end
	
	return info_html
end

function p.tekenKoptekst(data)
	local koptekst = mw.html.create('div')
		:addClass('ws-noexport')
		:addClass('ws-koptekst')
		
	koptekst:node(tekenAuteurs(data.auteurs))
	koptekst:node(tekenTitel(data.titel))
	koptekst:node(tekenVertalers(data.vertalers))
	koptekst:node(tekenDrukInfo(data.drukInfo, data.eersteDrukInfo))
	
	return koptekst
end




local function interpreteerMultilevelInhoud(inhoud_string)
	local rootTable = {}
	rootTable.root = true
	
	local currentLevel = 1
	local currentTable = rootTable
	
	for line in mw.text.gsplit(inhoud_string, "\n", true) do
		local asterisks, text = mw.ustring.match(line, "^%s*(%**)%s*([^*].-)%s*$")
		
		if asterisks then
			local asterisks = string.len(asterisks)

			if asterisks == currentLevel then
				-- nothing
			elseif asterisks == currentLevel+1 then
				-- descend into last element
				currentTable = currentTable[#currentTable]
				currentLevel = currentLevel + 1
			elseif asterisks < currentLevel then
				-- go up for each level back
				while asterisks < currentLevel do
					currentTable = currentTable.parent
					currentLevel = currentLevel - 1
				end
			else
				return '<span class=error>Kan niet meer dan één level dieper tegelijk gaan</span>'
			end
			
			local newTable = {}
			newTable.parent = currentTable
			newTable.name = text
			
			if #currentTable > 0 then
				newTable.prevElem = currentTable[#currentTable]
				currentTable[#currentTable].nextElem = newTable
			end

			table.insert(currentTable, newTable)
			currentTable[newTable.name] = newTable
		end
	end
	
	return rootTable
end

local function genereerLinkLijst(werk_titel, pagina_tabel)
	if not pagina_tabel or pagina_tabel.root then
		local tabel = {}
		tabel.link_root = werk_titel
		return tabel
	end
	
	local lijst = genereerLinkLijst(werk_titel, pagina_tabel.parent)

	local nieuwe_rij = {}
	if pagina_tabel.prevElem then
		nieuwe_rij.vorige = '[[' .. lijst.link_root .. '/' .. pagina_tabel.prevElem.name .. '|' .. pagina_tabel.prevElem.name .. ']]'
	end
	nieuwe_rij.sectie = pagina_tabel.name
	nieuwe_rij.sectie = '[[' .. lijst.link_root .. '/' .. pagina_tabel.name .. '|' .. pagina_tabel.name .. ']]'
	if pagina_tabel.nextElem then
		nieuwe_rij.volgende = '[[' .. lijst.link_root .. '/' .. pagina_tabel.nextElem.name .. '|' .. pagina_tabel.nextElem.name .. ']]'
	end
	
	lijst.link_root = lijst.link_root .. '/' .. pagina_tabel.name
	
	table.insert(lijst, nieuwe_rij)
	
	return lijst
end

--[[
	Deze functie tekent de tabel onder de koptekst die de links naar vorige en
	volgende hoofdstukken bevatten.
	
	lijst: een lijst van tabellen met mogelijke waardes voor vorige, volgende,
		sectie
	returnt: De gegenereerde mw.html tabel
]]
local function tekenKoptekstNavigatie(lijst)
	if not lijst or #lijst == 0 then
		-- geen waardes: return niks
		return nil
	end

	local nav_tabel = mw.html.create('table')
		:addClass('ws-onder-koptekst-navigatie')
	
	for i, v in ipairs(lijst) do
		local nav_rij = nav_tabel:tag('tr')
		
		local vorige_td = nav_rij:tag('td')
			:addClass('ws-onder-koptekst-vorige')
		if v.vorige then
			vorige_td:tag('span')
				:wikitext(v.vorige)
			
			-- TODO automatische footer weer doen werken
		end

		local sectie_td = nav_rij:tag('td')
			:addClass('ws-onder-koptekst-sectie')
		if v.sectie then
			sectie_td:wikitext(v.sectie)
		end
		
		local volgende_td = nav_rij:tag('td')
			:addClass('ws-onder-koptekst-volgende')
		if v.volgende then
			volgende_td:tag('span')
				:wikitext(v.volgende)
		end
	end
	
	return nav_tabel
end





function p.tekenOnderKoptekst(args)
	local sectie, vorige, volgende =
		args.Sectie or args.current,
		args.Vorige or args.prev,
		args.Volgende or args.next

	local onder_koptekst = mw.html.create('div')
		:addClass('ws-noexport')
		:addClass('ws-onder-koptekst')
	
	if args.nestedinhoud and #args.nestedinhoud > 0 then
		local inhoud_tabel = interpreteerMultilevelInhoud(args.nestedinhoud)
		local titel = mw.title.getCurrentTitle()
		local titel_delen = mw.text.split(titel.text, '/', true)
		local werk_titel = table.remove(titel_delen, 1)

		-- pagina vinden
		local pagina_tabel = inhoud_tabel
		while #titel_delen > 0 do
			pagina_tabel = pagina_tabel[titel_delen[1]]
			table.remove(titel_delen, 1)
		end
		
		local link_lijst = genereerLinkLijst(werk_titel, pagina_tabel)
		local koptekst_navigatie = tekenKoptekstNavigatie(link_lijst)

		onder_koptekst:node(koptekst_navigatie)
	elseif sectie or vorige or volgende then
		local nav = onder_koptekst:tag('table')
			:addClass('ws-onder-koptekst-navigatie')
			:tag('tr')
		
		if vorige or volgende then
			local td = nav:tag('td')
				:addClass('ws-onder-koptekst-vorige')
			if vorige then
				td:tag('span')
					:attr('id', 'headerprevious') -- voor de automatische footer
					:wikitext(vorige)
			end
		end
		
		if sectie then
			nav:tag('td')
				:addClass('ws-onder-koptekst-sectie')
				:wikitext(sectie)
		end
		
		if vorige or volgende then
			local td = nav:tag('td')
				:addClass('ws-onder-koptekst-volgende')
			if volgende then
				td:tag('span')
					:attr('id', 'headernext')
					:wikitext(volgende)
			end
		end
	end
	
	if args.extra_info and #args.extra_info > 0 then
		onder_koptekst:tag('div')
			:addClass('ws-onder-koptekst-opmerkingen')
			:wikitext(args.extra_info)
	end
	
	return onder_koptekst
end

function p.koptekst(frame)
	local args = getArgs(frame, {removeBlanks = false})
	local wikidata_id
	local data
	
	if args.wikidata and #args.wikidata > 0 then
		wikidata_id = args.wikidata
	else
		-- wikidata van de titel uit de magic header
		if args.titel then -- anders proberen we of de titelpagina een wikidata heeft
			string.gsub(args.titel, '^%[%[([^]|]*).*$', function(paginatitel)
				wikidata_id =  mw.wikibase.getEntityIdForTitle(paginatitel)
			end)
		end

		-- wikidata van deze pagina
		if not wikidata_id then
			wikidata_id =  mw.wikibase.getEntityIdForCurrentPage()
		end

		
		-- wikidata van een hoofdpagina
		if not wikidata_id then
			local paginatitel = mw.title.getCurrentTitle().text
			while string.find(paginatitel, '/', 1, true) do
				paginatitel = string.gsub(paginatitel, '^(.*)/.*$', function(parentPagina)
					wikidata_id =  mw.wikibase.getEntityIdForTitle(parentPagina)
					if wikidata_id then
						return '' -- klaar
					else
						return parentPagina
					end
				end)
			end
		end
	end
	
	assert(wikidata_id, 'Geen wikidata ID gevonden.')

	data = vraagWikidata(wikidata_id)
	local style = frame:extensionTag{name = 'templatestyles', args = { src = 'Gebruiker:Raketsla/klad/styles.css'}}
	local koptekst = p.tekenKoptekst(data)
	local onder_koptekst = p.tekenOnderKoptekst(args)
	local categorizering = "[[Categorie:Wikisource:Pagina's die de experimentele koptekst gebruiken]]"

	return tostring(style) .. tostring(koptekst) .. tostring(onder_koptekst) .. categorizering
end

return p