Modul:Citation: Unterschied zwischen den Versionen

Aus skandinavien-wiki.net
KKeine Bearbeitungszusammenfassung
K (173 Versionen von wikivoyage:Modul:Citation importiert)
 
(143 dazwischenliegende Versionen von einem anderen Benutzer werden nicht angezeigt)
Zeile 1: Zeile 1:
-- documentation
-- documentation
local scrollGallery = {
local citation = {
suite  = 'Citation',
suite  = 'Citation',
serial = '2020-03-23',
serial = '2022-10-21',
item  = 56159597
}
}


-- module import
-- 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 cx = require( 'Module:Check isxn' )
local li = require( 'Module:LinkISBN' )
local li = require( 'Module:LinkISBN' )
Zeile 12: Zeile 17:


-- module variable
-- module variable
local ci = {}
local ct = {
 
moduleInterface = citation
-- global variables
local types = {
book      = { 'book', 'Buch' },
map        = { 'map', 'Karte' },
collection = { 'collection', 'Sammelwerk' },
journal    = { 'journal', 'Zeitschrift' },
newspaper  = { 'newspaper', 'Zeitung' }
}
 
local params = {
type      = { 'type', 'Typ' },
author    = { 'Autor', COinS = 'rft.au' },
editor    = { 'Herausgeber', 'Hrsg' },
title      = { 'Titel', COinS = 'rft.title' },
chapter    = { 'Kapitel', types = 'book', COinS = 'rft.atitle' },
collection = { 'Sammelwerk', types = 'collection' },
journal    = { 'Zeitschrift', 'Sammelwerk', types = 'journal', COinS = 'rft.jtitle' },
newspaper  = { 'Zeitung', 'Sammelwerk', types = 'newspaper', COinS = 'rft.jtitle' },
abbr      = { 'Abk', types = { 'collection', 'journal', 'newspaper' } },
url        = { 'Online', 'URL' },
articleUrl = { 'Onlineaufsatz', 'Aufsatz-URL', types = { 'collection', 'journal', 'newspaper' } },
jstor      = { 'JSTOR', types = { 'journal', 'newspaper' } },
KBytes    = { 'KBytes', 'kBytes', 'kbytes' },
accessDate = { 'Zugriff', 'Abruf' },
scale      = { 'Maßstab', types = 'map' },
place      = { 'Ort', COinS = 'rft.place' },
publisher  = { 'Verlag', types = { 'book', 'map', 'collection' }, COinS = 'rft.pub' },
date      = { 'Datum', 'Jahr', COinS = 'rft.date' },
edition    = { 'Auflage', types = { 'book', 'map', 'collection' }, COinS = 'rft.edition' },
volume    = { 'Band', COinS = 'rft.volume' },
issue      = { 'Ausgabe', 'Nummer', types = { 'journal', 'newspaper' }, COinS = 'rft.issue' },
pages      = { 'Seite', 'Seiten', types = { 'book', 'collection', 'journal', 'newspaper' }, COinS = 'rft.pages' },
columns    = { 'Spalten', types = { 'book', 'collection', 'journal', 'newspaper' }, COinS = 'rft.pages' },
extent    = { 'Umfang', 'Seitenanzahl', types = { 'book', 'collection', 'map' } },
series    = { 'Serie', 'Reihe', types = { 'book', 'collection', 'map' }, COinS = 'rft.series' },
series2    = { 'Serie2', 'Reihe2', types = { 'book', 'collection', 'map' } },
series3    = { 'Serie3', 'Reihe3', types = { 'book', 'collection', 'map' } },
isbn      = { 'ISBN', types = { 'book', 'collection', 'map', 'journal' }, COinS = 'rft.isbn' },
dnb        = { 'DNB', types = { 'book', 'collection', 'map' } },
oclc      = { 'OCLC', types = { 'book', 'collection', 'map' }, COinS_id = 'info:oclcnum' },
issn      = { 'ISSN', COinS = 'rft.issn' },
doi        = { 'DOI', COinS_id = 'info:doi' },
language  = { 'Sprache' },
comment    = { 'Kommentar' },
noError    = { 'noError', 'noerror', 'keinFefler', 'kein Fehler' }
}
}


local formatters = {
-- check for valid arguments against params table
auAuthor = '%s: ',
local function getValidArgs( frameArgs )
auEditor = '%s (Hrsg.)',
local args = {}
auAuthorEditor = '%s ; %s',
tiAll = "%s. ",
tiTitle = "''%s''",
tiVolume = "''%s''; Bd. %s",
tiScale = 'Maßstab: %s. ',
tiIn = 'In: ',
tiChapter = "Kapitel ''%s''",
puAll = '%s.',
puPlaceDate = '%s, %s',
puPlacePub = '%s: %s',
puDateEdition = '%s (%d. Auflage)',
addSeries = '(%s)',
addPages = 'S. %s',
addColumns = 'Sp. %s',
addDelimiter1 = ', ',
addDelimiter2 = '; ',
addDoi = '[[w:Digital Object Identifier|doi]]:%s',
addLanguage = ' (%s)',
addComment = ' %s',
prPlace = ' <%s>',
prAbbr = ' (%s)',
prVolume = 'Bd. %s',
prIssue = 'Nr. %s',
prVolIssue = '%s,%s',
prVolYear = '%s (%s)',
nsVolume = 'Jg. %s',
nsNrOfDay = '%s vom %s',
dbDnb = '[[w:Deutsche Nationalbibliothek|DNB]] [http://d-nb.info/%s %s]',
dbOclc = '[[w:Online Computer Library Center|OCLC]] [https://worldcat.org/oclc/%s %s]',
dbIssn = '[[w:Internationale Standardnummer für fortlaufende Sammelwerke|ISSN]] [http://zdb-katalog.de/list.xhtml?t=iss%3D%22xx1xx%22&key=cql xx1xx]',
dbJstor = '[[w:JSTOR|JSTOR]] [https://www.jstor.org/stable/%s %s]',
wbAccess = 'Internetabruf am %s',
wbKBytes = 'Dateigröße %s KByte'
}
 
