モジュール:Zitation

local Serial = "2019-01-17"
--=
Zitation
**
Zitation = Zitation  or  { extern = false }
Zitation.serial = Serial
-- local globals
local Selbst      = "Modul:Zitation"
local FehlerTypen = { Intern    = { s = "Interner Fehler",
k = "Intern" },
Entfernen = { s = "Veraltet, bitte entfernen" },
Format    = { s = "Parameterformat" },
Konflikt  = { s = "Parameterkonflikt",
k = "Parameter" },
Modul     = { s = "Modul-Seite fehlt",
k = "Intern" },
Name      = { s = "Schreibweise falsch",
k = "Name" },
Pflicht   = { s = "Pflichtparameter fehlt",
k = "Parameter" },
Problem   = { s = "Parameterproblem" },
Abruf     = { s = "Abrufdatum mangelhaft",
k = "Abruf" },
Vorlage   = { s = "Vorlagen-Seite fehlt",
k = "Intern" },
Wert      = { s = "Ungültig",
k = "Parameter" }
}
local KategorieBeginn = "Wikipedia:Vorlagenfehler"
local Kategorien      = { Intern     = { s = "/Interner Fehler" },
Name       = { s = "/Parameterfehler" },
Parameter  = { s = "/Parameterfehler" },
Abruf      = { s = "/Abrufdatum" },
arXiv      = { s = "Parameter:arXiv" },
bibcode    = { s = "Parameter:bibcode" },
Datum      = { s = "Parameter:Datum" },
DNB        = { s = "Parameter:DNB" },
DOI        = { s = "Parameter:DOI" },
ISBN       = { s = "Parameter:ISBN" },
ISSN       = { s = "Parameter:ISSN" },
JSTOR      = { s = "Parameter:JSTOR" },
LCCN       = { s = "Parameter:LCCN" },
OCLC       = { s = "Parameter:OCLC" },
PMID       = { s = "Parameter:PMID" },
Sprachcode = { s = "Parameter:Sprachcode" },
URN        = { s = "Parameter:URN" },
ZDB        = { s = "Parameter:ZDB" }
}
local DocTypes =
{ CSV          = "CSV",
DJVU         = "DjVu",
FLASH        = "Flash",
GZIP         = "gzip",
MIDI         = "Musical Instrument Digital Interface",
MP3          = "MP3",
MPEG         = "MPEG",
MPEG4        = "MPEG-4",
MSEXCEL      = "MS Excel",
MSPOWERPOINT = "MS PowerPoint",
MSWORD       = "MS Word",
PDF          = "PDF",
POSTSCRIPT   = "PostScript",
RAR          = "RAR",
REAL         = "RealPlayer",
RTF          = "Rich Text Format",
WINDOWSMV    = "WMV",
ZIP          = "ZIP" }
local URLunwanted = {
"//arxiv%.org/abs/"                      = "arXiv",
"//adsabs%.harvard%.edu/"                = "bibcode",
"//portal%.dnb%.de/opac.+query=%d+X?$"   = "DNB",
"//doi%.org/10%."                        = "DOI",
"//dx%.doi%.org/10%."                    = "DOI",
"jstor%.org/pss/"                        = "JSTOR",
"jstor%.org/stable/"                     = "JSTOR",
"www%.worldcat%.org/oclc"                = "OCLC",
"ncbi%.nlm%.nih%.gov/pmc/articles/PMC%d" = "PMC",
"ncbi%.nlm%.nih%.gov/pmc/articles/pmc%d" = "PMC",
"ncbi%.nlm%.nih%.gov/pubmed/%d"          = "PMID",
"//nbn%-resolving%.de/urn:"              = "URN",
"//urn%.nb%.no/urn:nbn:"                 = "URN",
"//urn%.kb%.se/resolve%?urn="            = "URN" }
local Fehler    = false
local Fun       = { }
local KBytesMax = 100
local Resultat
local Silent = false
local Spacer
-- Allgemeine Hilfsfunktionen =======================================**
local function faced( ahead, after )
-- Zwei Elemente durch schmalen Abstand verbinden
-- Parameter:
--     ahead  -- string, mit erstem Element
--     after  -- string, mit zweitem Element
-- Rückgabewert: string
local e
if not Spacer then
e = mw.html.create( "span" )
:css( { display = "inline-block",
width   = ".2em" } )
:wikitext( " " )
Spacer = tostring( e )
end
return string.format( "%s%s%s", ahead, Spacer, after )
end -- faced()
local function facet( ahead, after )
-- Zwei Elemente durch schmalen umbruchgeschützten Abstand verbinden
-- Parameter:
--     ahead  -- string, mit erstem Element
--     after  -- string, mit zweitem Element
-- Rückgabewert: string
local e = mw.html.create( "span" )
:css( "white-space", "nowrap" )
:wikitext( faced( ahead, after ) )
return tostring( e )
end -- facet()
local function fading()
-- Ausblende-Modus feststellen
-- Rückgabewert: true, wenn im Ansicht-Modus (kein Bearbeitungsmodus)
if not Silent then
if not Zitation.frame then
Zitation.frame = mw.getCurrentFrame()
end
Silent = Zitation.frame:preprocess( "" )
end
return ( Silent ~= "" )
end -- fading()
local function faraway( assign, alien )
-- Sprache zuweisen
-- Parameter:
--     assign  -- mw.html-Element
--     alien   -- string mit Sprachcode, oder nil
if alien  and  alien ~= "de" then
assign:addClass( "lang" )
:attr( { dir  = "auto",
lang = alien } )
end
end -- faraway()
local function feed( area, access, about )
-- Zugriff auf Parameterkomponente
-- Parameter:
--     area    -- string, mit Name der Parametergruppe
--     access  -- string, mit Name der Komponente, oder nil
--     about   -- true, for returning original parameter name
-- Rückgabewert: Parameterwert, oder nil
local e, r
if not Zitation.o then
Zitation.o = { }
end
e = Zitation.o area 
if e then
if access then
r = e access 
if type( r ) == "table" then
if about then
r = r.s or "???????"
else
r = r.v
end
end
else
r = e
end
end
return r
end -- feed()
local function fehler( art, anzeige )
-- Ein Fehler ist aufgetreten
-- Parameter:
--     art      -- string mit Schlüsselwort zum Typ
--     anzeige  -- string mit Einzelheiten, oder nil
local t
if not Fehler then
Fehler = FehlerTypen
end
t = Fehler art 
if t then
if anzeige then
local s = mw.text.nowiki( anzeige )
if t.e then
t.e = string.format( "%s; %s", t.e, s )
else
t.e = s
end
end
if t.k then
local wk = Kategorien t.k 
if wk then
wk.e = true
else
Fehler.Intern.e     = "Wartungskat " .. 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 und Kategorien
-- Rückgabewert: string mit formatiertem Ergebnis
local r = ""
local s
local t = mw.title.getCurrentTitle()
if Fehler then
local sep = ""
for k, v in pairs( Fehler ) do
if v.e then
if v.s then
s = v.s .. ":"
else
s = ""
end
s = string.format( "*** %s %s", s, v.e )
if not v.k  and  fading() then
local e = mw.html.create( "span" )
e:wikitext( s )
:addClass( "Zitationsfehler Zitationswartung" )
:css( "display", "none" )
s = tostring( e )
end
r = string.format( "%s%s%s", r, sep, s )
sep = " "
end
end -- for k, v
end
if t.namespace == 0    or
( t.namespace == 4   and
t.text:sub( 1, 4 )  ==  "Lua/" ) then
Selbst = feed( "leise", "Vorlage" )  or  Selbst
for k, v in pairs( Kategorien ) do
if v.e then
if v.s:sub( 1, 1 ) == "/" then
s = Selbst
else
s = ""
end
r = string.format( "%sKategorie:%s/%s%s",
r, KategorieBeginn, s, v.s )
end
end -- for k, v
end
return r
end -- fehlerliste()
local function fein( abtrennung, anhang )
-- Ergänze Resultat um fertig formatierten Block
-- Parameter:
--     abtrennung  -- string mit vorangestelltem Separator
--     anhang      -- string mit Textelement
if anhang then
Resultat = string.format( "%s%s%s",
Resultat, abtrennung, anhang )
end
end -- fein()
local function figure( a )
-- Ist das eine Zahl aus arabischen oder römischen Ziffern?
return a:match( "^0-9./%-:IVX+$" )   or
a:match( "^C*LXVI+$" )   or
not mw.ustring.find( a, "%a" )
end -- figure()
local function figures( a )
-- Formatierte Aufzählung von Zahlen
local i = true
local r = a
local j, k, s, suffix
while i do
i, j, suffix = r:match( "^(%d+)%-(%d+)(.*)$" )
if i then
s = ""
else
s, i, j, suffix = r:match( "^(.*^0-9?)(%d+)%-(%d+)(.*)$" )
end
if i then
if tonumber( i )  datum then
r = false
end
end
end
return r
end -- future()
-- Spezielle Werte ==================================================**
local function Abrufdatum( abruf )
-- Gib behauptetes Abrufdatum zurück
-- Parameter:
--     abruf  -- table oder string, mit Datum
local o = abruf
local r
if type( o ) == "string" then
local DateTime = Zitation.fetch( "DateTime" )
o = DateTime( o )
end
if type( o ) == "table" then
if not future( o ) then
local s = o:format( "ISO" )
r = o:format( "T._Monat JJJJ", "de" )
if not o.dom or not o.month then
fehler( "Abruf", "Abrufdatum soll taggenau sein" )
elseif abruf ~= s then
fehler( "Format",
string.format( "'%s'=%s soll sein: %s",
feed( "www", "Abruf", true ),
abruf,
s ) )
fire( "Datum" )
end
end
end
if not r then
r = abruf
fehler( "Wert",
string.format( "'%s'=%s",
feed( "www", "Abruf", true ),
abruf ) )
fire( "Datum" )
end
return "abgerufen am " .. r
end -- Abrufdatum()
local function Herausgeber( apply, above, ahead )
-- Analysiere Herausgeber und formatiere ihn, mit Klammerzusatz
-- Parameter:
--     access  -- string mit Herausgeber
--     above   -- true: innerhalb Klammerebene
--     ahead   -- true: vorangestellt statt Klammerzusatz
-- Rückgabewerte:  -- string
local pat  = "^(^%(%+)%(%((%w+)%.?)%)%(.*)$"
local scan = apply
local seek = "|hg|hsg|hrsg|hrsgg|herausgeber|ed|eds|editor|editors|"
local story = ""
local r, s, start, sub, suffix
while true do
start, sub, s, suffix = mw.ustring.match( scan, pat )
if s then
if seek:find( string.format( "|%s|", s:lower() ) ) then
story = story .. mw.text.trim( start )
elseif suffix:sub( 1, 1 ) == "|"   and
sub:sub( 1, -1 ) == ")" then
story = string.format( "%s%s%s",
story, start, sub )
else
story = string.format( "%s%s%s",
story, start, s )
end
scan = suffix
else
break -- while
end
end -- while
r = story .. scan
sub, suffix = mw.ustring.match( r, "^(%w+%.?)%s*(.+)$" )
if sub == "Hg." then
-- (Verwechslungsgefahr bei abgekürztem Vornamen)
r = mw.text.trim( suffix )
elseif sub then
seek = "|hrsg|hrsgg|herausgegeben|"
if seek:find( string.format( "|%s|", sub:lower() ) ) then
r = mw.text.trim( suffix )
sub, suffix = mw.ustring.match( r, "^(vo?n?.?)%s*(.+)$" )
if sub == "von"  or  sub == "v." then
r = mw.text.trim( suffix )
end
end
end
if r ~= apply  or  r:match( "%)$" ) then
fehler( "Wert", "Herausgeber mit problematischem Zusatz" )
end
findbar( r, "Hrsg" )
if ahead then
r = "Hrsg.: " .. r
else
if above then
r = r .. " Hrsg."
else
r = r .. " (Hrsg.)"
end
end
return r
end -- Herausgeber()
local function Ortsname( analyse, area, access )
-- Analysiere einen Ortsnamen
-- Parameter:
--     analyse  -- string, mit Ortsname
--     area     -- string, mit Name der Parametergruppe
--     access   -- string, mit Name der Komponente
local s = analyse:gsub( "&#%x+;", "" )
if s:find( "%d%d%d%d" ) then
fehler( "Wert",
string.format( "'%s' %s (%s)",
feed( area, access, true ),
"mit verdächtiger Ziffernfolge",
"Jahreszahl, Postleitzahl" ) )
end
end -- Ortsname()
Fun.arXiv = function ( access )
-- Analysiere arXiv-ID und gib sie als formatierten Link zurück
local arXiv   = Zitation.fetch( "arXiv", "Vorlage:arXiv" )
local details = arXiv.fair( access )
if not details.legal then
fehler( "Wert", "'arXiv'" )
fire( "arXiv" )
end
arXiv.features( { showArticle = "arXiv" } )
return arXiv.format( details )
end -- Fun.arXiv()
Fun.bibcode = function ( access )
-- Analysiere bibcode-ID und gib sie als formatierten Link zurück
local bibcode = Zitation.fetch( "bibcode", "Vorlage:bibcode" )
local r       = bibcode.format{ access }
if not r:find( "//", 1, true ) then
fehler( "Wert",  "'bibcode' =" .. access )
fire( "bibcode" )
end
return r
end -- Fun.bibcode()
Fun.DOI = function ( access )
-- Analysiere DOI und gib sie als formatierten Link zurück
local URIutil = Zitation.fetch( "URIutil" )
local r       = URIutil.linkDOI( access )
local s       = "Digital Object Identifier"
if r then
r = string.format( "doi:%s", s, r )
else
r = string.format( "DOI:%s%s",
s,  access,  Zitation.fault( "(?!)", true ))
fehler( "Wert", "'DOI'" )
fire( "DOI" )
end
return r
end -- Fun.DOI()
Fun.DNB = function ( access )
-- Analysiere DNB und gib sie formatiert zurück
local URIutil = Zitation.fetch( "URIutil" )
local r
if URIutil.isDNBvalid( access ) then
r = URIutil.linkDNBopac( access, false, true, true )
else
local s = "Deutsche Nationalbibliothek"
fehler( "Wert", "'DNB'" )
fire( "DNB" )
r = string.format( "DNB %s%s",
s,  access,  Zitation.fault( "(?!)", true ))
end
return r
end -- Fun.DNB()
Fun.ISSN = function ( access, allow )
-- Analysiere ISSN und gib sie formatiert zurück
--     allow    -- true: permit invalid check digit
local URIutil = Zitation.fetch( "URIutil" )
if allow or URIutil.isISSNvalid( access ) then
r = URIutil.linkISSN( access, allow, true, true )
else
local s = "International Standard Serial Number"
fehler( "Wert", "'ISSN'" )
fire( "ISSN" )
r = string.format( "ISSN %s%s",
s,  access,  Zitation.fault( "(?!)", true ))
end
return r
end -- Fun.ISSN()
Fun.ISSNfalsch = function ( access )
-- Analysiere formal falsche ISSN und gib sie formatiert zurück
return Fun.ISSN( access, true )
end -- Fun.ISSNfalsch()
Fun.JSTOR = function ( access )
-- Analysiere JSTOR (stable) und gib sie formatiert zurück
-- i: Volume
local JSTOR = Zitation.fetch( "JSTOR" )
local r, URIutil
if access:find( "/", 1, true ) then
URIutil = Zitation.fetch( "URIutil" )
end
r = JSTOR.feasible( access, "stable", URIutil )
if r then
r = JSTOR.format( r, "stable", false, URIutil )
else
fehler( "Wert", "'JSTOR'" )
fire( "JSTOR" )
r = string.format( "JSTOR:%s%s",
access,  Zitation.fault( "(?!)", true ))
end
return r
end -- Fun.JSTOR()
Fun.LCCN = function ( access )
-- Analysiere LCCN und gib sie formatiert zurück
local URIutil = Zitation.fetch( "URIutil" )
local see = "Library of Congress Control Number"
local r = string.format( "LCCN ", see )
if URIutil.isLCCN( access ) then
r = r .. URIutil.linkLCCN( access, "-" )
else
fehler( "Wert", "'LCCN'" )
fire( "LCCN" )
r = string.format( "%s%s%s",
r,  access,  Zitation.fault( "(?!)", true ))
end
return r
end -- Fun.LCCN()
Fun.Lizenznummer = function ( access )
-- Gib DDR-Lizenznummer formatiert zurück
return "Lizenznummer " .. access
end -- Fun.Lizenznummer()
Fun.OCLC = function ( access )
-- Analysiere OCLC und gib sie formatiert zurück
local r
if access:match( "^1-90-9*$" ) then
r = framedTemplate( "OCLC", { access } )
else
fehler( "Wert", "'OCLC'" )
fire( "OCLC" )
r = string.format( "OCLC %s", access )
end
return r
end -- Fun.OCLC()
Fun.PMC = function ( access )
-- Analysiere PMC und gib sie formatiert zurück
local start, s = access:match( "^(%a%a%a)%s*(%d+)$" )
local r
if start and start:upper() == "PMC" then
fehler( "Wert", "'PMC' vor Nummer unerwünscht" )
else
s = access
end
if s:match( "^1-90-9*$" ) then
r = framedTemplate( "PMC", { s } )
else
fehler( "Wert", "'PMC'" )
fire( "PMID" )    -- Ja, PMID-Experte betreut auch PMC
r = string.format( "PMC %s", access )
end
return r
end -- Fun.PMC()
Fun.PMID = function ( access )
-- Analysiere PMID und gib sie formatiert zurück
if not access:match( "^1-90-9*$" ) then
fehler( "Wert", "'PMID'" )
fire( "PMID" )
end
return string.format( "PMID %s", access )
end -- Fun.PMID()
Fun.URN = function ( access )
-- Analysiere URN und gib sie formatiert zurück
local URIutil = Zitation.fetch( "URIutil" )
local r = URIutil.uriURN( "urn:" .. access )
if not r:find( "//", 1, true ) then
fehler( "Wert",  "'URN'=" .. access )
fire( "URN" )
end
return r
end -- Fun.URN()
Fun.ZDB = function ( access )
-- Analysiere ZDB und gib sie formatiert zurück
local URIutil = Zitation.fetch( "URIutil" )
if URIutil.isDNBvalid( access )  or
URIutil.isDNBvalid( access:gsub( "-", "" ) ) then
r = framedTemplate( "ZDB", { access:upper() } )
else
local s = "Zeitschriftendatenbank"
fehler( "Wert", "'ZDB'" )
fire( "ZDB" )
r = string.format( "ZDB %s%s",
s,  access, Zitation.fault( "(?!)", true ))
end
return r
end -- Fun.ZDB()
local function redundanz( analyse )
-- Prüfe Angabe auf Redundanz mit anderen Parametern
-- Parameter:
--     analyse  -- string
for k, v in pairs( URLunwanted ) do
if analyse:match( k ) then
local s = string.format( "%s '%s=' %s",
"Statt URL sollte etwas wie",
v,
"angegeben werden" )
fehler( "Konflikt", s )
end
end -- for k, v
if analyse:find( "title=\"ctx_ver=Z39.88-2004", 1 , true ) then
fehler( "Konflikt", "Verschachtelte Zitationsvorlagen" )
end
end -- redundanz()
local function bandNummer( area )
-- Formatiere Angaben von Band und/oder Nummer
-- Parameter:
--     area  -- string, mit Name der Parametergruppe print/serie
-- Rückgabewert: string mit Inhalt, oder nil
local sB = feed( area, "Band" )
local sN = feed( area, "Nummer" )
local lead, r
if sB then
sB = sB:gsub( " ", " " )
:gsub( "&#%x+;", " " )
:gsub( " ", " " )
:gsub( "%s%s+", " " )
if sB:sub( 1, 5 ) == "Band " then
sB   = sB:sub( 6 )
lead = true
elseif sB:sub( 1, 3 ) == "Bd." then
sB   = mw.text.trim( sB:sub( 4 ) )
lead = true
end
if figure( sB ) then
r = facet( "Band", sB )
else
if lead then
sB = "Band " .. sB
end
r = sB:gsub( "(Band) (%d+)", facet )
end
end
if sN then
lead = false
sN = sN:gsub( " ", " " )
:gsub( "&#%x+;", " " )
:gsub( " ", " " )
:gsub( "%s%s+", " " )
if sN:sub( 1, 7 ) == "Nummer " then
sN   = sN:sub( 8 )
lead = true
elseif sN:sub( 1, 3 ) == "Nr." then
sN   = mw.text.trim( sN:sub( 4 ) )
lead = true
end
if figure( sN ) then
sN = facet( "Nr.", sN )
else
if lead then
sN = "Nr. " .. sN
end
sN = sN:gsub( "(Nr%.) (%d+)", facet )
end
if r then
r = string.format( "%s, %s", r, sN )
else
r = sN
end
end
return r
end -- bandNummer()
local function Kapitel( a )
-- Formatiere Kapitelangabe
local r = a
if a:match( "^%d+$" ) then
r = facet( "Kap.", a )
end
return r
end -- Kapitel()
local function ArtikelNr( aN, aS )
-- Analysiere ArtikelNr
if aS then
fehler( "Konflikt", "Seitenzahl redundant wenn ArtikelNr" )
end
if not aN:match( "^%d+$" ) then
fehler( "Wert", "'ArtikelNr'=" .. aN )
end
end -- ArtikelNr()
local function Seiten( a )
-- Analysiere Seitenzahl und formatiere
local s, seiten = a:match( "^(%w+%.?)%s*(.+)$" )
local r
if s then
local seek = "|s.|ss.|seite|seiten|page|pages|p.|pp.|"
if seek:find( string.format( "|%s|", s:lower() ) ) then
fehler( "Wert", "Seitenzahl mit unnötigem Zusatz" )
seiten = mw.text.trim( seiten )
else
seiten = a
end
else
seiten = a
end
if #seiten > 50 then
-- URL? Google-Buch?
local shrink = string.format( "%%-0-9,;/ f%%.%s",
mw.ustring.char( 8211 ) )
s = mw.ustring.gsub( seiten, shrink, "" )
if #s > 10 then
fehler( "Wert", "Seitenzahl unerklärlich lang" )
r = a
end
end
if not r then
r = facet( "S.",  figures( seiten ) ):gsub( "%.$",
"." )
end
return r
end -- Seiten()
local function Spalten( a )
-- Analysiere Spaltenangabe und formatiere
local s, sp = a:match( "^(%w+%.?)%s*(.+)$" )
if s then
local seek = "|sp.|spalte|spalten|"
if seek:find( string.format( "|%s|", s:lower() ) ) then
fehler( "Wert", "Spaltenangabe mit unnötigem Zusatz" )
sp = mw.text.trim( sp )
else
sp = a
end
else
sp = a
end
return  facet( "Sp.", figures( sp ) ):gsub( "%.$",
"." )
end -- Spalten()
local function Werktitel( a, amend, alien, abschluss )
-- Formatiere einen Werktitel, das Sammelwerk, ggf. Reihe
-- Parameter:
--     a          -- string
--     amend      -- string mit Ergänzung, oder nil
--     alien      -- string mit Sprachcode, oder nil
--     abschluss  -- true: Satzendezeichen sicherstellen
-- Rückgabewert: string mit formatiertem Werktitel
local Text  = Zitation.fetch( "Text" )
local cite = mw.html.create( "cite" )
local sep
local r
cite:css( "font-style", "italic" )
:wikitext( Text.uprightNonlatin( a ) )
faraway( cite, alien )
r = tostring( cite )
if amend then
local s
if Text.sentenceTerminated( a ) then
sep = ""
else
sep = "."
end
r = string.format( "%s%s %s", r, sep, amend )
end
if abschluss  and
( ( not amend  and  not Text.sentenceTerminated( a ) )
or   ( amend  and  not Text.sentenceTerminated( amend ) ) ) then
r = r .. "."
end
return r
end -- Werktitel()
-- Einzelblöcke der Darstellung =====================================**
local function resourceMeta( anfang )
-- Ergänze Resultat um für einen Online-Abruf wichtigen Informationen
--     anfang  -- boolean
--                * true   -- runde Klammern
--                            um .Format und .KBytes gesetzt
--                * false  -- eckige Klammern
--                            um .Format und .KBytes und .Abruf
-- Rückgabewert: string mit führendem " " und Inhalt, oder ""
local r = ""
if feed( "www" ) then
local sURL     = feed( "www", "URL" )
local sWeblink = feed( "www", "Weblink" )
local some     = ( sURL or sWeblink )
local sAbruf   = feed( "www", "Abruf" )
local sFormat  = feed( "www", "Format" )
local sKBytes  = feed( "www", "KBytes" )
if some then
local sep = ""
some = some:lower() .. " "
if sFormat then
local s = sFormat:upper()
if s ~= "HTML" then
if s:find( "PDF%-?" ) then
r = "pdf"
else
r = sFormat
end
end
elseif some:find( "%Wpdf%W" ) then
r = "pdf"
end
if r:lower() == "pdf"  and
sWeblink  and
some:find( " .*pdf" ) then
r = ""
end
if r == "" then
sKBytes = false
else
local docTypes = mw.text.split( r:upper(), " " )
local s
r   = ""
sep = ""
for i = 1, #docTypes do
s   = docTypes i 
r   = string.format( "%s%s%s",
r,  sep,  DocTypes s  or s )
sep = " "
end -- for i
sep = "; "
end
if sKBytes then
local scan  = "^(%d+,%.?%d*)%s*(%a*)$"
local large = sKBytes:find( "sic!", 3, true )
local lot, size, suffix
sKBytes = sKBytes:gsub( " ", " " )
:gsub( " ", " " )
:gsub( "&#x0*aA0;", " " )
:gsub( " ", " " )
:gsub( "&#x0*202fF;", " " )
:gsub( " ", " " )
if large then
sKBytes = sKBytes:gsub( "%s*%sic!%%s*$", "" )
end
size, suffix = sKBytes:match( scan )
if size then
local n
size = size:gsub( "%.", "" )
if size:find( "," ) then
n    = tonumber( size:gsub( ",", "." ), 10 )
size = string.format( "%1.1d", n )
else
n = tonumber( size )
end
if suffix then
if suffix == "" then
suffix = false
else
suffix = suffix:lower()
if suffix:match( "^mi?b%l*$" ) then
n      = n * 1000
suffix = false
elseif suffix:match( "^ki?b%l*$" ) then
suffix = false
end
end
end
if suffix then
fehler( "Wert", "Byte-Einheit nicht erkannt" )
else
if n > 1000 then
n      = math.ceil( n * 0.01 ) * 0.1
size   = string.format( "%.1f", n )
suffix = "MB"
lot    = ( n > KBytesMax )
else
suffix = "kB"
end
end
sKBytes = facet( size:gsub( "%.", "," ), suffix )
if lot then
sKBytes = string.format( "%s", sKBytes )
if not large then
fehler( "Wert", "zu viele MegaBytes" )
end
end
else
fehler( "Wert", "KiloByte-Zahl nicht erkannt" )
end
r = string.format( "%s%s%s", r, sep, sKBytes )
if large and not lot then
fehler( "Wert", "Fehlplatziertes sic!" )
end
sep = "; "
end
if not anfang and sAbruf and sWeblink then
r = string.format( "%s%s%s",
r, sep, Abrufdatum( sAbruf ) )
end
if r ~= "" then
if anfang then
sep = " (%s)"
else
sep = " %s"
end
r = string.format( sep, r )
end
redundanz( some )
elseif sFormat or sKBytes or sAbruf then
local s = feed( "bas", "Titel" )
if not s  or  not s:find( "//" ) then
fehler( "Problem",
"Dateiformat/Größe/Abruf nur wenn Weblink" )
end
end
end
return r
end -- resourceMeta()
local function autorHrsg()
-- Ergänze Resultat um Personen zu Beginn der Zitation
local sAutor = feed( "bas", "Autor" )
local sHrsg  = feed( "bas", "Hrsg" )
local sTyp   = feed( "leise", "Typ" )
local lead
if sTyp  and  sTyp ~= "wl" then
fehler( "Wert",
"'Typ' zurzeit nur 'Typ=wl' (Werkliste) unterstützt" )
r = "wl"
end
if sHrsg then
lead = ( not feed( "bas", "Werk" ) )
findbar( sHrsg, "Hrsg" )
end
if sAutor or lead then
local list = false
if sAutor then
sAutor = sAutor:gsub( "^#", "#" ) -- nick, hashtag
:gsub( "^%*", "*" )
if sTyp ~= "wl" then
fein( "", sAutor )
list = true
end
if type( sAutor ) == "table" then
sAutor = Zitation.citePerson( sAutor, false )
end
findbar( sAutor, "Autor" )
if sHrsg  and  not feed( "bas", "Titel" ) then
fehler( "Konflikt",
"Gleichzeitig 'Autor' und 'Hrsg' nur wenn auch 'Titel'" )
end
else
fein( "",  Herausgeber( sHrsg ) )
list = true
end
if list then
fein( ": ", "" )
end
end
end -- autorHrsg()
local function erstAusgabe()
-- Erstausgabe
-- Rückgabewert: string
local sJahr   = feed( "ed1", "Jahr" )
local sOrt    = feed( "ed1", "Ort" )
local sVerlag = feed( "ed1", "Verlag" )
local r       = "Erstausgabe: "
local sep
if sVerlag then
r   = r .. sVerlag
sep = ","
if feed( "bas", "Verlag" ) == sVerlag then
fehler( "Konflikt",
string.format( "'%s' hat gleichen Wert wie '%s'",
feed( "ed1", "Verlag", true ),
feed( "bas", "Verlag", true ) ) )
end
else
sep = ""
end
if sOrt then
r = string.format( "%s%s %s", r, sep, sOrt )
Ortsname( sOrt, "ed1", "Ort" )
sep = " "
-- bas.Verlag und ed1.Verlag dürfen in derselben Stadt sein
end
if sJahr then
local jahr
if sJahr:match( "^%d%d%d%d$" ) then
if not future( sJahr ) then
jahr = tonumber( sJahr )
end
end
if jahr then
local datum = feed( "bas", "Datum" )
r = string.format( "%s%s %s", r, sep, sJahr )
if type( datum ) == "table"   and
datum.year   and   datum.year %s", sprache )
--              elseif sprache:match( "^%l.+ ,;/" ) then
--                  fehler( "Wert",
--                          "Original-Sprachcode seltsam: " .. sprache )
end
else
sprache = "Originaltitel"
end
r = string.format( "%s: %s", sprache, r )
if sTranslator then
r = string.format( "%s Übersetzt von %s",
r, sTranslator )
end
elseif not sTranslator then
fehler( "Pflicht", "Originaltitel fehlt" )
end
end
return r
end -- originalPublikation()
local function titel()
-- Ergänze Resultat um Titel
local sTitel = feed( "bas", "Titel" )
local sWerk  = feed( "bas", "Werk" )
if sTitel then
local stop = ""
local sReihe    = feed( "serie", "Reihe" )
local sTitelErg = feed( "bas",   "TitelErg" )
local sURL      = feed( "www",   "URL" )
local s = Werktitel( sTitel,
false,
feed( "bas", "Sprache" ),
sWerk  or  not sReihe  or  sTitelErg )
local Text
if sURL then
local URLutil = Zitation.fetch( "URLutil" )
if URLutil.isResourceURL( sURL ) then
s    = s:gsub( "%", "" )
:gsub( "%", "" )
sURL = sURL:gsub( "%", "%5B" )
:gsub( "%", "%5D" )
s    = string.format( "%s %s%s",
sURL, s, resourceMeta( true ) )
else
fehler( "Wert", "URL" )
end
end
if sTitelErg then
Text = Zitation.fetch( "Text" )
if ( sWerk  or  not sReihe )   and
not Text.sentenceTerminated( sTitelErg ) then
stop = "."
end
s = string.format( "%s %s%s", s, sTitelErg, stop )
end
fein( "", s )
if not sWerk then
local sAutor = feed( "bas", "Autor" )
local sHrsg  = feed( "bas", "Hrsg" )
if sAutor and sHrsg then
Text = Zitation.fetch( "Text" )
if stop == "" then
local strip = Resultat:gsub( "$", "" )
if not Text.sentenceTerminated( strip ) then
stop = "."
end
elseif sTitelErg then
stop = ""
end
stop = stop .. " "
s    = Herausgeber( sHrsg, false, true )
if not ( sReihe  or
Text.sentenceTerminated( s ) ) then
s = s .. "."
end
fein( stop, s )
end
end
else
if sWerk then
fehler( "Pflicht", "Kein 'Titel'" )
else
fehler( "Pflicht", "Weder 'Titel' noch sonstiges Werk" )
end
end
end -- titel()
local function werk()
-- Ergänze Resultat um Sammelwerk usw.
local sWerk = feed( "bas", "Werk" )
if sWerk then
local start = " In: "
local sHrsg = feed( "bas", "Hrsg" )
local s     = Werktitel( sWerk,
feed( "bas", "WerkErg" ),
feed( "bas", "Sprache" ),
not feed( "serie", "Reihe" ) )
if sHrsg then
s = string.format( "%s: %s",  Herausgeber( sHrsg ),  s )
end
if Resultat == "" then
start = "In: "
end
fein( start, s )
end
end -- werk()
local function auflage()
-- Ergänze Resultat um Auflage
local sAuflage = feed( "print", "Auflage" )
if sAuflage then
local s = sAuflage:gsub( "Auflage$",   "Auflage")
:gsub( "eEd%.?$",  "ed." )
:gsub( "eEdition", "ed." )
:gsub( "éÉd%.?$",  "éd." )
:gsub( "éÉdition", "éd." )
if s:match( "^%d+$" ) then
s = s .. "."
end
if not ( s:find( "Aufl", 1, true )  or
s:find( "eéd" ) ) then
s = s .. " Auflage"
end
if not s:match( "%.$" ) then
s = s .. "."
end
fein( " ", s )
end
end -- auflage()
local function reihe()
-- Ergänze Resultat um Angaben zur Reihe
if feed( "serie" ) then
local sReihe = feed( "serie", "Reihe" )
if sReihe then
local sBN   = bandNummer( "serie" )
local sHrsg = feed( "serie", "Hrsg" )
local s     = Werktitel( sReihe,
false,
feed( "bas", "Sprache" ),
sBN )
if sHrsg then
s = string.format( "%s: %s",
Herausgeber( sHrsg, true ),  s )
end
if sBN then
s = string.format( "%s %s", s, sBN )
end
fein( " ",  string.format( "(= %s).", s ) )
else
local scream
local flop = function ( au )
if feed( "serie", au ) then
local s = feed( "serie", au, true )
if scream then
scream = scream .. ", "
else
scream = ""
end
scream = string.format( "%s'%s'",
scream, s )
end
end -- flop()
flop( "Hrsg" )
flop( "Band" )
flop( "Nummer" )
if scream then
-- Muss in dieser Konstellation eigentlich immer sein
fehler( "Pflicht",
scream .. " nur wenn Reihe angegeben" )
end
end
end
end -- reihe()
local function bibliografischeAngaben()
-- Ermittle die Aufzählung bibliografische Angaben
-- Rückgabewert: string mit Inhalt, oder false
local r       = ""
local sep     = ""
local datum   = feed( "bas", "Datum" )
local sVerlag = feed( "bas", "Verlag" )
local s, sOrt
if feed( "print" ) then
sOrt = feed( "print", "Ort" )
if sOrt  and
( feed( "id", "ISSN" )  or  feed( "id", "ZDB" ) ) then
sOrt = false
end
s = bandNummer( "print" )
if s then
r = s
if s:find( "%.$" ) then
sep = " "
elseif sVerlag or sOrt then
sep = ". "
else
sep = ", "
end
end
end
if sVerlag then
r = string.format( "%s%s%s", r, sep, sVerlag )
sep = ", "
end
if sOrt then
s = sOrt:gsub( ",/; +$", "" )
r = string.format( "%s%s%s", r, sep, s )
if s ~= sOrt then
Zitation.fill( "print", "Ort", s )
end
Ortsname( sOrt, "print", "Ort" )
sep = ", "
end
if datum then
local o = datum
if type( datum ) == "string" then
local DateTime = Zitation.fetch( "DateTime" )
o = DateTime( datum )
end
if type( o ) == "table"  and  o.year then
Zitation.fill( "bas", "Datum", o )
if future( o )   or
( o.zone  and  not o.hour ) then
o = false
elseif feed( "id", "ISBN" ) then
s = tostring( o.year )
elseif feed( "www", "URL" ) then
s = o:format( "T._Monat JJJJ hh:mm:ss Zone" )
else
s = o:format( "T._Monat JJJJ" )
end
else
o = false
end
if not o then
if type( datum ) == "string" then
--  s = "Datum: " .. datum    -- LEGACY
s = datum
else
s = "Datum??"
end
fehler( "Wert", s )
fire( "Datum" )
end
if sOrt then
sep = " "
end
r = string.format( "%s%s%s", r, sep, s )
sep = ", "
end
if feed( "id" ) then
local lazy        = false    -- gültige ISBN bekannt
local sID         = feed( "id", "ID" )
local sISBN       = feed( "id", "ISBN" )
local sISBNfalsch = feed( "id", "ISBNfalsch" )
local sISBNdefekt = feed( "id", "ISBNdefekt" )
local fiddler     =
function( at )
local s = feed( "id", at )
if s then
if lazy  and
not  ( at == "ISSN"  or
at == "ISSNfalsch" ) then
s = "redundant, da ISBN gegeben"
s = string.format( "'%s' %s",
feed( "id", at, true ),
s )
fehler( "Konflikt", s )
else
s   = Fun at ( s )
r   = string.format( "%s%s%s",
r, sep, s )
sep = ", "
end
end
end
if sISBN and sISBNfalsch then
s = string.format( "'%s' und '%s' %s",
feed( "id", "ISBN", true ),
feed( "id", "ISBNfalsch", true ),
"nicht gleichzeitig angeben" )
fehler( "Konflikt", s )
elseif sISBN or sISBNfalsch then
local mode
if sISBNfalsch then
mode = -1
end
s, lazy = Zitation.ISBN( sISBN or sISBNfalsch,  mode )
r = string.format( "%s%s%s", r, sep, s )
sep = ", "
end
if sISBNdefekt then
s = Zitation.ISBN( sISBNdefekt, #sISBNdefekt )
r = string.format( "%s%s%s", r, sep, s )
sep = ", "
end
fiddler( "ISSN" )
fiddler( "ISSNfalsch" )
fiddler( "DNB" )
fiddler( "LCCN" )
fiddler( "Lizenznummer" )
fiddler( "OCLC" )
fiddler( "ZDB" )
if sID then
r = string.format( "%s%s%s", r, sep, sID )
sep = ", "
redundanz( sID )
end
end
if feed( "fragment" ) then
local sArtikelNr  = feed( "fragment", "ArtikelNr" )
local sFundstelle = feed( "fragment", "Fundstelle" )
local sKapitel    = feed( "fragment", "Kapitel" )
local sSeiten     = feed( "fragment", "Seiten" )
local sSpalten    = feed( "fragment", "Spalten" )
if sKapitel then
r = string.format( "%s%s%s", r, sep, Kapitel( sKapitel ) )
sep = ", "
end
if sSeiten then
r = string.format( "%s%s%s", r, sep, Seiten( sSeiten ) )
sep = ", "
end
if sSpalten then
r = string.format( "%s%s%s", r, sep, Spalten( sSpalten ) )
sep = ", "
end
if sArtikelNr then
ArtikelNr( sArtikelNr, sSeiten )
r = string.format( "%s%s%s", r, sep, sArtikelNr )
sep = ", "
end
if sFundstelle then
r = string.format( "%s%s%s",
r,
sep, "white-space:nowrap", sFundstelle )
sep = ", "
end
end
if feed( "id" ) then
local docCodes   = { "DOI",
"PMID",
"PMC",
"arXiv",
"bibcode",
"JSTOR",
"URN" }
local sign
for i = 1, #docCodes do
s    = docCodes i 
sign = feed( "id", s )
if sign then
r   = string.format( "%s%s%s", r, sep, Fun s ( sign ) )
sep = ", "
end
end -- for i
end
if r == "" then
r = false
end
return r
end -- bibliografischeAngaben()
local function klammerInhalt()
-- Inhalt der Klammer am Ende der bibliografischen Angaben
-- Rückgabewert: string mit Inhalt, oder false
local r          = ""
local sep        = ""
local sKommentar = feed( "bas",   "Kommentar" )
local sOrig      = originalPublikation()
local sprache    = feed( "bas",   "Sprache" )
local sUmfang    = feed( "print", "Umfang" )
if sprache  and  sprache ~= "de" then
local Multilingual = Zitation.fetch( "Multilingual" )
sprache = Multilingual.format( sprache, "de", "m",
false, false,
Zitation.frame,
" ", ", " )
r       = string.format( "%s%s%s", r, sep, sprache )
sep     = ", "
end
if sUmfang then
if not mw.ustring.find( sUmfang, "%a" ) then
-- "14, 234"
sUmfang = string.format( "%s S.", sUmfang )
end
r   = string.format( "%s%s%s", r, sep, sUmfang )
sep = ", "
end
local sanitize = feed( "www", "Weblink" )
if sanitize and sanitize:find( "InternetArchiveBot", 1, true ) then
-- 2018-12-04
mw.addWarning( "Unerlaubte Bot-Aktion " ..
"Informationsverlust vorheriger Angaben. "
.. "Unzulässige Formatierung. "
.. sanitize )
fein( "", "Kategorie:Wikipedia:InternetArchiveBot-Fehler")
Zitation.o.www = false
-- Wiederholt ZR-widrig den Titel der Website u. a.  171587445/183321268
end
if feed( "www" ) then
local sWeblink = feed( "www", "Weblink" )
if sWeblink then
local WLink = Zitation.fetch( "WLink" )
local show  = WLink.getWeblink( sWeblink )
local spec  = resourceMeta( false )
show = show:gsub( " www%d*%.", " " )
r    = string.format( "%s%s%s%s",
r, sep, show, spec )
if spec == "" then
sep = " – "
else
sep = " "
end
if sWeblink:find( "", 1, true )   or
sWeblink:find( "class=\"cite\"", 1, true ) then
fehler( "Konflikt",
"Zitationsvorlage rekursiv eingebunden" )
fire( "Parameter" )
-- Langfristig wirkungslos; greift nur vorübergehend
-- wenn IQ noch reine Vorlage,
-- oder cite als reine Vorlage.
-- Nach vollständiger Umsetzung
-- sperrt sich aber das System,
-- weil Modul:Zitation
-- dann rekursiv aufgerufen werden würde.
end
elseif feed( "www", "URL" ) then
local sAbruf = feed( "www", "Abruf" )
if sAbruf then
r   = string.format( "%s%s%s",
r, sep, Abrufdatum( sAbruf ) )
sep = ", "
end
else
local s = feed( "bas", "Titel" )
if not s  or  not s:find( "//" ) then
fehler( "Problem",
"Dateiformat/Größe/Abruf nur bei externem Link" )
end
end
end
if sOrig then
r = string.format( "%s%s%s", r, sep, sOrig )
if feed( "orig", "Translator" ) then
sep = ", "
else
sep = " "
end
end
if feed( "ed1" ) then
r   = string.format( "%s%s%s", r, sep, erstAusgabe() )
sep = ", "
end
if sKommentar then
r = string.format( "%s%s%s", r, sep, sKommentar )
redundanz( sKommentar )
end
if r == "" then
r = false
end
return r
end -- klammerInhalt()
local function endBlock()
-- Ergänze Resultat um bibliografische Angaben, Klammer sowie Zitat.
-- Komma-getrennte Aufzählung, die mit Punkt abgeschlossen wird,
-- oder Zitat wird nachgestellt.
local sZitat = feed( "bas", "Zitat" )
local sep    = ""
local s      = bibliografischeAngaben()
if s then
fein( " ", s )
if not s:match( "%.$" ) then
sep = "."
end
end
s = klammerInhalt()
if s then
if Resultat:find( "%)$" ) then
-- Irgendwas zuvor endet auf eine runde Klammer.
sep = " – ("
else
sep = " ("
end
fein( sep,  s .. ")" )
sep = "."
end
if sep ~= "" then
-- Aufzählung enthält zumindest ein Element
if sZitat then
fein( ":", "" )
elseif not Resultat:match( "%.$" ) then
fein( ".", "" )
end
end
if sZitat then
local sprache = feed( "bas", "Sprache" )
local Text    = Zitation.fetch( "Text" )
local story   = Text.quoteUnquoted( sZitat, sprache )
if sprache  and  sprache ~= "de" then
local q = mw.html.create( "span" )
faraway( q, sprache )
q:wikitext( story )
story = tostring( q )
end
fein( " ", story )
end
end -- endBlock()
local function coins()
-- Ergänze Resultat um COinS, wenn gewünscht
local COinS = feed( "coins" )
if COinS then
local std = "book"
local pars
if type( COinS ) == "table" then
pars = COinS
elseif feed( "bas" ) then
local datum    = feed( "bas",      "Datum" )
local sAutor   = feed( "bas",      "Autor" )
local sKapitel = feed( "fragment", "Kapitel" )
local sTitel   = feed( "bas",      "Titel" )
local sWerk    = feed( "bas",      "Werk" )
local stick
pars = { }
if sWerk then
if feed( "print",    "Nummer" )  or
feed( "id",       "ISSN" )  or
feed( "id",       "ISSNfalsch" )  or
feed( "id",       "ZDB" )  or
feed( "fragment", "ArtikelNr" ) then
pars.genre  = "journal"
pars.jtitle = sWerk
std         = "journal"
else
pars.genre  = "book"
pars.btitle = sWerk
end
pars.atitle = sTitel
elseif sKapitel then
pars.genre  = "bookitem"
pars.btitle = sTitel
pars.atitle = sKapitel
else
pars.genre  = "book"
pars.btitle = sTitel
end
if type( datum ) == "table" then
pars.date = datum:format( "ISO" )
end
if sAutor then
if type( sAutor ) == "table" then
stick = Zitation.citePerson( sAutor, true )
else
pars.au = flat( sAutor, 3, true )
end
end
pars.pub   = feed( "bas",      "Verlag" )
pars.pages = feed( "fragment", "Seiten" )
if feed( "id" ) then
pars.isbn = feed( "id", "ISBN" )  or
feed( "id", "ISBNfalsch" )
feed( "id", "ISBNfalsch" )
pars.issn = feed( "id", "ISSN" )  or
feed( "id", "ISSNfalsch" )
pars.oclc = feed( "id", "OCLC" )
pars.doi  = feed( "id", "DOI" )
pars.pmc  = feed( "id", "PMC" )
pars.pmid = feed( "id", "PMID" )
end
if feed( "print" ) then
pars.edition = feed( "print", "Auflage" )
pars.issue   = feed( "print", "Nummer" )
pars.place   = feed( "print", "Ort" )
pars.volume  = feed( "print", "Band" )
end
pars.series = feed( "serie", "Reihe" )
end
if pars then
fein( "",  Zitation.COinS( pars, false, stick ),  std )
end
end
end -- coins()
-- Exportierte Funktionen ===========================================**
Zitation.failure = function ( alert, always )
-- Ausgabe von Fehlern mit class=error
-- Parameter:
--     alert   -- string, mit Fehlerliste, oder nil
--     always  -- do not hide: boolean, or nil
-- Rückgabewert: string, ggf. mit Fehlermeldung
local r
if alert then
local TemplUtl = Zitation.fetch( "TemplUtl" )
local light    = feed( "leise", "leiser" )  and  not always
local self     = feed( "leise", "Vorlage" )  or  Selbst
r = string.format( "Fehler in %s – %s",
self, alert )
r = TemplUtl.failure( r,  not light, false, Zitation.frame )
else
r = ""
end
return r
end -- Zitation.failure()
Zitation.fault = function ( a, always )
-- Formatiere Fehler als teils ausgeblendet
-- Parameter:
--     a       -- string, mit Fehlermeldung
--     always  -- true, wenn nicht zu unterdrücken
-- Rückgabewert:
--     string, ggf. mit umschließendem HTML-Element
local r
if not always  and
feed( "leise", "leiser" )  and
mw.site.server == "//de.wikipedia.org" then
if fading() then
local e = mw.html.create( "span" )
e:addClass( "Zitationsfehler Zitationswartung" )
:css( "display", "none" )
:wikitext( a )
r = tostring( e )
end
end
return r or a
end -- Zitation.fault()
Zitation.fetch = function ( assigned, acquire )
-- Binde Modul ein
-- Parameter:
--     assigned  -- string mit Name
--                  "arXiv"
--                  "bibcode"
--                  "DateTime"
--                  "JSTOR"
--                  "Multilingual"
--                  "TemplUtl"
--                  "Text"
--                  "URIutil"
--                  "URLutil"
--                  "WLink"
--     acquire   -- string mit abweichendem Modulnamen, oder false
-- Rückgabewert: table des Moduls
-- error: Modul nicht gefunden
local r
if Zitation.extern then
r = Zitation.extern assigned 
else
Zitation.extern = { }
end
if not r then
local s = assigned
local lucky, g
if acquire then
s = acquire
end
lucky, g = pcall( require, "Module:" .. s )
if type( g ) == "table" then
r = g assigned ()
Zitation.extern assigned  = r
else
fehler( "Modul", g )
error( string.format( "Zitation.fetch(%s) %s", s, g ) )
end
end
return r
end -- Zitation.fetch()
Zitation.figure = function ( adjust )
-- Bilde Zahlenwert
-- Parameter:
--     adjust  -- Wert beliebigen Typs
-- Rückgabewert:
--     Numerischer Wert, notfalls 0
local r
local s = type( adjust )
if s == "string" then
r = tonumber( adjust ) or 0
elseif s == "number" then
r = adjust
else
r = 0
end
return r
end -- Zitation.figure()
Zitation.fill = function ( area, access, assign, alias )
-- Parameterkomponente zuweisen
-- Parameter:
--     area    -- string, mit Name der Parametergruppe
--     access  -- string, mit Name der Komponente
--     assign  -- Parameterwert
--     alias   -- string, mit Name des Benutzerparameters, oder nil
if not Zitation.o then
Zitation.o = { }
end
if type( Zitation.o area  ) ~= "table" then
Zitation.o area  = { }
end
Zitation.o area  access  = { s = alias    or
string.format( "%s.%s",
area, access ),
v = assign }
end -- Zitation.fill()
Zitation.filler = function ( args, assign )
-- Parameterkomponenten zuweisen
-- Parameter:
--     args    -- Zfilter.object,
--                mit Zuweisungen nach Vorlagenparametername
--     assign  -- table, mit Transformation in neutrales Datenmodell
local g, r, value
if not Zitation.o then
Zitation.o = { }
end
for k, v in pairs( assign ) do
value = args{ k }
if value then
g = v 1 
if not Zitation.o g  then
Zitation.o g  = { }
end
Zitation.o g  v 2   = value
end
end -- for k, v
end -- Zitation.filler()
Zitation.filter = function ( args, allowed )
-- Analysiere Argumentenliste und gleiche mit erlaubten Namen ab
-- Parameter:
--     args     -- table, mit aktuellen Werten
--     allowed  -- table, mit erlaubten Namen, zugewiesen:
--                        true   -- Nur diese Namensvariante bekannt
--                        table  -- Namensvariationen
--                                  Jeder Wert:
--                                  true   -- unerwünscht, Meldung
--                                  table  -- Details
--                                  table  -- low=true: Keine Meldung
-- Rückgabewerte:
--     table, mit gefilterten Werten, nach Parametername
--            Zfilter object
--            Jede Komponente:
--                 index-Zugriff:
--                     string, mit Parameterwert, kein leerer string
--                 get-Zugriff:
--                     table, mit
--                            s=Orginal-Parametername
--                            v=Parameterwert, nicht leer
local signatur = "__Zfilter"
local meta     = { }
local r        = {  signatur  = { } }
local discard  = false
local doubled  = false
local un       = false
local d, lapsus
meta.__call     = function ( self, arglist )
-- Antwort auf:  Tabelle{ ... }
return self signatur  arglist 1  
end
meta.__index    = function ( self, access )
-- Antwort auf:  ... = Tabellex
local e = self signatur  access 
if type( e ) == "table" then
e = e.v
end
return e
end
meta.__newindex = function ( self, access, assign )
-- Antwort auf:  Tabellex = ...
local put = assign
if assign  and
( type( assign ) ~= "table"   or
not assign.v ) then
put = { s=access, v=assign }
end
self signatur  access  = put
return
end
setmetatable( r, meta )
for s, v in pairs( args ) do
d = allowed s 
if d then
lapsus = false
if type( d ) == "table" then
for dk, dv in pairs( d ) do
if args dk  then
if not doubled then
doubled = { }
end
if not doubled dk  then
doubled tostring( s )  = dk
end
end
end
else
d = false
end
elseif type( s ) == "string" then
if d == false then
if not discard then
discard = { }
end
table.insert( discard, s )
else
lapsus = true
end
else
lapsus = true
if v then
if mw.text.trim( v ) == "" then
fehler( "Format", "Pipe '|' zu viel" )
end
v = false
end
s = tostring( s )
end
if lapsus then
if not un then
un = { }
end
un s  = true
end
if v == "" then
v = false
end
if v then
r s  = v
if v:find( "", 1, true )   and
type( s ) == "string" then
if not v:find( "InternetArchiveBot", 1, true ) then
fehler( "Wert",
string.format( "'%s' mit Wikisyntax", s ) )
end
end
end
end -- for s, v
if un then
local down      = { }
local scream    = false
local undesired = false
local unknown   = false
local light, s, sa
for k, v in pairs( allowed ) do
s = mw.ustring.lower( k )
down s  = { standard=k }
if type( v ) == "table" then
for ka, va in pairs( v ) do
sa = mw.ustring.lower( ka )
if type( va ) == "table" then
va.standard = k
else
va = { standard=k }
end
down sa  = va
end
end
end -- for k, v
for k, v in pairs( un ) do
if type( k ) == "string" then
s = mw.ustring.lower( k )
d = down s 
else
d = false
end
if d then
if type( d ) == "table" then
light = d.low
s     = d.standard
else
light = false
end
if r s  then
if not doubled then
doubled = { }
end
if not doubled s  then
doubled k  = s
end
else
r s  = r{ k }
r k  = nil
if not light then
if not undesired then
undesired = { }
end
undesired k  = s
end
end
else
if not unknown then
unknown = { }
end
unknown k  = true
end
end -- for k, v
if unknown then
down = { }
for k, v in pairs( allowed ) do
if type( v ) == "table" then
sa = mw.ustring.lower( k )
for ka, va in pairs( v ) do
sa = mw.ustring.lower( ka )
if type( va ) == "table" then
va.standard = k
else
va = { standard=k }
end
down sa  = va
end
end
end -- for k, v
for k, v in pairs( unknown ) do
if type( k ) == "string" then
s = mw.ustring.lower( k )
d = down s 
if d then
if type( d ) == "table" then
light = d.low
else
light = false
end
s = d.standard
if r s  then
if not doubled then
doubled = { }
end
doubled k  = s
else
r s  = r{ k }
r k  = nil
if not light then
if not undesired then
undesired = { }
end
undesired k  = d.standard
end
end
else
if scream then
scream = scream .. ", "
else
scream = "Unbekannte Parameter: "
end
scream = scream .. k
end
end
end -- for k, v
fehler( "Konflikt", scream )
scream = false
end
if undesired then
for k, v in pairs( undesired ) do
if scream then
scream = scream .. ", "
else
scream = ""
end
scream = string.format( "%s '%s' ist '%s'",
scream, k, v )
end -- for k, v
fehler( "Name", scream )
scream = false
end
end
if doubled then
for k, v in pairs( doubled ) do
if scream then
scream = scream .. ","
else
scream = "Parameterwerte gedoppelt: "
end
scream = string.format( "%s '%s' ./. '%s'",
scream, k, v )
end -- for k, v
fehler( "Konflikt", scream )
scream = false
end
if discard then
for k, v in pairs( discard ) do
fehler( "Entfernen",  v .. "=" )
end -- for k, v
end
return r
end -- Zitation.filter()
Zitation.format = function ()
-- Generiere Zitation
-- Rückgabewert:
--     1  -- string mit Vorlagenresultat
--     2  -- string mit Fehlermeldung(en) und -kategorien, oder false
local s
Resultat = ""
foreign( "bas", "Sprache" )
autorHrsg()
titel()       -- Schließt mit Punkt etc.
werk()        -- Schließt mit Punkt etc.
reihe()
auflage()     -- Schließt mit Punkt
endBlock()    -- Schließt mit Punkt
coins()
s = fehlerliste()
if s == "" then
s = false
end
return Resultat, s
end -- Zitation.format()
Zitation.COinS = function ( args, assign, already )
-- Create string with COinS 
-- Parameter:
--     args     -- table, with COinS components
--     assign   -- optional string, with ID
--     already  -- optional string, with preformatted &sequence
-- Returns HTML element string
local Text  = Zitation.fetch( "Text" )
local WLink = Zitation.fetch( "WLink" )
local rft   = { }
local site  = mw.site.server:gsub( "^%l*:?//", "" )
local s, sub, v
if assign then
sub = assign
else
if args.genre then
sub = args.genre
else
sub = "book"
end
end
if args.isbn then
args.isbn = args.isbn:gsub( "-", "" ):upper()
end
s = string.format( "%s%s%s",
"ctx_ver=Z39.88-2004",
"&rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3A",
sub )
if not args.genre then
s = s .. "&rft.genre=book"
end
if type( assign ) == "string" then
sub = assign
else
sub = mw.title.getCurrentTitle().fullText
end
s = string.format( "%s&rfr_id=info:sid/%s:%s",
s,
site,
mw.uri.encode( sub ) )
if already then
s = s .. already
end
for k, v in pairs( args ) do
table.insert( rft, k )
end -- for k, v
table.sort( rft )
for i = 1, #rft do
sub = rft i 
v   = args sub 
if type( v ) == "table" then
if type( v.tostring ) == "function" then
v = v.tostring()
end
end
if type( v ) == "string" then
v = mw.text.killMarkers( v )    -- 
v = mw.uri.encode( WLink.getPlain( Text.getPlain( v ) ) )
:gsub( "%%E2%%80%%93", "-" )
s = string.format( "%s&rft.%s=%s", s, sub, v )
end
end -- for i
s = string.format( "%s",
s,
"style='display:none'",
" " )
return s
end -- Zitation.COinS()
Zitation.ISBN = function ( access, accept, alert )
-- Create string with formatted ISBN
-- Parameter:
--     access   -- string, with presumable ISBN
--     accept   -- optional number, whether invalid data is permitted
--                  0, nil   -- require valid ISBN
--                 -1        -- ignore invalid check digit
--                 other     -- other, e.g. number of digits
--     alert    -- optional string, with maintenance category title
-- Returns:
--     1  -- string, for display
--     2  -- true, if conditions not matched
local URIutil = Zitation.fetch( "URIutil" )
local mode  = accept or 0
local isbn, lapsus, legal, lethal, r
if mode == -1 then
legal, isbn = URIutil.isISBN( access )
if legal then
if URIutil.isISBNvalid( access ) then
fehler( "Wert", "'ISBN' ist nicht formal falsch" )
else
lapsus = true
end
end
elseif mode == 0 then
legal, isbn = URIutil.isISBNvalid( access )
else
legal, isbn  = URIutil.isISBN( access )
if isbn == -1 then
lapsus = true
legal  = true
lethal = true
end
end
if legal then
if lethal then
r = URIutil.linkISBN( access, true, true, true, alert )
else
r = "ISBN " .. URIutil.formatISBN( access, isbn )
end
if lapsus then
local plus = mw.html.create( "small" )
local show, story
if lethal then
show  = "defekt"
story = "WP:ISBNdefekt"
else
show  = "formal falsch"
story = "WP:ISBNformalFalsch"
end
if story then
show = string.format( "%s", story, show )
end
show = string.format( "(%s)", show )
plus:addClass( "ISBN-bad-code" )
:css( "white-space", "nowrap" )
:wikitext( show )
r = string.format( "%s %s", r, tostring( plus ) )
end
else
r = string.format( "ISBN %s%s",
access,
Zitation.fault( "(?!)", true ) )
fehler( "Wert", "'ISBN'" )
fire( "ISBN" )
end
return r, legal
end -- Zitation.ISBN()
-- Export ===========================================================**
local p = { }
p.Endpunkt = function ( frame )
-- LEGACY für Vorlage:Internetquelle
local r = ""
local s = frame.args.titel
if s then
local Text = Zitation.fetch( "Text" )
if Text.sentenceTerminated( s ) then
r = ""
else
r = "."
end
end
return r
end -- p.Endpunkt
p.TitelFormat = function ( frame )
-- LEGACY für Vorlage:Internetquelle
local r = ""
local s = frame.args.titel
if s then
local Text = Zitation.fetch( "Text" )
if Text.sentenceTerminated( s ) then
r = s
else
r = s .. "."
end
r = string.format( "%s", r )
end
return r
end -- p.TitelFormat
p.COinS_Template = function ( frame )
local l, r = pcall( Zitation.COinS, frame:getParent().args )
return r
end -- p.COinS_Template
p.ISBN = function ( frame )
local mode = frame.args 2 
if mode then
mode = tonumber( mode )
end
if frame.args.template then
Selbst = frame.args.template
end
local l, r = pcall( Zitation.ISBN,
frame.args 1 ,
mode,
frame.args.link )
return r
end -- p.ISBN
function p.failsafe()
return Zitation.serial
end
p.Zitation = function ()
return Zitation
end -- p.Zitation
return p