Dokumentation für das Modul Citation[Ansicht] [Bearbeiten] [Versionsgeschichte] [Aktualisieren]

Verwendung

Das Modul wird direkt von den Vorlagen {{Buch}}, {{Karte}}, {{Sammelwerk}}, {{Zeitschrift}} und {{Zeitung}} aufgerufen. Parameterbeschreibung siehe dort.

Versionsbezeichnung auf Wikidata: 2025-05-01 Ok!

Stilvorlagen

Benötigte weitere Module

Dieses Modul benötigt folgende weitere Module: Check isxn • Citation/COinS • Citation/i18n • Citation/utilities • LinkISBN • UrlCheck • Yesno

Prüfungen

Die Prüfung der einzelnen Angaben wird, soweit möglich, mit Lua-Pattern vorgenommen. Bei ISBN, ISSN und deutschen URN wird die Prüfziffer ausgewertet.

Literatur

Hinweise
-- documentation local citation = { 	suite  = 'Citation', 	serial = '2025-05-01', 	item   = 56159597 }  -- module import -- require( 'strict' ) local cu = require( 'Module:Citation/utilities' ) local cc = require( 'Module:Citation/COinS' ) local ci = require( 'Module:Citation/i18n' ) local cx = require( 'Module:Check isxn' ) local li = require( 'Module:LinkISBN' ) local uc = require( 'Module:UrlCheck' ) local yn = require( 'Module:Yesno' )  -- module variable local ct = { 	moduleInterface = citation }  -- check for valid arguments against params table local function getValidArgs( frameArgs ) 	local args = {} 	local complete = {} 	local wrongParams = {}  	for key, value in pairs( ci.params ) do 		if not value.types or cu.inArray( value.types, frameArgs.type ) then 			for key2, value2 in ipairs( value ) do 				complete[ value2 ] = key 				args[ key ] = args[ key ] or 					( key ~= 'bibcode' and cu.parameterCleanup( frameArgs[ value2 ] ) or frameArgs[ value2 ] ) 			end 			args[ key ] = args[ key ] or '' 		end 	end 	-- no missing items 	for key, value in pairs( ci.params ) do 		if not args[ key ] then 			args[ key ] = '' 		end 	end  	for key, value in pairs( frameArgs ) do 		if not complete[ key ] then 			table.insert( wrongParams, key ) 		end 	end 	if #wrongParams == 1 then 		cu.addErrorMsg( cu.formatItem( wrongParams[ 1 ], ci.texts.unknownParam ) ) 	elseif #wrongParams > 0 then 		cu.addErrorMsg( cu.formatItem( table.concat( wrongParams, ', ' ), ci.texts.unknownParams ) ) 	end 	return args end  local function checkRedundantParams( args, keys ) 	local c = 0 	for i, key in ipairs( keys ) do 		if cu.isSet( args[ key ] ) then 			c = c + 1 			if c > 1 then 				return true 			end 		end 	end 	return false end  -- check parameter values local function checkValues( args ) 	local wrong = {} 	local i  	if cu.isSet( args.title ) then 		args.title = args.title:gsub( '%s*%.+$', '' ) 	end  	-- convert book with chapter to collection 	if args.type == 'book' and not cu.isSet( args.collection ) and cu.isSet( args.chapter ) then 		args.type = 'bookitem' 		args.collection, args.title, args.chapter = args.title, args.chapter, '' 		args.siteUrl, args.url, args.chapterUrl = args.url, args.chapterUrl, '' 	end  	if ( args.type == 'web' or args.type == 'webnews' ) 		and not cu.isSet( args.title ) and not cu.isSet( args.url ) then 		args.title = ci.texts.noTitle 		cu.addErrorMsg( ci.texts.noTitleUrl ) 	elseif not cu.isSet( args.title ) then 		args.title = ci.texts.noTitle 		cu.addErrorMsg( ci.texts.unknownTitle ) 	end  	args.pages = cu.cleanupPageNumbers( args.pages ) 	args.columns = cu.cleanupPageNumbers( args.columns )  	if ( cu.getNumber( args.KBytes ) / 1024 > 100 ) or 		( cu.getNumber( args.MBytes ) > 100 ) then 		cu.addErrorMsg( ci.texts.moreThan100 ) 	end 	if cu.isSet( args.KBytes ) then 		args.KBytes = args.KBytes:gsub( '%s*%[sic!%]', '' ) 	end 	if cu.isSet( args.MBytes ) then 		args.MBytes = args.MBytes:gsub( '%s*%[sic!%]', '' ) 	end 	if cu.isSet( args.KBytes ) and cu.isSet( args.MBytes ) then 		args.MBytes = '' 		cu.addErrorMsg( ci.texts.KBytesMBytes ) 	end  	args.ignoreError = yn( args.ignoreError, false ) 	if args.ignoreError then 		args.ignoreError = 'true' 	else 		args.ignoreError = 'false' 	end  	-- containing date format detected from args.date 	args.dateFormat = '' 	if cu.isSet( args.date ) then 		if args.date:match( '^[12]%d%d%d%-[01]?%d%-[0123]?%d$' ) then 			args.dateFormat = 'j. F Y' 		elseif args.date:match( '^[12]%d%d%d%-[01]?%d$' ) then 			args.dateFormat = 'M Y' 		elseif args.date:match( '^[12]%d%d%d$' ) then 			args.dateFormat = 'Y' 		elseif mw.ustring.match( args.date, '^[12]%d%d%d[-‒–—][12]%d%d%d$' ) or 			mw.ustring.match( args.date, '^[12]%d%d%d[-‒–—]$' ) then 			args.date = mw.ustring.gsub( args.date, '[-‒–—]', '–' ) 			args.dateFormat = 'R' 		else 			args.date = args.date:match( '%d+' ) or '' 			if cu.isSet( args.date ) then 				i = tonumber( args.date ) 				if i >= 1000 and i < 2100 then 					args.dateFormat = 'Y' 				else 					args.date = '' 					cu.addErrorMsg( ci.texts.wrongDate ) 				end 			end 		end 	end 	for key, value in ipairs( { 'accessDate', 'archiveDate' } ) do 		if cu.isSet( args[ value ] ) and 			not args[ value ]:match( '^20%d%d%-[01]?%d%-[0123]?%d$' ) then 			args[ value ] = '' 			cu.addErrorMsg( ci.texts.wrongDate ) 		end 	end  	for key, value in ipairs( { 'url', 'archiveUrl' } ) do 		if cu.isSet( args[ value ] ) and 			uc.isUrl( args[ value ], ci.skipPathCheck ) > 2 then 			args[ value ] = '' 			cu.addErrorMsg( ci.texts.noURL ) 		end 	end 	if cu.isSet( args.url ) then 		for j, url in ipairs( ci.unwantedUrls ) do 			if args.url:find( url, 1, true ) then 				cu.addErrorMsg( ci.texts.unwantedURL ) 				break 			end 		end 	end 	args.urlStatus = cu.getKey( args.urlStatus, ci.urlStatusTable ) 	if not cu.isSet( args.urlStatus ) and cu.isSet( args.archiveUrl ) then 		args.urlStatus = 'dead' 	elseif not cu.isSet( args.urlStatus ) then 		args.urlStatus = 'live' 	end 	args.isArchived = cu.isSet( args.archiveUrl ) 	if args.urlStatus == 'dead' or args.urlStatus == 'usurped' then 		args.originalUrl = args.url 		args.url = args.archiveUrl 		args.archiveUrl = '' 	end  	for key, value in ipairs( { 'dnb', 'oclc', 'jstor', 'pmid', 'KBytes' } ) do 		if cu.isSet( args[ value ] ) and not args[ value ]:match( '^[1-9]%d*$' ) then 			args[ value ] = '' 			table.insert( wrong, value ) 		end 	end  	if cu.isSet( args.asin ) then 		if args.asin:match("^%d%d%d%d%d%d%d%d%d[%dX]$") then 			if not cu.isSet( args.isbn ) and not args.asin:find( '^63[01]' ) and 				cx.check_isbn( { args = { [ 1 ] = args.asin, error = 'error' } } ) ~= 'error' then 				args.isbn = args.asin 			end 			args.asin = '' 			table.insert( wrong, 'asin' ) 		elseif not args.asin:match("^%u[%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u][%d%u]$") then 			args.asin = '' 			table.insert( wrong, 'asin' ) 		end 	end  	if cu.isSet( args.ol ) then 		args.ol = args.ol:gsub( '^OL', '' ) 		if not args.ol:match( '^[1-9]%d*[AMW]$' ) then 			args.ol = '' 			table.insert( wrong, 'ol' ) 		end 	end  	local match, country 	if cu.isSet( args.urn ) then 		args.urn = args.urn:lower():gsub( '^urn:', '' ) 		match, country = args.urn:match( '^(nbn:(%l%l):[%d%l%-%.:/_]+)$' ) 		if not ( match and country and ci.nbnResolving[ country ] ) then 			args.urn = '' 			table.insert( wrong, 'urn' ) 		end 	end 	if cu.isSet( args.urn ) and ci.nbnCheckDigit[ country ] and 		not cu.check_UrnNbn( 'urn:' .. args.urn ) then 		cu.addErrorMsg( ci.texts.wrongURN ) 	end  	-- in suffix spaces or n-dashes and at the end periods or commas are not allowed 	if cu.isSet( args.doi ) and not mw.ustring.match( args.doi, '^10%.[1-9]%d%d%d%d?/[^%s–]-[^%.,]$' ) then 		args.doi = '' 		table.insert( wrong, 'doi' ) 	end  	if cu.isSet( args.hdl ) and not mw.ustring.match( args.hdl, '^[1-9][%d%.]*%d/[^%s–]-[^%.,]$' ) then 		args.hdl = '' 		table.insert( wrong, 'hdl' ) 	end  	if not cu.isSet( args.url ) then 		for j, key in ipairs( ci.additionalTitleUrls ) do 			if cu.isSet( args[ key ] ) then 				args.url = ci.params[ key ].url:format( args[ key ] ) 				if key == 'urn' then 					args.urn = '' 				end 				break 			end 		end 	end  	-- See: https://arxiv.org/help/arxiv_identifier 	if cu.isSet( args.arxiv ) and not ( 		-- 1991-07 … 2007-03 		args.arxiv:match( '^%a[%a%.%-]+/[90]%d[01]%d%d%d%d$' ) or args.arxiv:match( '^%a[%a%.%-]+/[90]%d[01]%d%d%d%d[vV]%d+$' ) or 		-- 2007-04 … 2014-12 		args.arxiv:match( '^[01]%d[01]%d%.%d%d%d%d$' ) or args.arxiv:match( '^[01]%d[01]%d%.%d%d%d%d[vV]%d+$' ) or 		-- 2015-01 … 		args.arxiv:match( '^%d%d[01]%d%.%d%d%d%d%d$' ) or args.arxiv:match( '^%d%d[01]%d%.%d%d%d%d%d[vV]%d+$' ) ) then 		args.arxiv = '' 		table.insert( wrong, 'arXiv' ) 	end  	-- See: https://adsabs.harvard.edu/abs_doc/help_pages/data.html#bibcodes 	if cu.isSet( args.bibcode ) and 		not ( args.bibcode:len() == 19 and args.bibcode:match( '^[12]%d%d%d%a[%w&%.][%w&%.][%w&%.][%w%.]+[%a%.]$' ) ) then 		args.bibcode = '' 		table.insert( wrong, 'bibcode' .. args.bibcode:len() ) 	end 	if cu.isSet( args.bibcode ) then 		args.bibcode = args.bibcode:gsub( '%.', '#b#' ) -- keep bibcode periods (full stops) 	end  	if cu.isSet( args.edition ) and args.edition:match( '^%d+%.*$' ) then 		args.edition = args.edition:gsub( '%.', '' ) 		if args.edition == '1' then 			args.edition = '' 		end 	end  	if cu.isSet( args.type ) and args.type ~= 'map' then 		args.scale = '' 	end  	if cu.isSet( args.access ) then 		args.access = cu.getKey( args.access, ci.accessTypes ) 		if args.access == '' then 			cu.addErrorMsg( ci.texts.accesswrong ) 		elseif not cu.isSet( args.url ) and not cu.isSet( args.archiveUrl ) and 			not cu.isSet( args.doi ) and not cu.isSet( args.hdl ) and 			not cu.isSet( args.jstor ) then 			cu.addErrorMsg( ci.texts.accessNoUrl ) 		end 	end  	if checkRedundantParams( args, { 'isbn', 'dnb', 'urn', 'oclc', 'ol', 'asin' } ) or 		checkRedundantParams( args, { 'doi', 'hdl', 'jstor', 'arxiv', 'bibcode' } ) then 		cu.addErrorMsg( ci.texts.redundantParams ) 	end  	if #wrong == 1 then 		cu.addErrorMsg( cu.formatItem( wrong[ 1 ], ci.texts.wrongValue ) ) 	elseif #wrong > 1 then 		cu.addErrorMsg( cu.formatItem( table.concat( wrong, ', ' ), ci.texts.wrongValues ) ) 	end end  local function formatIdentifier( tab, key, urlPart, text, add ) 	if cu.isSet( urlPart ) and cu.isSet( text ) then 		text = ci.params[ key ].prefix .. 			cu.makeLink( ci.params[ key ].url:gsub( '%%s', urlPart ), text ) .. 			( add or '' ) 		table.insert( tab, text ) 	end end  local function addIssn( tab, issn, ignoreError ) 	if cu.isSet( issn ) then 		local add = ignoreError ~= 'true' and ci.texts.wrongIssn or '' 		add = cx.check_issn( { args = { [ 1 ] = issn, error = add } } ) 		formatIdentifier( tab, 'issn', issn, issn, add ) 	end end  -- make author part local function makeAuthor( author, editor ) 	author = cu.formatItem( author, ci.formatters.auAuthor ) 	editor = cu.formatItem( editor, ci.formatters.auEditor ) 	if cu.isSet( author ) and cu.isSet( editor ) then 		author = cu.formatItem2( author, editor, ci.formatters.auAuthorEditor ) 	elseif not cu.isSet( author ) and cu.isSet( editor ) then 		author = editor 	end 	return cu.formatItem( author, ci.formatters.auAuthorAll ) end  local function formatTitle( args, title, class ) 	local langAttr = {} 	if #args.languages > 0 then 		langAttr.lang = args.languages[ 1 ] 	end 	return tostring( mw.html.create( 'bdi' ) 		:addClass( class ) 		:attr( langAttr ) 		:wikitext( title ) 	) end  -- make title part local function makeTitle( args, title, volume, addition, url, scale, titleType ) 	if titleType == 'bookitem' then 		title = cu.formatItem( title, ci.formatters.tiCollectionTitle ) 	elseif titleType == 'journal' then 		title = cu.formatItem( title, ci.formatters.tiJournalTitle ) 	else 		title = formatTitle( args, title, ci.formatters.tiTitleClass ) 	end 	if not cu.isSet( title ) then 		title = ci.texts.noTitle 		cu.addErrorMsg( ci.texts.unknownTitle ) 	else 		title = title:gsub( "''+", '' ) -- remove multiple apostrophes 	end 	if cu.isSet( url ) then 		title = cu.makeLink( url, title:gsub( '[%[%]]', '' ) ) 	end  	if cu.isSet( volume ) then 		title = cu.formatItem2( title, volume, ci.formatters.tiVolume ) 	end 	if cu.isSet( addition ) then 		title = cu.formatItem2( title, addition, ci.formatters.tiAddition ) 	end 	return cu.formatItem( title, ci.formatters.tiAll ) 		.. cu.formatItem( scale, ci.formatters.tiScale ) end  -- make publisher part for books local function makePublisher( args, tab ) 	local theDate = '' 	if cu.isSet( args.date ) then 		if cu.isSet( args.dateFormat ) and args.dateFormat ~= 'Y' and args.dateFormat ~= 'R' then 			args.dateFormat = 'M Y' 		end 		theDate = cu.getDate( args.date, args.dateFormat, ci.texts.wrongDate ) 	end  	local published = ''  	if cu.isSet( args.edition ) then 		if args.edition:match( '^%d+$' ) then 			theDate = cu.formatItem2( theDate, args.edition, ci.formatters.puDateEditionNum ) 		else 			theDate = cu.formatItem2( theDate, args.edition, ci.formatters.puDateEdition ) 		end 	end  	local place = cu.formatItem( args.place, ci.formatters.puPlace ) 	local publisher = cu.formatItem( args.publisher, ci.formatters.puPublisher ) 	if cu.isSet( place ) and cu.isSet( publisher ) then 		published = cu.formatItem2( place, publisher, ci.formatters.puPlacePub ) 	elseif cu.isSet( place ) then 		published = place 	elseif cu.isSet( publisher ) then 		published = publisher 	end  	theDate = cu.formatItem( theDate, ci.formatters.puDate ) 	if not cu.isSet( published ) then 		published = theDate 	elseif cu.isSet( theDate ) then 		published = cu.formatItem2( published, theDate, ci.formatters.puPlaceDate ) 	end 	cu.insertItem( tab, published ) end  local function makeIsbn( args, tab ) 	if cu.isSet( args.isbn ) then 		table.insert( tab, 			li._linkISBNSet( { isbn = args.isbn, ignoreError = args.ignoreError } ) ) 	elseif cu.isSet( args.dnb ) then 		formatIdentifier( tab, 'dnb', args.dnb, args.dnb ) 	elseif cu.isSet( args.urn ) then 		formatIdentifier( tab, 'urn', args.urn, args.urn ) 	elseif cu.isSet( args.oclc ) then 		formatIdentifier( tab, 'oclc', args.oclc, args.oclc ) 	elseif cu.isSet( args.ol ) then 		local prefix = { 			A = 'authors/OL', 			M = 'books/OL', 			W = 'works/OL' 		}; 		formatIdentifier( tab, 'ol', prefix[ args.ol:sub( -1 ) ] .. args.ol, args.ol ) 	elseif cu.isSet( args.asin ) then 		formatIdentifier( tab, 'asin', args.asin, args.asin ) 	end 	addIssn( tab, args.issn, args.ignoreError ) 	addIssn( tab, args.eissn, args.ignoreError ) end  local function formatPages( s ) 	return mw.ustring.gsub( s, '-', '–' ) end  local function makePages( args, tab ) 	cu.insertItem( tab, formatPages( args.pages ), ci.formatters.addPages ) 	cu.insertItem( tab, formatPages( args.columns), ci.formatters.addColumns ) end  local function makeDoi( args, tab ) 	if cu.isSet( args.extent ) then 		if args.extent:match( '^%d+$' ) then 			args.extent = cu.formatItem( args.extent, ci.formatters.addExtent ) 		end 		table.insert( tab, args.extent ) 	end 	for i, key in ipairs( { 'doi', 'hdl', 'jstor', 'arxiv', 'bibcode' } ) do 		if cu.isSet( args[ key ] ) then 			formatIdentifier( tab, key, args[ key ], args[ key ] ) 			break 		end 	end 	formatIdentifier( tab, 'pmid', args.pmid, args.pmid ) end  local function makeWebInfo( args, tab ) 	local ext, kb 	if cu.isSet( args.url ) or cu.isSet( args.originalUrl ) or cu.isSet( args.archiveUrl )  		or cu.isSet( args.siteUrl ) or cu.isSet( args.chapterUrl ) then  		if cu.isSet( args.accessDate ) then 			args.accessDate = cu.getDate( args.accessDate, 'j. F Y', ci.texts.wrongDate ) 			cu.insertItem( tab, args.accessDate, ci.formatters.wbAccess ) 		end 		if cu.isSet( args.format ) then 			table.insert( tab, args.format:upper() ) 		else 			for i, url in ipairs( { args.url, args.chapterUrl, args.siteUrl, 				args.archiveUrl } ) do 				ext = cu.getExtension( url ) 				if ext then 					table.insert( tab, ext ) 					break 				end 			end 		end 		if cu.isSet( args.KBytes ) then 			kb = tonumber( args.KBytes ) or 0 			if kb >= 1024 then 				cu.insertItem( tab, 					tostring( cu.round( kb / 1024, 3 ) ):gsub( '%.', ci.texts.decimalPoint ), 					ci.formatters.wbMBytes ) 			else 				cu.insertItem( tab, args.KBytes, ci.formatters.wbKBytes ) 			end 		elseif cu.isSet( args.MBytes ) then 			cu.insertItem( tab, args.MBytes, ci.formatters.wbMBytes ) 		end 	end end  local function makeArchived( args ) 	local archived = ci.formatters.arArchived 	local original = ci.formatters.arOriginal 	local result = ''  	if cu.isSet( args.archiveUrl ) then 		archived = cu.makeLink( args.archiveUrl, archived ) 	end 	if cu.isSet( args.originalUrl ) then 		original = cu.makeLink( args.originalUrl, original ) 	end 	 	local archiveDay = '', result 	if cu.isSet( args.archiveDate ) then 		archiveDay = cu.getDate( args.archiveDate, 'l, j. F Y', ci.texts.wrongDate ) 	end  	if archiveDay ~= '' then 		if args.isArchived then 			result = mw.ustring.format( ci.formatters.arArchiveDate, archived, original, archiveDay ) 		else 			result = cu.formatItem( original, ci.formatters.arOffline ) 		end 	else 		if cu.isSet( args.archiveDate ) then 			cu.addErrorMsg( ci.texts.wrongDate ) 		end 		if args.isArchived then 			result = cu.formatItem2( archived, original, ci.formatters.arArchive ) 		else 			result = cu.formatItem( original, ci.formatters.arOffline ) 		end 	end 	return result end  local function analyzeLanguages( args ) 	local ok = true 	if cu.isSet( args.language ) then 		local parts = mw.text.split( args.language:lower(), ' ' ) 		local lng = {} 		for i = 1, #parts, 1 do 			parts[ i ] = mw.text.trim( parts[ i ]:gsub( ',', '' ) ) 			lng[ i ] = parts[ i ] 			if parts[ i ]:match( '^%a%a%a?$' ) or parts[ i ]:match( '^%a%a%-%a%a$' ) then 				parts[ i ] = mw.language.fetchLanguageName( parts[ i ], args.wikiLang ) 				if parts[ i ] == '' then 					ok = false 					break 				end 			else 				ok = false 				break 			end 		end 		if ok and #parts == 1 and lng[ 1 ] == args.wikiLang then 			parts = {} 			args.language = '' 		end 		if ok and #parts > 0 then 			args.languages = lng  			args.language = table.concat( parts, ', ' ) 			args.language = cu.formatItem( args.language, ci.formatters.addInLanguage ) 		end 	end end  local function makeLanguageComment( args, result ) 	result = result .. cu.formatItem( args.language, ci.formatters.addLanguage ) 	result = cu.formatItem( result, ci.formatters.puAll ) 	if cu.isSet( args.archiveUrl ) or cu.isSet( args.originalUrl )  		or args.urlStatus == 'usurped' then 		result = result .. makeArchived( args ) 	end 	return result .. cu.formatItem( args.quote, ci.formatters.addQuote ) 		.. cu.formatItem( args.comment, ci.formatters.addComment ) end  local function makePublished( args ) 	local result = {} 	makePublisher( args, result ) 	cu.insertItem( result, args.series, ci.formatters.tiSeries ) 	makeIsbn( args, result ) 	if cu.isSet( args.chapter ) and cu.isSet( args.chapterUrl ) then 		args.chapter = cu.makeLink( args.chapterUrl, args.chapter ) 	end 	cu.insertItem( result, args.chapter, ci.formatters.tiChapter ) 	makePages( args, result ) 	if #result > 0 then 		result = { table.concat( result, ci.formatters.addDelimiter1 ) } 	end  	makeDoi( args, result ) 	makeWebInfo( args, result ) 	result = table.concat( result, ci.formatters.addDelimiter2 )  	return makeLanguageComment( args, result ) end  local function makeBook( args ) 	local author, title 	 	if args.type == 'book' or args.type == 'map' then 		author = makeAuthor( args.author, args.editor ) 		title = makeTitle( args, args.title, args.volume, args.titleAddition, 			args.url, args.scale, 'title' ) 	else -- bookitem 		author = makeAuthor( '', args.editor ) 		title = makeTitle( args, args.collection, args.volume, args.titleAddition, 			args.url, '', 'bookitem' ) 	end 	return author .. title .. makePublished( args ) end  local function makeCollection( args ) 	local author = makeAuthor( args.author, '' ) 	local title = makeTitle( args, args.title, '', '', args.url, '', 'title' ) 	local editor = makeAuthor( '', args.editor ) 	local collection = makeTitle( args, args.collection, args.volume, 		args.titleAddition, args.siteUrl, '', 'bookitem' )  	return author .. title .. ci.formatters.tiIn .. editor .. collection 		.. makePublished( args ) end  local function makeJournalTitle( args ) 	local title 	if args.type == 'journal' then 		title = args.journal 	elseif args.type == 'newspaper' then 		title = args.newspaper 	else 		title = args.website 	end 	if not cu.isSet( title ) then 		if args.type ~= 'web' or args.type == 'webnews' then 			title = ci.texts.noTitle 			cu.addErrorMsg( ci.texts.unknownPeriodical ) 		end 	else 		title = title:gsub( "''+", '' ) -- remove multiple apostrophes 		if args.type == 'journal' then 			title = cu.formatItem( title, ci.formatters.tiJournalTitle ) 		elseif args.type == 'newspaper' then 			title = cu.formatItem( title, ci.formatters.tiNewspaperTitle ) 		else 			title = cu.formatItem( title, ci.formatters.tiWebsiteTitle ) 		end 		if cu.isSet( args.siteUrl ) then 			title = cu.makeLink( args.siteUrl, title:gsub( '[%[%]]', '' ) ) 		end 		title = ci.formatters.tiIn .. title 			.. cu.formatItem( args.place, ci.formatters.prPlace ) 			.. cu.formatItem( args.abbr, ci.formatters.prAbbr) 	end 	return title end  local function makeJournalInfo( args, tab ) 	local year = '' 	if cu.isSet( args.date ) then 		year = cu.getDate( args.date, args.dateFormat, ci.texts.wrongDate ) 	end 	local volume = '' 	if cu.isSet( args.volume ) then 		volume = cu.formatItem( args.volume, ci.formatters.prVolume ) 		if cu.isSet( args.issue ) then 			volume = cu.formatItem2( volume, args.issue, ci.formatters.prVolIssue ) 		end 		if year ~= '' then 			volume = cu.formatItem2( volume, year, ci.formatters.prVolYear ) 		end 	else 		if cu.isSet( args.issue ) then 			volume = cu.formatItem( args.issue, ci.formatters.prIssue ) 			if year ~= '' then 				volume = cu.formatItem2( volume, year, ci.formatters.prVolYear ) 			end 		else 			volume = year 		end 	end 	cu.insertItem( tab, volume ) end  local function makeNewspaperInfo( args, tab ) 	local day = '' 	if cu.isSet( args.date ) then 		if args.dateFormat == 'j. F Y' then 			-- following result can be '' 			day = cu.getDate( args.date, 'l, j. F Y', ci.texts.wrongDate ) 		elseif args.dateFormat == 'M Y' or args.dateFormat == 'Y' then 			day = cu.getDate( args.date, args.dateFormat, ci.texts.wrongDate ) 		else 			cu.addErrorMsg( ci.texts.wrongDate ) 		end 	end  	day = cu.formatItem( day, ci.formatters.puDate ) 	cu.insertItem( tab, args.publisher ) 	cu.insertItem( tab, args.volume, ci.formatters.nsVolume ) 	cu.insertItem( tab, args.issue, ci.formatters.prIssue ) 	cu.insertItem( tab, day ) end  local function makePeriodical( args ) 	local author = makeAuthor( args.author, '' ) 		.. makeTitle( args, args.title, '', args.titleAddition, args.url, '', 'title' )  	local result = {} 	local jTitle = makeJournalTitle( args ) 	cu.insertItem( result, jTitle ) 	 	makeIsbn( args, result ) 	if args.type == 'journal' then 		makeJournalInfo( args, result ) 	else -- newspaper and web 		makeNewspaperInfo( args, result ) 	end 	makePages( args, result ) 	makeDoi( args, result ) 	makeWebInfo( args, result ) 	if #result > 0 then 		result[ 1 ] = mw.ustring.gsub( result[ 1 ], '^%l', mw.ustring.upper ) 	end 	result = table.concat( result, ci.formatters.addDelimiter1 )  	return author .. makeLanguageComment( args, result ) end  local function makeCitation( frameArgs ) 	local args = getValidArgs( frameArgs ) 	checkValues( args )  	args.wikiLang = mw.language.getContentLanguage():getCode() 	args.languages = {} 	analyzeLanguages( args )  	local citation 	if args.type == 'map' or args.type == 'book' then 		citation = makeBook( args ) 	elseif args.type == 'bookitem' then 		citation = makeCollection( args ) 	elseif args.type == 'journal' or args.type == 'newspaper' 		or args.type == 'web' or args.type == 'webnews' then 		citation = makePeriodical( args ) 	else 		args.type = 'book' 		citation = ci.texts.wrongType .. makeBook( args ) 	end  	citation = cu.finalCleanup( citation ) 	if cu.isSet( args.access ) then 		citation = citation 			.. '&nbsp;<span class="voy-cite-access">' 			.. ci.accessTypes[ args.access ].file .. '</span>' 	end 	cc.prepareForCOinS( args ) 	 	return cu.getErrorMsgs() 		.. tostring( mw.html.create( 'cite' ) 			:attr( 'class', ci.citeClass .. ci.addCiteClasses[ args.type ] ) 			:wikitext( citation ) 		) 		.. cc.makeCOinS( args ) end  function ct.citation( frame ) 	local fType = frame.args.type 	local args = frame:getParent().args  	if cu.isSet( fType ) then 		args.type = fType 	else 		args.type = cu.getKey( cu.getArgValue( ci.params, 'type', args ), ci.refTypes ) 	end 	if not cu.isSet( args.type ) then 		if cu.getArgValue( ci.params, 'scale', args ) ~= '' then 			args.type = 'map' 		elseif cu.getArgValue( ci.params, 'collection', args ) ~= '' then 			args.type = 'bookitem' 		elseif cu.getArgValue( ci.params, 'journal', args ) ~= '' then 			args.type = 'journal' 		elseif cu.getArgValue( ci.params, 'newspaper', args ) ~= '' then 			args.type = 'newspaper' 		elseif cu.getArgValue( ci.params, 'website', args ) ~= '' then 			args.type = 'web' 		else 			args.type = 'book' 		end 	end 	return cu.templateStyles( frame ) .. makeCitation( args ) end  return ct