local texts = {
noTitel      = '<span class="error">Fehlender Titel</span>',
noURL        = '<span class="error">Fehlerhafte URL</span>[[Category:Literatur: fehlerhafte URL]]',
unknownParam  = '<span class="error">Fehlerhafter Parameter: %s</span>[[Category:Literatur: fehlerhafte Parameter]]',
unknownParams = '<span class="error">Fehlerhafte Parameter: %s</span>[[Category:Literatur: fehlerhafte Parameter]]',
unknownTitle  = '[[Category:Literatur: fehlender Titel]]',
unknownPeriodical = '[[Category:Literatur: fehlender Titel eines Periodikums]]',
wrongDate    = '<span class="error">Ungültiges Datum</span>[[Category:Literatur: ungültiges Datum]]',
wrongIssn    = '<span class="error">Ungültige ISSN</span>[[Category:Seiten mit ISSN-Fehlern]]',
wrongType    = '<span class="error">Fehlerhafter Typ</span>[[Category:Literatur: fehlerhafter Typ]]'
}
 
local errorMsgs = {}
local dateFormat = ''
 
-- check if table contains the value
local function inArray( tab, val )
if type( tab ) == 'string' then
return tab == val
end
 
local index, value
for index, value in ipairs( tab ) do
if value == val then
return true
end
end
 
return false
end
 
-- returns a single value from frame argument table
local function getArgValue( param, args )
value = '', k, v
if params[ param ] then
for k, v in ipairs( params[ param ] ) do
if args[ v ] and args[ v ] ~= '' then
value = args[ v ]
break
end
end
end
return value
end
 
-- string cleanup
local function cleanupParameters( s )
if not s or s == '' then
return s
end
s = s:gsub( '[\009\010\013]', ' ' ) -- horizontal tab, line feed, carriage return
s = s:gsub( '[%z%c]', '' ) -- control characters
s = s:gsub( '&nbsp;', ' ' );
s = s:gsub( '\226\128\138', ' ' ); -- hair space
s = mw.ustring.gsub( s, '[\226\128\141\226\128\139\194\173]', '' ); -- zero-width joiner, zero-width space, soft hyphen
s = mw.ustring.gsub( s, '%.%.%.', '…' )
s = mw.ustring.gsub( s, '%.%.', '‥' )
s = mw.ustring.gsub( s, '<br%s*/*>', '' )
s = mw.ustring.gsub( s, '</*p%s*/*>', '' )
return mw.ustring.gsub( s, '</*span%s*/*>', '' )
end
 
-- check for possible arguments against params table
local function checkParams( frameArgs )
local args = {}, key, key2, ok, value, value2
local complete = {}
local complete = {}
local wrongParams = {}
local wrongParams = {}
local aType = getArgValue( 'type', frameArgs )
-- convert type values if translated
for key, value in pairs( types ) do
if inArray( value, aType ) then
aType = key
break
end
end


for key, value in pairs( params ) do
for key, value in pairs( ci.params ) do
if not value.types or inArray( value.types, aType ) then
if not value.types or cu.inArray( value.types, frameArgs.type ) then
for key2, value2 in ipairs( value ) do
for key2, value2 in ipairs( value ) do
complete[ value2 ] = key
complete[ value2 ] = key
args[ key ] = args[ key ] or
args[ key ] = args[ key ] or
cleanupParameters( frameArgs[ value2 ] )
( key ~= 'bibcode' and cu.parameterCleanup( frameArgs[ value2 ] ) or frameArgs[ value2 ] )
end
end
args[ key ] = args[ key ] or ''
args[ key ] = args[ key ] or ''
Zeile 186: Zeile 38:
end
end
-- no missing items
-- no missing items
for key, value in pairs( params ) do
for key, value in pairs( ci.params ) do
if not args[ key ] then
if not args[ key ] then
args[ key ] = ''
args[ key ] = ''
Zeile 198: Zeile 50:
end
end
if #wrongParams == 1 then
if #wrongParams == 1 then
table.insert( errorMsgs,
cu.addErrorMsg( cu.formatItem( wrongParams[ 1 ], ci.texts.unknownParam ) )
mw.ustring.format( texts.unknownParam, table.concat( wrongParams, ', ' ) ) )
elseif #wrongParams > 0 then
elseif #wrongParams > 0 then
table.insert( errorMsgs,
cu.addErrorMsg( cu.formatItem( table.concat( wrongParams, ', ' ), ci.texts.unknownParams ) )
mw.ustring.format( texts.unknownParams, table.concat( wrongParams, ', ' ) ) )
end
end
return args
return args
end
end


local function getPageNumbers( pages )
local function checkRedundantParams( args, keys )
if not pages then
local i = 0
return ''
for _, key in ipairs( keys ) do
if cu.isSet( args[ key ] ) then
i = i + 1
if i > 1 then
return true
end
end
end
end
pages = ( '' .. pages ):gsub( '–', '-' ); -- replace endashes with hyphens
return false
return pages:gsub( '&%w+;', '-' ); -- replace html entities with hyphens
end
end


