Die Dokumentation für dieses Modul kann unter Modul:Vorlage:Cite web/Doku erstellt werden

--[=[ 2015-04-25
Unterstützung für {{Cite web}}
]=]


-- Global
local Selbst = "Vorlage:Cite web"
local Fehler = false
local KategorieBeginn  =  "Kategorie:Wikipedia:Vorlagenfehler/" .. Selbst
local Kategorien       =
     { Intern       =  { s = "/Interner Fehler" },
       Parameter    =  { s = "/Parameterfehler" }
     }
local Zitation

local Parameter = [==[
{{citeweb
|url
|title
|author
|authors
|last
|first
|authorlink
|last1
|first1
|authorlink1
|last2
|first2
|authorlink2
|last3
|first3
|authorlink3
|last4
|first4
|authorlink4
|last5
|first5
|authorlink5
|editor-last
|editor-first
|editor
|editor-link
|editor1-last
|editor1-first=
|editor1-link
|editor2-last
|editor2-first=
|editor2-link
|editors
|date
|year
|work
|website
|publisher
|location
|page
|pages
|language
|format
|arxiv
|doi
|doi_brokendate
|archiveurl
|archivedate
|accessdate
|quote
|offline
]==]


-- Nicht unterstützt da durch Wikipedia:Zitierregeln festgelegt
--|separator
--|postscript

-- Nicht unterstützt da unzulässige Angabe für einen Internetverweis --> cite book oder cite journal nutzen
--|asin
--|bibcode
--|isbn
--|issn
--|jfm
--|jstor
--|lccn
--|mr
--|oclc
--|ol
--|osti
--|pmc
--|pmid
--|rfc
--|ssrn
--|zbl
--|id

-- Nicht unterstützte Parameter
--|ref
--|dead-url >> in der deutschen Lokalisation 'offline'

-- Derzeit noch nicht unterstützte Parameter
--|trans_title
--|type
--|subscription
--|registration
--|at

-- Nutzung in en-Wiki nicht mehr erwünscht

-- Nicht unterstützte Alias der englischen Vorlage
--|series
--|month --> date
--|year --> date
--|coauthors --> authors (ohne author)

local function fault( a )
    -- Formatiere Fehler mit class=error
    -- Parameter:
    --     a  -- string mit Text
    return string.format( "<span class=\"error\">%s</span>", a )
end -- fault()
 
 
 
local function fehler( art, anzeige )
    -- Ein Fehler ist aufgetreten
    -- Parameter:
    --     art      -- string mit Schlüsselwort zum Typ
    --     anzeige  -- string mit Einzelheiten
    local t
    if not Fehler then
    	Fehler = { Intern    = { s = "Interner Fehler",
                                 k = "Intern" },
                   Modul     = { s = "Modul-Seite fehlt",
                                 k = "Intern" },
                   Vorlage   = { s = "Vorlagen-Seite fehlt",
                                 k = "Intern" },
                   Konflikt  = { s = "Parameterkonflikt",
                                 k = "Parameter" },
                   Parameter = { s = "Parameterfehler",
                                 k = "Parameter" },
                   Pflicht   = { s = "Pflichtparameter fehlt",
                                 k = "Parameter" },
                   Wert      = { s = "Werte ungültig",
                                 k = "Parameter" },
                   Doppelt   = { s = "Mehrfache Angabe von Parametern",
                                 k = "Parameter" }
                 }
    end
    t = Fehler[ art ]
    if t then
        if t.e then
            t.e  =  string.format( "%s; %s", t.e, anzeige )
        elseif anzeige then
            t.e  =  anzeige
        else
            t.e  =  ""
        end
        if t.k then
            local wk  =  Kategorien[ t.k ]
            if wk then
                wk.e  =  true
            else
                Fehler.Intern.e      =  string.format( "Wartungskat %s", wk )
                Kategorien.Intern.e  =  true
            end
        end
    else
        Fehler.Intern.e      =  string.format( "fehler(%s) %s", art, anzeige )
        Kategorien.Intern.e  =  true
    end
end -- fehler()
 
 
 
local function fehlerliste()
    -- Auflistung aller Fehlermeldungen
    -- Rückgabewert: string mit formatiertem Ergebnis
    local r = ""
    local sep = ""
    if Fehler then
        for k, v in pairs( Fehler ) do
             if v.e then
                r = string.format( "%s%s*** %s: %s", r, sep, v.s or "", v.e)
                sep = " "
            end
        end -- for k, v
        r = "<br />" .. fault( r )
    end
    return r
end -- fehlerliste()
 
 
 
local function fire( art )
    -- Melde Kategorie an
    -- Parameter:
    --     art  -- string mit Schlagwort zum Typ
    local t = Kategorien[ art ]
    if t then
        t.e  =  true
    else
        fehler( "Intern",  "Kategorie:" .. art )
    end
end -- fire()
 
 
 
local function firelist()
    -- Auflistung aller gemeldeten Kategorien
    -- Returns: string mit allen Kategorien
    local r  =  ""
    local s
    for k, v in pairs( Kategorien ) do
        if v.e then
            if v.x then
                s  =  "Kategorie:Wikipedia:"
            else
                s  =  KategorieBeginn
            end
            r = string.format( "%s[[%s%s]]", r, s, v.s )
        end
    end -- for k, v
    return r
end -- firelist()



local function framedTemplate( access, args )
    -- Vorlage einbinden
    -- Parameter:
    --     access  -- Name der Vorlage
    --     args    -- table mit Parameterliste
    -- Rückgabewert: string mit expandierter Vorlage
    if not Frame then
        Frame = mw.getCurrentFrame()
    end
    return Frame:expandTemplate{ title = access, args = args }
end -- framedTemplate()



-------------------------------------------------------------------------------



function autorenListe(args, max)
    local names = {}
    local r = ""
    local first = ""
    local sep = ""
    local AddEtAl = false

    -- Prüfung ob mehr als die maximal erwünschte Anzahl von Autoren vorhanden sind
 	for i = max+1, 99, 1 do
 		if args["last" .. i] then
 			max = tonumber(args["display-authors"]) or 1
 			AddEtAl = true
 		end
 	end	
 	
    for i = 1, max, 1 do
        if (i == 1) then
        	if args["last"] or args["last" .. i] then
        		if args["last"] and  args["last" .. i] then
        			fehler( "Doppelt", "'last' und 'last1'" )
    			end
        		if args["first"] and args["first" .. i] then
        			fehler( "Doppelt", "'first' und 'first1'" )
        		end
 
				local linkcount = 0
				local linkparams =  ""
				if args["author-link"] then
					linkcount = linkcount +1 
					linkparams = linkparams .. ", 'author-link'"
				end
				if args["author-link1"] then
					linkcount = linkcount +1 
					linkparams = linkparams .. ", 'author-link1'"
				end
				if args["authorlink"] then
					linkcount = linkcount +1 
					linkparams = linkparams .. ", 'authorlink'"
				end
				if args["authorlink1"] then
					linkcount = linkcount +1 
					linkparams = linkparams .. ", 'authorlink1'"
				end
 
				if linkcount > 1 then
					linkparams = string.gsub(linkparams, ", (['%w%d%-]+)", "%1",1)
					linkparams = string.gsub(linkparams, ", (['%w%d%-]+)$", " und %1")
					fehler( "Doppelt", linkparams )
				end
 
        		if args["last"] or args["last1"] then
            		first = ""
            		if args["first"] or args["first" .. i] then
            			first = (args["first"] or args["first" .. i]) .. " "
            		end
            		if args["authorlink"] or args["author-link"] or args["authorlink1"] or args["author-link1"] then
            			r = string.format("%s%s[[%s|%s%s]]", r, sep, args["authorlink"] or args["author-link"] or args["authorlink1"] or args["author-link1"], first, args["last"] or args["last1"])
        			else
            			r = string.format("%s%s%s%s", r, sep, first, args["last"] or args["last1"])
    				end
        			sep = ", "
        		end
			elseif args["first" .. i] then
    			fehler( "Parameter", "'first" .. i.."' ohne 'last" .. i.."'" )
			elseif args["first"] then
    			fehler( "Parameter", "'first' ohne 'last'" )
    		end		
    	else
            if args["last" .. i] then
            	first = ""
            	if args["first" .. i] then
            		first = args["first" .. i] .. " "
            	end
            	if args["authorlink"..i] then
            		r = string.format("%s%s[[%s|%s%s]]", r, sep, args["authorlink"..i], first, args["last"..i])
        		else
            		r = string.format("%s%s%s%s", r, sep, first, args["last"..i])
    			end
        		sep = ", "
        	elseif args["first" .. i] then
        		fehler( "Parameter", "'first" .. i.."' ohne 'last"..i"'" )
        	end
        	-- TODO Fehlermeldung, wenn ein Autor fehlt --> z.B. last1 und last3 aber nicht last2
    	end
	end
    if AddEtAl then
		r = string.format("%s %s", r, 'et al.')	
	end
 
    if r == "" then
    	r = nil
	end
    return r, AddEtAl;
end --autoren_liste

function hrsgListe(args)
    local names = {}
    local r = ""
    local first = ""
    local sep = ""
    local max = tonumber(args["display-editors"]) or 5
    
    for i = 1, max, 1 do
        if (i == 1) then
        	if args["editor-last"] or args["editor" .. i .. "-last"] then
        		if args["editor-last"] and  args["editor" .. i .. "-last"] then
        			fehler( "Doppelt", "'editor-last' und 'editor1-last'" )
        		elseif args["editor-last"] then
            		if args["editor-first"] then
            			first = args["editor-first"] .. " "
            		else
            			first = ""
            		end
        			r = r .. sep .. first .. args["editor-last"]
        			sep = ", "
        		else
            		if args["editor" .. i .. "-first"] then
            			first = args["editor" .. i .. "-first"] .. " "
            		else
            			first = ""
            		end
        			r = r .. sep .. first .. args["editor" .. i .. "-last"]
        			sep = ", "
        		end
    		end	
        			
    	else
            if args["editor" .. i .. "-last"] then
            	if args["editor" .. i .. "-first"] then
            		first = args["editor" .. i .. "-first"] .. " "
            	else
            		first = ""
            	end
        		r = r .. sep .. first .. args["editor" .. i .. "-last"]
        		sep = ", "
        	end
    	end
    end
    if r == "" then
    	r = nil
	end
    return r;
end

local Autor = function ( args, max )
--|author
--|authors
--|last1 |first1 |author-link1
-- ..
--|last9 |first9 |author-link9
--|display-authors

--Nicht unterstützt
--|authorn --> nutze lastn
--|author1 --> nutze author
--|coauthors --> nutze authors

    local r = args.author or args.authors
    local a, etal = autorenListe( args, max );
    if r and a then
    	fehler( "Doppelt", "'author(s)' und 'last*'" )
    elseif r then
    	if args.author then 
            if args["authorlink"] or args["author-link"] then
    			r = string.format("[[%s|%s]]", args["authorlink"] or args["author-link"], r)
			end
    	end
        if args.author and args.authors then
            fehler( "Doppelt", "'author' und 'authors'" )
        end
    else
    	r = a
    end
    return r
end -- Autor()



local Datum = function ( args, name )
    local r = args[name]
    if (name == "date") then
    	if not is_set(r) then
    		r = args.year
			if  args.year and tonumber(args.year) == nil then
				fehler( "Wert" , "'year'" )
			end
    	elseif is_set(r) and args.year then
			fehler( "Konflikt" , "'date' und 'year'" )
		end
    end

    --if (name == "accessdate") and not (args.archivedate) then
		-- accessdate ist kein aktuell kein Pflichtparameter
		--fehler( "Pflicht" , "'accessdate'" )
	--end

    return r
end -- Datum()


local Herausgeber = function ( args )
-- |editor
-- |editors

-- Noch nicht unterstützt
-- |editor-first |editor-last |editor-link
-- |editor1-last |editor1-first |editor1-link
-- ...
-- |editor5-last |editor5-first |editor5-link
-- |display-editors

    local r = args.editor or args.editors
    local e = hrsgListe( args )
    if r and e then
    	fehler( "Doppelt", "'editor(s)' und 'editor*-last'" )
	elseif r then
        if args.editor and args.editors then
            fehler( "Doppelt", "'editor' und 'editors'" )
        end
    else
    	r = e
    end
    return r
end -- Herausgeber()



local Werk = function ( args )
-- Nicht unterstützte Alias der englischen Vorlage
-- work oder website --> nicht journal, newspaper, magazine, periodical // series
    local r = args.work or args.website
    --if r then
        if args.work and args.website then
            fehler( "Doppelt", "'work' und 'website'" )
        end
    --end
    return r
end -- Werk()



local Seiten = function ( args )
    local r = args.page or args.pages
    if r then
        if args.page and args.pages then
            fehler( "Doppelt", "'page' und 'pages'" )
        end
        -- p. bzw. pp. durch f. bzw. ff. ersetzen
        s = r:gsub( "[%s]*pp[%.]*", " ff." ):gsub( "[%s]*p[%.]*", " f." )
        if r ~= s then
        	fehler( "Wert", "'page' oder 'pages' enthält englischsprachige Abkürzungen" )
    	else
    		r = s
		end
    end
    return r
end -- Seiten()



local URL = function ( args )
    local r = args.url
    if not r then
		fehler( "Pflicht" , "'url'" )
    end
    return r
end -- URL()



local format = function ( args )
    -- Analysiere Argumente und bilde formatierte Zitation
    -- Parameter:
    --     args  -- table mit Vorlagenparametern
    -- Rückgabewert: string mit formatierter Zitation
    local r
    local z = { }
    local pars, schrott = Zitation.filter( args, Parameter )
    if schrott then
        fehler( "Parameter", schrott )
    end

    -- erwünschte Angaben
    z.Autor, etal = Autor( pars, tonumber(args["display-authors"]) or 9)
    if etal then
		z.Coins_autoren = Autor( pars, 99 )
	end
	
    if pars.title then
    	z.Titel        = pars.title
    else
    	fehler( "Pflicht" , "'title'" )
    	z.Titel        = pars.url -- kein leerer Titel/Weblink
    end
    
    z.Datum        = Datum( pars, "date")
    z.URL          = URL( pars )

    z.Format     = pars.format

	if is_set(pars["offline"]) then
		if ((pars["offline"]:lower() =='no') or (pars["offline"]:lower() =='nein')) then
			-- Wenn die URL noch erreichbar ist (laut) Eingabe, dann werden die Archivparameter nicht übergeben
	    	pars["offline"] = nil
	    	pars.archiveurl = nil
	    	pars.archivedate = nil
	    elseif ((pars["offline"]:lower() =='yes') or (pars["offline"]:lower() =='ja')) then
    		z.Offline = pars["offline"]
    	else
    		fehler( "Wert", "'offline'" )	
		end
    end
    
    if pars.archiveurl and Datum( pars, "archivedate") then
    	z.ArchivURL    = pars.archiveurl
    	z.Archivdatum  = Datum( pars, "archivedate")
    elseif pars.archiveurl then
    	fehler( "Konflikt", "ArchivURL nur mit Archivdatum" )
    elseif  is_set(Datum( pars, "archivedate")) then
    	fehler( "Konflikt", "Archivdatum nur mit ArchivURL" )
	end
	
    z.Abruf        = Datum( pars, "accessdate")
    z.Sprache      = pars.language
    
    -- zusätzliche Angaben
    z.Werk         = Werk ( pars )    
    z.Zitat        = pars.quote
    z.Verlag       = pars.publisher
    z.Ort          = pars.location
    z.Seiten       = Seiten( pars )
    z.Hrsg         = Herausgeber( pars )

    -- Für Internetquellen sinnvolle Parameter
    z.DOI          = pars.doi
    z.arXiv        = pars.arxiv
    
    -- Zusätzliche Hinweise im Kommentar
    --z.Kommentar    = pars.comment
    --z.Typ          = Typ( pars )

    z.COinS        = false
    z.Klasse       = "website"
    z._Selbst      = "Cite web"

    r, schrott = Zitation.format( z )
    if schrott then
        r = r .. schrott
        --fehler( "Wert", schrott )
    end
    return r
end -- format()



local function f( a )
    -- Hauptfunktion zur Steuerung des Gesamtablaufs
    -- Rückgabewert: string mit formatiertem Gesamtergebnis
    local lucky, r = pcall( require, "Modul:Zitation" )
    if type( r ) == "table" then
        Zitation = r.Zitation()
        r = format( a )
    else
        fehler( "Modul", r )
    end
    return  string.format( "%s%s%s", r, fehlerliste(), firelist() )
end -- f()
 
 
 
-- Export
local p = {}
 
function p.test( a )
    local lucky, r = pcall( f, a )
    return r
end
 
function p.f( frame )
    local lucky, r = pcall( f, frame:getParent().args )
    return r
end
 
return p