-- check parameter values
local function checkValues( args )
local function checkValues( args )
local i, key, value
local wrong = {}
local i


args.pages = getPageNumbers( args.pages )
if cu.isSet( args.title ) then
args.columns = getPageNumbers( args.columns )
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.noError = yn( args.noError, false )
args.ignoreError = yn( args.ignoreError, false )
if args.noError then
if args.ignoreError then
args.noError = 'true'
args.ignoreError = 'true'
else
else
args.noError = 'false'
args.ignoreError = 'false'
end
end


if args.date ~= '' then
-- 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
if args.date:match( '^[12]%d%d%d%-[01]?%d%-[0123]?%d$' ) then
dateFormat = 'j. F Y'
args.dateFormat = 'j. F Y'
elseif args.date:match( '^[12]%d%d%d%-[01]?%d$' ) then
elseif args.date:match( '^[12]%d%d%d%-[01]?%d$' ) then
dateFormat = 'M Y'
args.dateFormat = 'M Y'
elseif args.date:match( '^[12]%d%d%d$' ) then
elseif args.date:match( '^[12]%d%d%d$' ) then
dateFormat = 'Y'
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
else
args.date = args.date:match( '%d+' ) or ''
args.date = args.date:match( '%d+' ) or ''
if args.date ~= '' then
if cu.isSet( args.date ) then
i = tonumber( args.date )
i = tonumber( args.date )
if i >= 1000 and i < 2100 then
if i >= 1000 and i < 2100 then
dateFormat = 'Y'
args.dateFormat = 'Y'
else
else
args.date = ''
args.date = ''
table.insert( errorMsgs, texts.wrongDate )
cu.addErrorMsg( ci.texts.wrongDate )
end
end
end
end
end
end
end
end
if args.accessDate ~= '' and
for key, value in ipairs( { 'accessDate', 'archiveDate' } ) do
not args.accessDate:match( '^20%d%d%-[01]?%d%-[0123]?%d$' ) then
if cu.isSet( args[ value ] ) and
args.accessDate = ''
not args[ value ]:match( '^20%d%d%-[01]?%d%-[0123]?%d$' ) then
table.insert( errorMsgs, texts.wrongDate )
args[ value ] = ''
cu.addErrorMsg( ci.texts.wrongDate )
end
end
end


i = 0
for key, value in ipairs( { 'url', 'archiveUrl' } ) do
for key, value in ipairs( { 'url', 'articleUrl' } ) do
if cu.isSet( args[ value ] ) and
if args[ value ] ~= '' then
uc.isUrl( args[ value ], ci.skipPathCheck ) > 2 then
if uc.isUrl( args[ value ] ) > 2 then
args[ value ] = ''
args[ value ] = ''
cu.addErrorMsg( ci.texts.noURL )
i = i + 1
end
end
if cu.isSet( args.url ) then
for _, url in ipairs( ci.unwantedUrls ) do
if args.url:find( url, 1, true ) then
cu.addErrorMsg( ci.texts.unwantedURL )
break
end
end
end
end
end
end
if i > 0 then
args.urlStatus = cu.getKey( args.urlStatus, ci.urlStatusTable )
table.insert( errorMsgs, texts.noURL )
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
end


for key, value in ipairs( { 'dnb', 'oclc', 'jstor', 'KBytes' } ) do
for key, value in ipairs( { 'dnb', 'oclc', 'jstor', 'pmid', 'KBytes' } ) do
if not args[ value ]:match( '^%d+$' ) then
if cu.isSet( args[ value ] ) and not args[ value ]:match( '^[1-9]%d*$' ) then
args[ value ] = ''
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
end
end


args.edition = args.edition:match( '%d+' ) or ''
local match, country
if args.edition == '1' then
if cu.isSet( args.urn ) then
args.edition = ''
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 _, 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
end


if args.type ~= 'map' then
-- See: https://arxiv.org/help/arxiv_identifier
args.scale = ''
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
end
end


local function makeAuthor( author, editor )
-- See: https://adsabs.harvard.edu/abs_doc/help_pages/data.html#bibcodes
if editor ~= '' then
if cu.isSet( args.bibcode ) and
editor = mw.ustring.format( formatters.auEditor, editor )
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
end
if author ~= '' and editor ~= '' then
if cu.isSet( args.bibcode ) then
author = mw.ustring.format( formatters.auAuthorEditor, author, editor )
args.bibcode = args.bibcode:gsub( '%.', '#b#' ) -- keep bibcode periods (full stops)
elseif author == '' and editor ~= '' then
author = editor
end
end
if author ~= '' then
 
return mw.ustring.format( formatters.auAuthor, author )
if cu.isSet( args.edition ) and args.edition:match( '^%d+%.*$' ) then
else
args.edition = args.edition:gsub( '%.', '' )
return ''
if args.edition == '1' then
args.edition = ''
end
end
end
end


local function makeTitle( title, volume, url, scale )
if cu.isSet( args.type ) and args.type ~= 'map' then
if title == '' then
args.scale = ''
title = texts.noTitle
table.insert( errorMsgs, texts.unknownTitle )
end
end
if url ~= '' then
 
title = '[' .. url .. ' ' .. title .. ']'
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
end
 
if volume and volume ~= '' then
if checkRedundantParams( args, { 'isbn', 'dnb', 'urn', 'oclc', 'ol', 'asin' } ) or
title = mw.ustring.format( formatters.tiVolume, title, volume )
checkRedundantParams( args, { 'doi', 'hdl', 'jstor', 'arxiv', 'bibcode' } ) then
else
cu.addErrorMsg( ci.texts.redundantParams )
title = mw.ustring.format( formatters.tiTitle, title )
end
end
title = mw.ustring.format( formatters.tiAll, title )
 
if scale and scale ~= '' then
if #wrong == 1 then
title = title .. mw.ustring.format( formatters.tiScale, scale )
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
return title
end
end


local function makeDoiLink( doi )
local function formatIdentifier( tab, key, urlPart, text, add )
doi = mw.ustring.gsub( doi, 'https?://doi.org/', '' )
if cu.isSet( urlPart ) and cu.isSet( text ) then
return '[' .. 'https://doi.org/' .. mw.uri.encode( doi )
text = ci.params[ key ].prefix ..
.. ' ' .. doi .. ']'
cu.makeLink( ci.params[ key ].url:gsub( '%%s', urlPart ), text ) ..
( add or '' )
table.insert( tab, text )
end
end
end


local function makeIssnLink( issn, noError )
local function addIssn( tab, issn, ignoreError )
local text = ''
if cu.isSet( issn ) then
if noError ~= 'true' then
local add = ignoreError ~= 'true' and ci.texts.wrongIssn or ''
text = texts.wrongIssn
add = cx.check_issn( { args = { [ 1 ] = issn, error = add } } )
formatIdentifier( tab, 'issn', issn, issn, add )
end
end
return formatters.dbIssn:gsub( 'xx1xx', issn )
.. cx.check_issn( { args = { [ 1 ] = issn, error = text } } )
end
end


local function getDate( aDate, aFormat )
-- make author part
local function formatDate( aDate, aFormat )
local function makeAuthor( author, editor )
return mw.getContentLanguage():formatDate( aFormat, aDate, true )
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
end
return cu.formatItem( author, ci.formatters.auAuthorAll )
end


if aDate ~='' then
-- make title part
local success, t;
local function makeTitle( title, volume, addition, url, scale, titleType )
success, t = pcall( formatDate, aDate, aFormat )
if titleType == 'bookitem' then
if success then
title = cu.formatItem( title, ci.formatters.tiCollectionTitle )
return t
elseif titleType == 'journal' then
else
title = cu.formatItem( title, ci.formatters.tiJournalTitle )
table.insert( errorMsgs, texts.wrongDate )
else
return ''
title = cu.formatItem( title, ci.formatters.tiTitle )
end
end
if not cu.isSet( title ) then
title = ci.texts.noTitle
cu.addErrorMsg( ci.texts.unknownTitle )
else
else
return ''
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
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
end


-- make publisher part for books
local function makePublisher( args, tab )
local function makePublisher( args, tab )
local theDate = ''
local theDate = ''
if args.date ~= '' then
if cu.isSet( args.date ) then
if dateFormat ~= '' and dateFormat ~= 'Y' then
if cu.isSet( args.dateFormat ) and args.dateFormat ~= 'Y' and args.dateFormat ~= 'R' then
dateFormat = 'M Y'
args.dateFormat = 'M Y'
end
end
theDate = getDate( args.date, dateFormat )
theDate = cu.getDate( args.date, args.dateFormat, ci.texts.wrongDate )
end
end


local published = ''
local published = ''


if theDate ~= '' and args.edition ~= '' then
if cu.isSet( args.edition ) then
theDate = mw.ustring.format( formatters.puDateEdition, theDate, args.edition )
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
end
if args.place ~= '' and args.publisher ~= '' then
 
published = mw.ustring.format( formatters.puPlacePub, args.place, args.publisher )
local place = cu.formatItem( args.place, ci.formatters.puPlace )
elseif args.place ~= '' then
local publisher = cu.formatItem( args.publisher, ci.formatters.puPublisher )
published = args.place
if cu.isSet( place ) and cu.isSet( publisher ) then
elseif args.publisher ~= '' then
published = cu.formatItem2( place, publisher, ci.formatters.puPlacePub )
published = args.publisher
elseif cu.isSet( place ) then
published = place
elseif cu.isSet( publisher ) then
published = publisher
end
end
if published == '' then
 
theDate = cu.formatItem( theDate, ci.formatters.puDate )
if not cu.isSet( published ) then
published = theDate
published = theDate
elseif theDate ~= '' then
elseif cu.isSet( theDate ) then
published = mw.ustring.format( formatters.puPlaceDate, published, theDate )
published = cu.formatItem2( published, theDate, ci.formatters.puPlaceDate )
end
if published ~= '' then
table.insert( tab, published )
end
end
cu.insertItem( tab, published )
end
end


local function makeSeries( args, tab )
local function makeIsbn( args, tab )
local key, value
if cu.isSet( args.isbn ) then
for key, value in ipairs( { 'series', 'series2', 'series3' } ) do
table.insert( tab,
if args[ value ] ~= '' then
li._linkISBNSet( { isbn = args.isbn, ignoreError = args.ignoreError } ) )
table.insert( tab, mw.ustring.format( formatters.addSeries, args[ value ] ) )
elseif cu.isSet( args.dnb ) then
end
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
end
addIssn( tab, args.issn, args.ignoreError )
addIssn( tab, args.eissn, args.ignoreError )
end
end


local function makeIsbn( args, tab )
local function formatPages( s )
if args.isbn ~= '' then
return mw.ustring.gsub( s, '-', '' )
table.insert( tab,
li._linkISBNSet( { isbn = args.isbn, noerror = args.noError } ) )
elseif args.dnb ~= '' then
table.insert( tab, mw.ustring.format( formatters.dbDnb, args.dnb, args.dnb ) )
elseif args.oclc ~= '' then
table.insert( tab, mw.ustring.format( formatters.dbOclc, args.oclc, args.oclc ) )
end
if args.issn ~= '' then
table.insert( tab, makeIssnLink( args.issn, args.noError ) )
end
end
end


local function makePages( args, tab )
local function makePages( args, tab )
if args.pages ~= '' then
cu.insertItem( tab, formatPages( args.pages ), ci.formatters.addPages )
table.insert( tab,
cu.insertItem( tab, formatPages( args.columns), ci.formatters.addColumns )
mw.ustring.format( formatters.addPages, args.pages:gsub( '-', '–' ) ) )
end
if args.columns ~= '' then
table.insert( tab,
mw.ustring.format( formatters.addColumns, args.columns:gsub( '-', '–' ) ) )
end
end
end


local function makeDoi( args, tab )
local function makeDoi( args, tab )
if args.extent ~= '' then
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 )
table.insert( tab, args.extent )
end
end
if args.doi ~= '' then
for _, key in ipairs( { 'doi', 'hdl', 'jstor', 'arxiv', 'bibcode' } ) do
table.insert( tab,
if cu.isSet( args[ key ] ) then
mw.ustring.format( formatters.addDoi, makeDoiLink( args.doi ) ) )
formatIdentifier( tab, key, args[ key ], args[ key ] )
end
break
if args.jstor ~= '' then
end
table.insert( tab,
mw.ustring.format( formatters.dbJstor, args.jstor, args.jstor ) )
end
end
formatIdentifier( tab, 'pmid', args.pmid, args.pmid )
end
end


local function makeWebInfo( args, tab )
local function makeWebInfo( args, tab )
if args.url ~= '' or args.articleUrl ~= '' then
local kb
if args.accessDate ~= '' then
if cu.isSet( args.url ) or cu.isSet( args.originalUrl ) or cu.isSet( args.archiveUrl ) then
args.accessDate = getDate( args.accessDate, 'j. F Y' )
if cu.isSet( args.accessDate ) then
if args.accessDate ~= '' then
args.accessDate = cu.getDate( args.accessDate, 'j. F Y', ci.texts.wrongDate )
table.insert( tab,
cu.insertItem( tab, args.accessDate, ci.formatters.wbAccess )
mw.ustring.format( formatters.wbAccess, args.accessDate ) )
end
if cu.isSet( args.format ) then
table.insert( tab, args.format:upper() )
else
for index, value in ipairs( { 'PDF', 'DOC', 'DOCX', 'RTF', 'ODT',
'PPT', 'PPTX', 'XLS', 'XLSX' } ) do
if cu.hasExtension( args.url, value ) then
table.insert( tab, value )
break
end
if cu.hasExtension( args.archiveUrl, value ) then
table.insert( tab, value )
break
end
end
end
end
end
if args.KBytes ~= '' then
if cu.isSet( args.KBytes ) then
table.insert( tab,
kb = tonumber( args.KBytes ) or 0
mw.ustring.format( formatters.wbKBytes, args.KBytes ) )
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
end
end
end


local function makeLanguageComment( args, result )
local function makeArchived( args )
if args.language ~= '' then
local archived = ci.formatters.arArchived
result = result .. mw.ustring.format( formatters.addLanguage, args.language )
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
end
if result ~= '' then
result = mw.ustring.format( formatters.puAll, result )
local archiveDay = '', result
if cu.isSet( args.archiveDate ) then
archiveDay = cu.getDate( args.archiveDate, 'l, j. F Y', ci.texts.wrongDate )
end
end
if args.comment ~= '' then
 
result = result .. mw.ustring.format( formatters.addComment, args.comment )
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
end
return result
return result
end
local function makeLanguageComment( args, result )
local ok = true
if cu.isSet( args.language ) then
local parts = mw.text.split( args.language, ' ' )
for i = 1, #parts, 1 do
parts[ i ] = mw.text.trim( parts[ i ]:gsub( ',', '' ) )
if parts[ i ]:match( '^%a%a%a?$' ) then
parts[ i ] = mw.language.fetchLanguageName( parts[ i ],
mw.language.getContentLanguage():getCode() )
if parts[ i ] == '' then
ok = false
break
end
else
ok = false
break
end
end
if ok and #parts > 0 then
args.language = table.concat( parts, ', ' )
args.language = cu.formatItem( args.language, ci.formatters.addInLanguage )
end
end
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
end


local function makePublished( args )
local function makePublished( args )
result = {}
local result = {}
makePublisher( args, result )
makePublisher( args, result )
makeSeries( args, result )
cu.insertItem( result, args.series, ci.formatters.tiSeries )
makeIsbn( args, result )
makeIsbn( args, result )
if args.chapter ~= '' then
if cu.isSet( args.chapter ) and cu.isSet( args.chapterUrl ) then
table.insert( result, mw.ustring.format( formatters.tiChapter, args.chapter ) )
args.chapter = cu.makeLink( args.chapterUrl, args.chapter )
end
end
cu.insertItem( result, args.chapter, ci.formatters.tiChapter )
makePages( args, result )
makePages( args, result )
if #result > 0 then
if #result > 0 then
result = { table.concat( result, formatters.addDelimiter1 ) }
result = { table.concat( result, ci.formatters.addDelimiter1 ) }
end
end


makeDoi( args, result )
makeDoi( args, result )
makeWebInfo( args, result )
makeWebInfo( args, result )
result = table.concat( result, formatters.addDelimiter2 )
result = table.concat( result, ci.formatters.addDelimiter2 )


return makeLanguageComment( args, result )
return makeLanguageComment( args, result )
Zeile 485: Zeile 580:
local author, title
local author, title
if args.type == 'map' or args.type == 'book' then
if args.type == 'book' or args.type == 'map' then
author = makeAuthor( args.author, args.editor )
author = makeAuthor( args.author, args.editor )
title = makeTitle( args.title, args.volume, args.url, args.scale )
title = makeTitle( args.title, args.volume, args.titleAddition, args.url,
else
args.scale, 'title' )
else -- bookitem
author = makeAuthor( '', args.editor )
author = makeAuthor( '', args.editor )
title = makeTitle( args.collection, args.volume, args.url, args.scale )
title = makeTitle( args.collection, args.volume, args.titleAddition,
args.url, '', 'bookitem' )
end
end
return author .. title .. makePublished( args )
return author .. title .. makePublished( args )
Zeile 496: Zeile 593:


local function makeCollection( args )
local function makeCollection( args )
local author, collection, editor, title
local author = makeAuthor( args.author, '' )
local title = makeTitle( args.title, '', '', args.url, '', 'title' )
local editor = makeAuthor( '', args.editor )
local collection = makeTitle( args.collection, args.volume, args.titleAddition,
args.siteUrl, '', 'bookitem' )


author = makeAuthor( args.author, '' )
return author .. title .. ci.formatters.tiIn .. editor .. collection
title = makeTitle( args.title, args.volume, args.articleUrl, '' )
editor = makeAuthor( '', args.editor )
collection = makeTitle( args.collection, args.volume, args.articleUrl, '' )
 
return author .. title .. formatters.tiIn .. editor .. collection
.. makePublished( args )
.. makePublished( args )
end
end
Zeile 511: Zeile 607:
if args.type == 'journal' then
if args.type == 'journal' then
title = args.journal
title = args.journal
elseif args.type == 'newspaper' then
title = args.newspaper
else
else
title = args.newspaper
title = args.website
end
end
if title == '' then
if not cu.isSet( title ) then
title = texts.noTitel
if args.type ~= 'web' or args.type == 'webnews' then
table.insert( errorMsgs, texts.unknownPeriodical )
title = ci.texts.noTitle
end
cu.addErrorMsg( ci.texts.unknownPeriodical )
if args.url ~= '' then
end
title = '[' .. args.url .. ' ' .. title .. ']'
else
end
title = title:gsub( "''+", '' ) -- remove multiple apostrophes
if args.place ~= '' then
if args.type == 'journal' then
title = title .. mw.ustring.format( formatters.prPlace, args.place )
title = cu.formatItem( title, ci.formatters.tiJournalTitle )
end
elseif args.type == 'newspaper' then
if args.abbr ~= '' then
title = cu.formatItem( title, ci.formatters.tiNewspaperTitle )
title = title .. mw.ustring.format( formatters.prAbbr, args.abbr )
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
end
return title
return title
Zeile 532: Zeile 638:
local function makeJournalInfo( args, tab )
local function makeJournalInfo( args, tab )
local year = ''
local year = ''
if args.date ~= '' then
if cu.isSet( args.date ) then
year = getDate( args.date, dateFormat )
year = cu.getDate( args.date, args.dateFormat, ci.texts.wrongDate )
end
end
local volume = ''
local volume = ''
if args.volume ~= '' then
if cu.isSet( args.volume ) then
volume = mw.ustring.format( formatters.prVolume, args.volume )
volume = cu.formatItem( args.volume, ci.formatters.prVolume )
if args.issue ~= '' then
if cu.isSet( args.issue ) then
volume = mw.ustring.format( formatters.prVolIssue, volume, args.issue )
volume = cu.formatItem2( volume, args.issue, ci.formatters.prVolIssue )
end
end
if year ~= '' then
if year ~= '' then
volume = mw.ustring.format( formatters.prVolYear, volume, year )
volume = cu.formatItem2( volume, year, ci.formatters.prVolYear )
end
end
else
else
if args.issue ~= '' then
if cu.isSet( args.issue ) then
volume = mw.ustring.format( formatters.prIssue, args.issue )
volume = cu.formatItem( args.issue, ci.formatters.prIssue )
if year ~= '' then
if year ~= '' then
volume = mw.ustring.format( formatters.prVolYear, volume, year )
volume = cu.formatItem2( volume, year, ci.formatters.prVolYear )
end
end
else
else
Zeile 554: Zeile 660:
end
end
end
end
if volume ~= '' then
cu.insertItem( tab, volume )
table.insert( tab, volume )
end
end
end


local function makeNewspaperInfo( args, tab )
local function makeNewspaperInfo( args, tab )
if args.volume ~= '' then
local day = ''
table.insert( tab,
if cu.isSet( args.date ) then
mw.ustring.format( formatters.nsVolume, args.volume ) )
if args.dateFormat == 'j. F Y' then
end
-- following result can be ''
 
day = cu.getDate( args.date, 'l, j. F Y', ci.texts.wrongDate )
day = ''
if args.date ~= '' then
if dateFormat == 'j. F Y' then
day = getDate( args.date, 'l, j. F Y' )
else
else
table.insert( errorMsgs, texts.wrongDate )
cu.addErrorMsg( ci.texts.wrongDate )
end
end
end
end


local issue = ''
day = cu.formatItem( day, ci.formatters.puDate )
if args.issue ~= '' then
cu.insertItem( tab, args.publisher )
issue = mw.ustring.format( formatters.prIssue, args.issue )
cu.insertItem( tab, args.volume, ci.formatters.nsVolume )
if day ~= '' then
cu.insertItem( tab, args.issue, ci.formatters.prIssue )
issue = mw.ustring.format( formatters.nsNrOfDay, issue, day )
cu.insertItem( tab, day )
end
else
issue = day
end
if issue ~= '' then
table.insert( tab, issue )
end
end
end


local function makePeriodical( args )
local function makePeriodical( args )
local result = { makeAuthor( args.author, '' )
local author = makeAuthor( args.author, '' )
.. makeTitle( args.title, '', args.articleUrl, '' ) .. formatters.tiIn
.. makeTitle( args.title, '', args.titleAddition, args.url, '', 'title' )
.. makeJournalTitle( args ) }


local result = {}
local jTitle = makeJournalTitle( args )
cu.insertItem( result, jTitle )
makeIsbn( args, result )
makeIsbn( args, result )
if args.type == 'journal' then
if args.type == 'journal' then
makeJournalInfo( args, result )
makeJournalInfo( args, result )
else
else -- newspaper and web
makeNewspaperInfo( args, result )
makeNewspaperInfo( args, result )
end
end
Zeile 602: Zeile 698:
makeDoi( args, result )
makeDoi( args, result )
makeWebInfo( args, result )
makeWebInfo( args, result )
result = table.concat( result, formatters.addDelimiter1 )
if #result > 0 then
 
result[ 1 ] = mw.ustring.gsub( result[ 1 ], '^%l', mw.ustring.upper )
return makeLanguageComment( args, result )
end
 
local function prepareForCOinS( args )
args.date = args.date:match( '%d+' ) or ''
args.pages = args.pages:match( '%d+%-%d+' ) or args.pages:match( '%d+' )
args.columns = args.columns:match( '%d+%-%d+' ) or args.columns:match( '%d+' )
 
-- only first author
local at = args.author:find( ';' ), count
if at then
args.author = mw.text.trim( args.author:sub( 1, at - 1 ) )
else
_,count = args.author:gsub( '@', '@' )
if count > 1 then
at = args.author:find( ',' )
args.author = mw.text.trim( args.author:sub( 1, at - 1 ) )
end
end
end
 
local function makeCOinS( args )
local rft = {}, key, value
 
for key, value in pairs( params ) do
if value.COinS and value.COinS:find( 'rft.' ) and args[ key ] and args[ key ] ~= '' then
table.insert( rft, value.COinS .. '=' .. mw.uri.encode( '' .. args[ key ] ) )
end
end
end
result = table.concat( result, ci.formatters.addDelimiter1 )


if next( rft ) then
return author .. makeLanguageComment( args, result )
if args.type == 'book' or args.type == 'map' or args.type == 'collection' then
if args.type == 'collection' then
table.insert( rft, 'rft.atitle=' .. mw.uri.encode( args.title ) )
table.insert( rft, 'rft.btitle=' .. mw.uri.encode( args.collection ) )
table.insert( rft, 1, 'rft.genre=bookitem' )
else
table.insert( rft, 'rft.btitle=' .. mw.uri.encode( args.title ) )
table.insert( rft, 1, 'rft.genre=book' )
end
table.insert( rft, 1, 'rft_val_fmt=' .. mw.uri.encode( 'info:ofi/fmt:kev:mtx:book' ) )
else
table.insert( rft, 1, 'rft.genre=journal' )
table.insert( rft, 1, 'rft_val_fmt=info:ofi/fmt:kev:mtx:journal' )
if args.type == 'journal' then
table.insert( rft, 'rft.jtitle=' .. mw.uri.encode( args.journal ) )
else
table.insert( rft, 'rft.jtitle=' .. mw.uri.encode( args.newspaper ) )
end
table.insert( rft, 'rft.atitle=' .. mw.uri.encode( args.title ) )
end
table.insert( rft, 1, 'ctx_ver=Z39.88-2004' )
rft = table.concat( rft, '&' )
return '<span class="Z3988" title="' .. rft .. '"></span>'
end
end
 
-- remove adjoining punctuation marks
local function finalCleanup( s )
s = mw.ustring.gsub( s, '%.+%.', '.' )
s = mw.ustring.gsub( s, '([!%?])(%s%.+)', '%1' )
return mw.ustring.gsub( s, '([,;:])(%s%.+)', '.' )
end
end


local function makeCitation( frameArgs )
local function makeCitation( frameArgs )
local args, citation
local args = getValidArgs( frameArgs )
args = checkParams( frameArgs )
checkValues( args )
checkValues( args )


local citation
if args.type == 'map' or args.type == 'book' then
if args.type == 'map' or args.type == 'book' then
citation = makeBook( args )
citation = makeBook( args )
elseif args.type == 'collection' then
elseif args.type == 'bookitem' then
citation = makeCollection( args )
citation = makeCollection( args )
elseif args.type == 'journal' or args.type == 'newspaper' then
elseif args.type == 'journal' or args.type == 'newspaper'
or args.type == 'web' or args.type == 'webnews' then
citation = makePeriodical( args )
citation = makePeriodical( args )
else
else
citation = texts.wrongType
args.type = 'book'
citation = ci.texts.wrongType .. makeBook( args )
end
end


citation = finalCleanup( citation )
citation = cu.finalCleanup( citation )
prepareForCOinS( args )
if cu.isSet( args.access ) then
 
citation = citation
return table.concat( errorMsgs, ' ' )
.. '&nbsp;<span class="voy-cite-access">'
.. '<cite style="font-style: normal;" class="citation ' .. args.type
.. ci.accessTypes[ args.access ].file .. '</span>'
.. ' printNoLink">' .. citation .. '</cite>' .. makeCOinS( args )
end
end
cc.prepareForCOinS( args )
 
function ci.book( frame )
local args = frame:getParent().args, ok
args.type = 'book'
return makeCitation( args )
end


function ci.map( frame )
return cu.getErrorMsgs()
local args = frame:getParent().args
.. tostring( mw.html.create( 'cite' )
args.type = 'map'
:attr( 'class', ci.citeClass .. ci.addCiteClasses[ args.type ] )
return makeCitation( args )
:wikitext( citation )
)
.. cc.makeCOinS( args )
end
end


function ci.collection( frame )
function ct.citation( frame )
local fType = frame.args.type
local args = frame:getParent().args
local args = frame:getParent().args
args.type = 'collection'
return makeCitation( args )
end


function ci.journal( frame )
if cu.isSet( fType ) then
local args = frame:getParent().args
args.type = fType
args.type = 'journal'
else
return makeCitation( args )
args.type = cu.getKey( cu.getArgValue( ci.params, 'type', args ), ci.refTypes )
end
end
 
if not cu.isSet( args.type ) then
function ci.newspaper( frame )
if cu.getArgValue( ci.params, 'scale', args ) ~= '' then
local args = frame:getParent().args
args.type = 'map'
args.type = 'newspaper'
elseif cu.getArgValue( ci.params, 'collection', args ) ~= '' then
return makeCitation( args )
args.type = 'bookitem'
end
elseif cu.getArgValue( ci.params, 'journal', args ) ~= '' then
 
args.type = 'journal'
function ci.citation( frame )
elseif cu.getArgValue( ci.params, 'newspaper', args ) ~= '' then
local args = frame:getParent().args
args.type = 'newspaper'
 
elseif cu.getArgValue( ci.params, 'website', args ) ~= '' then
aType = getArgValue( 'type', args )
args.type = 'web'
if not aType or aType == '' or not inArray( types, aType ) then
if getArgValue( 'scale', args ) ~= '' then
aType = 'map'
elseif getArgValue( 'collection', args ) ~= '' then
aType = 'collection'
elseif getArgValue( 'journal', args ) ~= '' then
aType = 'journal'
elseif getArgValue( 'newspaper', args ) ~= '' then
aType = 'newspaper'
else
else
aType = 'book'
args.type = 'book'
end
end
args.type = aType
end
end
return makeCitation( args )
return cu.templateStyles( frame ) .. makeCitation( args )
end
end


return ci
return ct

Aktuelle Version vom 11. Februar 2023, 20:58 Uhr

Die Dokumentation für dieses Modul kann unter Modul:Citation/doc erstellt werden

-- documentation
local citation = {
	suite  = 'Citation',
	serial = '2022-10-21',
	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 i = 0
	for _, key in ipairs( keys ) do
		if cu.isSet( args[ key ] ) then
			i = i + 1
			if i > 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 _, 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 _, 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

-- make title part
local function makeTitle( 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 = cu.formatItem( title, ci.formatters.tiTitle )
	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 _, 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 kb
	if cu.isSet( args.url ) or cu.isSet( args.originalUrl ) or cu.isSet( args.archiveUrl ) 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 index, value in ipairs( { 'PDF', 'DOC', 'DOCX', 'RTF', 'ODT',
				'PPT', 'PPTX', 'XLS', 'XLSX' } ) do
				if cu.hasExtension( args.url, value ) then
					table.insert( tab, value )
					break
				end
				if cu.hasExtension( args.archiveUrl, value ) then
					table.insert( tab, value )
					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 makeLanguageComment( args, result )
	local ok = true
	if cu.isSet( args.language ) then
		local parts = mw.text.split( args.language, ' ' )
		for i = 1, #parts, 1 do
			parts[ i ] = mw.text.trim( parts[ i ]:gsub( ',', '' ) )
			if parts[ i ]:match( '^%a%a%a?$' ) then
				parts[ i ] = mw.language.fetchLanguageName( parts[ i ],
					mw.language.getContentLanguage():getCode() )
				if parts[ i ] == '' then
					ok = false
					break
				end
			else
				ok = false
				break
			end
		end
		if ok and #parts > 0 then
			args.language = table.concat( parts, ', ' )
			args.language = cu.formatItem( args.language, ci.formatters.addInLanguage )
		end
	end
	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.title, args.volume, args.titleAddition, args.url,
			args.scale, 'title' )
	else -- bookitem
		author = makeAuthor( '', args.editor )
		title = makeTitle( 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.title, '', '', args.url, '', 'title' )
	local editor = makeAuthor( '', args.editor )
	local collection = makeTitle( 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 )
		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.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 )

	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