Questa pagina è protetta dallo spostamento
Questa pagina è protetta

Modulo:Citazione

Da Wikipedia, l'enciclopedia libera.
Vai alla navigazione Vai alla ricerca

Modulo Lua per la riproduzione delle funzioni dei vari template {{Cita libro}}, {{Cita web}}, {{Cita news}}, {{Cita pubblicazione}}, {{Cita conferenza}} e {{Cita video}}.

Quelle che seguono sono note tecniche sul funzionamento del modulo. Per le istruzioni su come usarlo per inserire citazioni nelle voci vedi il manuale di{{Cita testo}}.

Sottomoduli

  • Modulo:Citazione/Configurazione- Contiene le tabelle di configurazione con i nomi dei parametri, i messaggi di errore, i caratteri di separazione...
  • Modulo:Citazione/Whitelist- Contiene le tabelle dei parametri accettati dal modulo per poter identificare parametri con un nome errato.
  • Modulo:Citazione/Suggerimenti- Contiene una tabella in cui è possibile inserire nomi di parametri che vengono sbagliati spesso e suggerire nel messaggio d'errore il nome del parametro corretto.
  • Modulo:Citazione/Argomenti- Serve a generare Modulo:Citazione/Whitelist ed è usato una tantum.

Funzioni accessorie

Nel seguito per settata si intende una variabile diversa da nil e da stringa nulla

is_set(var)
vera se una variabile è settata
first_set(...)
ritorna la prima variabile settata
inArray( needle, haystack )
scandisce l'arrayhaystacke ritorna la posizione in cui si trova il valoreneedle.Seneedlenon si trova inhaystacko ènilritornafalse
substitute( msg, args )
ritorna la stringamsgcompilata usando la tabella di valoriargs.Basata sulla funzionemw.message.newRawMessage,non granchè documentata, apparentemente nella stringa i$nvengono sostituiti dal valore in posizione ennesima inargs.Seargsè nil ritorna nil
wrap( key, str, lower )
formatta il messaggiokeycon la stringastr.keydeve essere un indice della tabellacitation_config.messages.Selowerè vero il messaggio viene messo in minuscolo prima di inserirestr
debug_msg(msg)
inserisce un messaggio di debug nella coda dei messaggi di errore per essere emesso a video
debug_value(name, value)
inserisce il messaggio di debugname=value.Usata per emettere il valore di una variabile, da usare per esempio come debug_value('name', name)
argument_wrapper( args )
restituisce una tabella per accedere ai valori della tabella originaleargsmediante una tabella di alias. Data l'istruzioneA=argument_wrapper(args)la chiamataA[key]il valoreargs[first_set(citation_config.aliases[key])].Questo permette la localizzazione dei parametri e la creazione di alias per lo stesso valore. Per esempio secitation_config.aliases['Chapter'] = {'capitolo', 'contributo', 'voce', 'articolo', 'sezione' }la chiamataA['Chapter']resituirà uno dei valori settati traargs['capitolo'],args['contributo'],args['voce'],args['articolo'],args['sezione'].Aggiunge inoltre il metodo A:ORIGIN che restituisce l'alias con il quale è stato trovato un valore. I valori trovati vengono bufferizzati in una tabella interna.
Aggiunge un messaggio alla coda di errori se:
  • keynon è presente incitation_config.aliases
  • keyè una tabella di valori e più di uno di questi è settato
  • se inargsnon viene trovato alcun valore corrispondente a uno degli alias dikeyritorna stringa vuota ""
validate(name)
ritornatruesenamenon è nil ed è il nome di un parametro accettato,falsein caso contrario
errorcomment( content, hidden )
formatta il commentocommentper la visualizzazione, sehiddenètrueil codice sarà inserito ma non visibile salvo analizzare il codice html della pagina, altrimenti sarà formattato come da settaggio delle classi "error" e "citation-comment" nel css (normalmente una scritta in rosso)
seterror( error_id, arguments, raw, prefix, suffix )
formatta il commento con codiceerror_idcon la tabella di argomentiarguments.Se valorizzatiprefixesuffixvengono aggiunti rispettivamente prima e dopo il messggio. Serawètrueil messaggio viene ritornato senza essere passato prima pererrorcomment.
la chiaveerror_idfa riferimento alla tabella di messaggicitation_config.error_conditionsche per ogni codice di errore restituisce il messaggio da formattare, la categoria di errore in cui inserire la voce e se il messaggio deve essere visibile o nascosto.

Fragment

Per gestire l'unione dei pezzi di citazione, viene definito un "oggetto" Lua (in realtà una tabella con una metatable che definisce alcuni metodi aggiuntivi). Unfragmentè composto da un array il cui primo elemento è un stringa da inserire all'inizio della sequenza, seguito da uno o più stringhe e terminati da una stringa da inserire al termine della sequenza. Quando due frammentif1ef2vengono uniti (vedifragment.appendefragment.appends) viene valutata la priorità dell'ultimo separatore dif1e quella del primo dif2e conservato solo quello con priorità maggiore. Il nuovo frammento avrà il separatore iniziale dif1e quello finale dif2.

Fragment.new(text, sep_key)
crea un pseudooggetto Lua che memorizza l'array di stringhetextusando come separatore tra una stringa e l'altrasep_key.Setta come separatore iniziale per la sequenza la stringa nulla e come separatore finalesep_key.Ritorna l'oggetto creato.
Sep_keydeve essere una chiave della tabellaFragment.priorityche per ogni separatore indica la sua priorità (quindi quale separatore prevale quando due frammenti vengono uniti) e cosa inserire esattamente (per esempio per "," inserisce in realtà "," — aggiunge cioè lo spazio). La tabella è caricata dal modulo di configurazione, un esempio è:
[ "" ] = { order=0, sep = "" },
[ "" ] = { order=1, sep = "" },
[ "," ] = { order=2, sep = "," },
[ "." ] = { order=3, sep = "." },
[ "in" ] = {order=4, sep = "in" },
[ "" ] = { order=5, sep = "" },spazio semplice che però prevale su altri separatori
[ "nothing" ] = {order=6, sep= "" }stringa nulla che prevale su tutto (per forzare nessun separatore a inizio citazione)
Fragment:start(sep_key)
setta come separatore inizialesep_key
Fragment:last(sep_key)
setta come separatore finalesep_key
Fragment:empy(sep_key)
ritornatruese fragment è un frammento vuoto (contiene un array di stringhe vuoto)
Fragment:append(txr)
appende il frammento o strignatxrin fondo afragment(nel caso chetxrè una stringa la trasforma infragmentconsep_keyuguale a quella del frammento a cui viene appesa)
Fragment:appends(txr)
appende un array misto di frammenti/stringhe

-- Modulo per la gestione delle citazioni, originariamente importato dalla
-- revisione 555909894 del 20/5/2013 da [[:en:Module:Citation/CS1]]

--[[ ===============================================================================
Variabile in cui vengono memorizzate le condizioni di errore registrate durante l'esecuzione
delle funzioni del modulo.
===============================================================================]]
localz={
error_categories={};-- lista delle categorie di errore
error_ids={};-- lista dei codici di errore
message_tail={};-- messaggi di errore da visualizzare in coda alla citazione
}

--[[ ===============================================================================
Carica la tabella di configurazione, correggendo il nome se caricato da sandbox
-- nota: non ancora attiva per qualche motivo non funziona
===============================================================================]]
localfunctionload_configuration_table(name)
localframe=mw.getCurrentFrame()
localreal_name=name
ifnil~=string.find(frame:getTitle(),'sandbox',1,true)then
real_name=real_name..'/sandbox'
end
returnmw.loadData(real_name)
end

--[[ ===============================================================================
Caricamento delle tabelle di configurazione del modulo.
===============================================================================]]
localcfg=mw.loadData('Module:Citazione/Configurazione')
--local cfg = load_configuration_table('Module:Citazione/Configurazione')

--[[ ===============================================================================
Lista di tutti i parametri riconosciuti.
===============================================================================]]
localwhitelist=mw.loadData('Module:Citazione/Whitelist')
--local whitelist = load_configuration_table('Module:Citazione/Whitelist')

--[[ ===============================================================================
Ritorna true se una variabile è settata (diversa da nil e da stringa vuota)
===============================================================================]]
localfunctionis_set(var)
returnnot(var==nilorvar=='');
end

-- Ritorna il nostro {{Collegamento interrotto}}
localfunctioninterrupted_url()
returnmw.getCurrentFrame():expandTemplate{title='Collegamento interrotto'}
end

--[[ ===============================================================================
Ritorna la prima variabile settata di quelle passate alla funzione
===============================================================================]]
localfunctionfirst_set(...)
locallist={...};
for_,varinpairs(list)do
ifis_set(var)then
returnvar;
end
end
end

--[[ ===============================================================================
Ritorna la posizione di needle nella lista haystack, altrimenti ritorna false
===============================================================================]]
localfunctionin_array(needle,haystack)
ifneedle==nilthenreturnfalse;end
forn,vinipairs(haystack)do
ifv==needlethenreturnn;end
end
returnfalse;
end

--[[ ===============================================================================
Popola gli argomenti numerati nella stringa msg usando la tabella di argomenti args
===============================================================================]]
localfunctionsubstitute(msg,args)
returnargsandmw.message.newRawMessage(msg,args):plain()ormsg;
end

--[[ ===============================================================================
Rende la stringa sicura per il markup corsivo ''... ''
Nota: non si può usare <i> per il corsivo poichè il comportamento atteso se lo si
specifica per i titoli è di renderli non corsivi. Inoltre <i> e '' interagiscono
male con la funzione HTML tidy di Mediawiki
===============================================================================]]
localfunctionsafe_for_italics(str)
ifnotis_set(str)then
returnstr;
else
ifstr:sub(1,1)=="'"thenstr="<span></span>"..str;end
ifstr:sub(-1,-1)=="'"thenstr=str.."<span></span>";end

-- Rimuove le andate a capo perché rompono il corsivo.
returnstr:gsub('\n',' ');
end
end

--[[ ===============================================================================
Ritorna true/false a seconda che la stringa si possa scrivere in corsivo
===============================================================================]]
localfunctionis_italicizable(str)
returnrequire('Modulo:Valido in corsivo')._main({str})
end

--[[ ===============================================================================
Restituisce un messaggio dalla tabella cfg.messages in cui viene inserita una stringa
- key: codice del messaggio da visualizzare in cfg.messages
- str: una stringa da inserire nel messaggio, se non è definita o uguale a stringa
vuota la funzione ritorna una stringa vuota
===============================================================================]]
localfunctionwrap(key,str)
ifnotis_set(str)then
return"";
elseifin_array(key,{'italic-title','trans-italic-title'})then
str=safe_for_italics(str);
end
returnsubstitute(cfg.messages[key],{str});
end

--[[ ===============================================================================
Inserisce un messaggio di debug da visualizzare in coda alla citazione
===============================================================================]]
localfunctiondebug_msg(msg)
table.insert(z.message_tail,{set_error('debug_txt',{msg},true)});
end

--[[ ===============================================================================
A scopo di debug, aggiunge la stringa 'name=<value>' in coda alla citazione
===============================================================================]]
localfunctiondebug_value(name,value)
ifnotvaluethenvalue='nil'end
debug_msg(name..'= "'..value..' "')
end

--[[ ===============================================================================
Formatta un commento per identificare gli errori, aggiungendo la classe css per
renderlo visibile o meno
===============================================================================]]
localfunctionerror_comment(content,hidden)
returnwrap(hiddenand'hidden-error'or'visible-error',content);
end

--[[ ===============================================================================
Imposta un condizione di errore e ritorna un messaggio appropriato. L'inserimento
del messaggio nell'output è di responsabilità della funzione chiamante
-- -- error_id: codice dell'errore (una chiave valida per cfg.error_conditions)
-- -- arguments: una lista di argomenti opzionali per la formattazione del messaggio
-- -- raw: ritorna una coppia: {messaggio di errore, visibilità} invece del messaggio
-- di errore formattato
-- -- prefix: stringa da aggiungere in testa al messaggio
-- -- suffix: stringa da aggiungere in coda al messaggio
===============================================================================]]
localfunctionset_error(error_id,arguments,raw,prefix,suffix)
localerror_state=cfg.error_conditions[error_id];

prefix=prefixor"";
suffix=suffixor"";

iferror_state==nilthen
error(cfg.messages['undefined_error']);
elseifis_set(error_state.category)then
table.insert(z.error_categories,error_state.category);
end

localmessage=substitute(error_state.message,arguments);

message=mw.ustring.format(
'%s ([[%s#%s|%s]])',
message,cfg.messages['help page link'],error_state.anchor,
cfg.messages['help page label']
)

z.error_ids[error_id]=true;
ifin_array(error_id,{'bare_url_missing_title','trans_missing_title'})
andz.error_ids['citation_missing_title']then
return'',false;
end

message=table.concat({prefix,message,suffix});
ifraw==truethenreturnmessage,error_state.hiddenend
returnerror_comment(message,error_state.hidden);
end

--[[ ===============================================================================
Cerca il primo parametro settato da una lista di parametri e genera un errore se
più di un parametro è settato.
Ritorna la coppia (value, selected) dove value è il valore del parametro trovato e
selected il nome del parametro trovato
===============================================================================]]
localfunctionselect_one(args,possible,error_condition,index)
localvalue=nil;
localselected='';
localerror_list={};

ifindex~=nilthenindex=tostring(index);end

-- Handle special case of "#" replaced by empty string
ifindex=='1'then
for_,vinipairs(possible)do
v=v:gsub("#","");
ifis_set(args[v])then
ifvalue~=nilandselected~=vthen
table.insert(error_list,wrap('parameter',v));
else
value=args[v];
selected=v;
end
end
end
end

for_,vinipairs(possible)do
ifindex~=nilthen
v=v:gsub("#",index);
end
ifis_set(args[v])then
ifvalue~=nilandselected~=vthen
table.insert(error_list,wrap('parameter',v));
else
value=args[v];
selected=v;
end
end
end

if#error_list>0then
-- genera il messaggio di errore concatenando i parametri duplicati
localerror_str="";
if#error_list==1then
error_str=error_list[1]..cfg.messages['parameter-pair-separator'];
else
error_str=table.concat(error_list,cfg.messages['parameter-separator'])..cfg.messages['parameter-final-separator'];
end
error_str=error_str..wrap('parameter',selected);
table.insert(z.message_tail,{set_error(error_condition,{error_str},true)});
end
returnvalue,selected;
end

--[[ ===============================================================================
Funzione di supporto per la mappatura degli argomenti del file di configurazione,
così che nomi multipli possono essere assegnati ad una singola variabile interna
===============================================================================]]
localfunctionargument_wrapper(args)
localorigin={};

returnsetmetatable({
ORIGIN=function(self,k)
localdummy=self[k];--force the variable to be loaded.
returnorigin[k];
end
},
{
__index=function(tbl,k)
iforigin[k]~=nilthen
returnnil;
end

localargs,list,v=args,cfg.aliases[k];

iftype(list)=='table'then
v,origin[k]=select_one(args,list,'redundant_parameters');
iforigin[k]==nilthen
origin[k]='';-- Empty string, not nil
end
elseiflist~=nilthen
v,origin[k]=args[list],list;
else
-- maybe let through instead of raising an error?
-- v, origin[k] = args[k], k;
error(cfg.messages['unknown_argument_map']);
end

-- Empty strings, not nil;
ifv==nilthen
v=cfg.defaults[k]or'';
origin[k]='';
end

tbl=rawset(tbl,k,v);
returnv;
end,
});
end

--[[ ===============================================================================
Controlla che il nome di un parametro sia valido usando la whitelist
===============================================================================]]
localfunctionvalidate(name)
name=tostring(name);
-- Normal arguments
ifwhitelist.basic_arguments[name]thenreturntrueend
-- Arguments with numbers in them
name=name:gsub("%d+","#");
ifwhitelist.numbered_arguments[name]thenreturntrueend
-- Not found, argument not supported.
returnfalse
end

--[[ ===============================================================================
Oggetto per memorizzare gli elementi di una citazione. Un frammento di citazione è
formato dai seguenti elementi:
- self[n]: n-esimo elemento da unire, è una lista di stringhe inframezzata dai
separatori da usare per unirle.
- self.last_priority: priorità del separatore di chiusura
- self.first_priority: priorità del separatore di apertura
- self.sep_key: codice del carattere separatore di default da usare
se unita a un altro frammento
===============================================================================]]
localFragment={}

Fragment.precedence=cfg.style.separator_priority
localFragment_mt={__index=Fragment}

Fragment.new=function(texts,sep_key)
iftype(texts)=="string"thentexts={texts}end
ifnotFragment.precedence[sep_key]thensep_key=""end
localtx={}
tx.last_priority=0
tx.first_priority=0
tx.sep_key=sep_key
tx[1]=""
for_,elinipairs(texts)do
ifel~=""then
tx[#tx+1]=el
tx[#tx+1]=Fragment.precedence[tx.sep_key].sep
end
end
if#tx>1then
tx.last_priority=Fragment.precedence[tx.sep_key].order
else
tx[1]=""
end
setmetatable(tx,Fragment_mt)
returntx
end

--- cambia il separatore iniziale di un frammento di citazione
functionFragment:start(sep_key)
if#self==0thenreturnselfend
localseparator=Fragment.precedence[sep_key]orFragment.precedence[""]
self[1]=separator.sep
self.first_priority=separator.order
returnself
end

-- cambia il separatore finale di un frammento di citazione
functionFragment:last(sep_key)
if#self==0thenreturnselfend
localseparator=Fragment.precedence[sep_key]orFragment.precedence[""]
self[#self]=separator.sep
self.last_priority=separator.order
returnself
end

-- ritorna un frammento di citazione vuoto
functionFragment:empty()
return#self==0
end

-- appende una stringa o un frammento di citazione in coda
functionFragment:append(txr)
iftxr==nilthenreturnselfend
iftype(txr)=="string"thentxr=Fragment.new(txr,self.sep_key)end
if#txr==0thenreturnselfend
if#self==0thenself[1]=txr[1]end
self.last_priority=self.last_priorityor0
ifself.last_priority<txr.first_prioritythen
self[#self]=txr[1]
end
fori,elinipairs(txr)do
ifi>1thenself[#self+1]=elend
end
self.last_priority=txr.last_priority
--self.sep_key = txr.sep_key
returnself
end

-- appende una lista di stringhe o frammenti di citazione
functionFragment:appends(fragments)
for_,finipairs(fragments)do
self:append(f)
end
returnself
end

-- collassa il frammento in una stringa e la restituisce
Fragment_mt.__tostring=function(tx)
returntable.concat(tx,'')
end
-- =====================================================================
-- Fine definizione oggetto Fragment
-- =====================================================================

--[[ ===============================================================================
Formatta un wikilink interno o un link esterno a un documento
- options.code_id: codice per il link esterno
- options.id: etichetta del link esterno o id del documento
- options.encode: se true o nil l'url viene codificato (en:Percent-encoding)
- options.link: link alla voce wiki sul codice documento
- options.label: etichetta del link alla voce wiki sul codice documento
- options.separator: separatore tra codice e link (di default uno spazio unificatore)
- options.pattern: pattern del link in cui "$1" è l'id normale e "$2" l'id nell'url esterno
===============================================================================]]
localfunctionlink_id(options)
localurl_string=options.code_idoroptions.id;
ifoptions.encode==trueoroptions.encode==nilthen
url_string=mw.uri.encode(url_string);
end
forwinmw.ustring.gmatch(options.pattern,'$1')do
options.pattern=mw.ustring.gsub(options.pattern,'^(%[[^%[]%S+)$1(.-%])','%1$2%2');
options.pattern=mw.ustring.gsub(options.pattern,'([^%[]%[[^%[]%S+)$1(.-%])','%1$2%2');
end
returnmw.ustring.format('[[%s|%s]]%s%s',
options.link,options.label,options.separatoror"",
substitute(options.pattern,{mw.text.nowiki(options.id),url_string})
);
end

--[[ ===============================================================================
Determina se un URL è corretto. Al momento controlla solo la stringa inizia con
prefisso URI valido e che non contenga spazi
TODO: aggiungere controlli più stringenti (vedi en.wiki)
===============================================================================]]
localfunctioncheck_url(url_str)
-- se contiene spazi non può essere un url corretto
ifnil==url_str:match("^%S+$")then
returnfalse;
end
-- Protocol-relative or URL scheme
returnurl_str:sub(1,2)=="//"orurl_str:match("^[^/]*:")~=nil;
end

--[[ ===============================================================================
Rende una stringa sicura per essere usata come descrizione di un url
===============================================================================]]
localfunctionsafe_for_url(str)
ifstr:match("%[%[.-%]%]")~=nilthen
table.insert(z.message_tail,{set_error('wikilink_in_url',{},true)});
end

returnstr:gsub('[%[%]\n]',{
['[']='&#91;',
[']']='&#93;',
['\n']=' '});
end

--[[ ===============================================================================
Formatta un collegamento esterno con controllo degli errori
- URL: url del link esterno
- label: etichetta del link esterno (se non inserita viene usato
URL come etichetta e segnalato l'errore)
- source: parametro in cui è contenuto l'url
===============================================================================]]
localfunctionexternal_link(URL,label,source)
localerror_str="";
ifnotis_set(label)then
label=URL;
ifis_set(source)then
error_str=set_error('bare_url_missing_title',{wrap('parameter',source)},false,"");
else
error(cfg.messages["bare_url_no_origin"]);
end
end
ifnotcheck_url(URL)then
error_str=set_error('bad_url',{},false,"")..error_str;
end
returntable.concat({"[",URL,"",safe_for_url(label),"]",error_str});
end

--[[ ===============================================================================
Aggiunta collegamenti multipli, per ora usati solo dal modulo Collegamenti esterni
===============================================================================]]
localfunctionappend_links(value,links)
iftype(links)=='table'then
for_,tinipairs(links)do
t[2]=is_italicizable(t[2])andwrap('italic-title',t[2])ort[2]
value=value..' / '..external_link(t[1],t[2])
end
end
returnvalue
end

--[[ ===============================================================================
Formatta un DOI e controlla per errori
===============================================================================]]
localfunctiondoi(id,inactive)
localcat=""
localhandler=cfg.id_handlers['DOI'];

localtext;
ifis_set(inactive)then
localinactive_year=inactive:match("%d%d%d%d")or''
--text = "[[".. handler.link.. "|".. handler.label.. "]]:".. id;
ifis_set(inactive_year)then
table.insert(z.error_categories,"Pagine con DOI inattivo dal"..inactive_year);
else
table.insert(z.error_categories,"Pagine con DOI inattivo");-- when inactive doesn't contain a recognizable year
end
inactive="("..cfg.messages['inactive']..""..inactive..")"
end
text=link_id({link=handler.link,label=handler.label,
pattern=handler.pattern,id=id,separator=handler.separator,encode=handler.encode})..(inactiveor'')
ifnil==id:match("^10%.[^%s–]-/[^%s–]-[^%.,]$")then-- doi must begin with '10.', must contain a fwd slash, must not contain spaces or endashes, and must not end with period or comma
cat=set_error('bad_doi');
end
returntext..cat
end

--[[ ===============================================================================
Formatta un link a Open library e controlla per errori
===============================================================================]]
localfunctionopen_library(id)
localcode=id:sub(-1,-1)
localhandler=cfg.id_handlers['OL'];
if(code=="A")then
returnlink_id({link=handler.link,label=handler.label,
pattern="[[openlibrary:authors/OL$1|$1]]",id=id,separator=handler.separator,
encode=handler.encode})
elseif(code=="M")then
returnlink_id({link=handler.link,label=handler.label,
pattern="[[openlibrary:books/OL$1|$1]]",id=id,separator=handler.separator,
encode=handler.encode})
elseif(code=="W")then
returnlink_id({link=handler.link,label=handler.label,
pattern="[[openlibrary:works/OL$1|$1]]",id=id,separator=handler.separator,
encode=handler.encode})
else
returnlink_id({link=handler.link,label=handler.label,
pattern="[[openlibrary:OL$1|$1]]",id=id,separator=handler.separator,
encode=handler.encode})..
' '..set_error('bad_ol');
end
end

--[[ ===============================================================================
Formatta un link alla libreria Opac mediante SBN e controlla per errori
===============================================================================]]
localfunctionsbn(id)
localhandler=cfg.id_handlers['SBN']
localstart_match,end_match,cd1,cd2=string.find(id,'^IT\\ICCU\\(...)\\(%d+)')
ifnot(cd1andcd2)then
start_match,end_match,cd1,cd2=string.find(id,'^IT\\ICCU\\(....)\\(%d+)')
end
ifcd1andcd2then
returnlink_id({link=handler.link,label=handler.label,
pattern='[http://opac.sbn.it/bid/$1 $1]',id=id,code_id=cd1..cd2,
encode=handler.encode})
else
returnlink_id({link=handler.link,label=handler.label,
pattern='[http://opac.sbn.it/bid/$1 $1]',id=id,
encode=handler.encode})..' '..set_error('bad_sbn')
end
end

--[[ ===============================================================================
Nice Opaque Identifiern utilisé par les formats Ark pour générer une clé
adattato da fr:Module:Biblio/Références
===============================================================================]]
localfunctionark_id(base)
base=tostring(base)
ifbasethen
localxdigits='0123456789bcdfghjkmnpqrstvwxz'
localsum=0
localposition
fori=1,base:len()do
position=xdigits:find(base:sub(i,i),1,true)or1
sum=sum+i*(position-1)
end
localindex=sum%29+1
returnxdigits:sub(index,index)
end
end

--[[ ===============================================================================
Formatta un link alla Bibliothèque Nationale de France e controlla per errori
adattato da fr:Module:Biblio/Références
===============================================================================]]
localfunctionbnf(id)
localhandler=cfg.id_handlers['BNF']
ifidthen
localtxt=id
localerror_code=''
localbnf_id=id:upper():match('BNF(%d+%w)')orid:lower():match('cb(%d+%w)')orid:match('^%d+%w')

ifbnf_idthen
-- bnf contient une suite de chiffres qui peut être un ark valide
localbase=bnf_id:sub(1,8)
ifbnf_id:len()==8then
-- il manque la clé, on l'ajoute
id=base..ark_id('cb'..base)
txt=base
elseifbnf_id:len()>8andbnf_id:sub(9,9)==ark_id('cb'..base)then
-- ark valide
id=bnf_id:sub(1,9)
txt=base
else
-- ark qui semble non valide
id=bnf_id
txt=bnf_id
error_code=set_error('bad_bnf')
end
else
-- le paramètre ne semble pas un ark valide
error_code=set_error('bad_bnf')
end

-- dans tous les cas on renvoie l'adresse, on catégorise juste pour vérifier ce qui ne va pas
returnlink_id({
link=handler.link,
label=handler.label,
pattern=handler.pattern,
id=txt,
code_id=bnf_id,
separator=handler.separator
})..' '..error_code
end
end

--[[ ===============================================================================
Rimuove text e trattini irrilevanti da un numero isbn
===============================================================================]]
localfunctionclean_isbn(isbn_str)
returnisbn_str:gsub("[^-0-9X]","");
end

--[[ ===============================================================================
Determina se una stringa ISBN è valida
===============================================================================]]
localfunctioncheck_isbn(isbn_str)
isbn_str=clean_isbn(isbn_str):gsub("-","");

locallen=isbn_str:len();

iflen~=10andlen~=13then
returnfalse;
end
localtemp=0;
iflen==10then
ifisbn_str:match("^%d*X?$")==nilthenreturnfalse;end
isbn_str={isbn_str:byte(1,len)};
fori,vinipairs(isbn_str)do
ifv==string.byte("X")then
temp=temp+10*(11-i);
else
temp=temp+tonumber(string.char(v))*(11-i);
end
end
returntemp%11==0;
else
ifisbn_str:match("^%d*$")==nilthenreturnfalse;end
isbn_str={isbn_str:byte(1,len)};
fori,vinipairs(isbn_str)do
temp=temp+(3-2*(i%2))*tonumber(string.char(v));
end
returntemp%10==0;
end
end

--[[ ===============================================================================
Ritorna la sola etichetta visibile di un wikilink
===============================================================================]]
localfunctionremove_wikilink(str)
-- Sia [[A|B]] che [[B]] ritornano B
return(str:gsub("%[%[([^%[%]]*)%]%]",function(l)
returnl:gsub("^[^|]*|(.*)$","%1"):gsub("^%s*(.-)%s*$","%1");
end));
end

--[[ ===============================================================================
Riconosce le date nel formato ISO yyyy-mm-dd e le riformatta in dmy. Si assicura
che 01 e 1 siano resi come 1º qualora indichino il giorno.
===============================================================================]]
localfunctionget_date(str)
ifis_set(str)then
localtry_year,try_month,try_day=string.match(str,'^(%d%d%d%d)-(%d%d)-(%d%d)$')
iftry_daythen
localMonth=cfg.months[tonumber(try_month)]
ifMonththen
try_day=try_day=='01'and'1º'ortonumber(try_day)
returnstring.format("%s %s %s",try_day,Month,try_year)
end
end
try_day,try_month,try_year=string.match(str,'^(%d%d?) (%a+) (%d%d%d%d)$')
iftry_daythen
try_day=(try_day=='1'ortry_day=='01')and'1º'ortonumber(try_day)
returnstring.format("%s %s %s",try_day,try_month,try_year)
end
end
returnstr
end

--[[ ===============================================================================
Unisce year, day e month ritornando la data come un'unica stringa.
month è controllato solo se year è definito, e day è controllato solo se month è definito.
Se month è un numero tenta di convertilo nel nome corrispondente (1->gennaio, 2->febbraio...),
altrimenti non lo modifica
===============================================================================]]
localfunctionget_date_yyyy_mm_dd(year,month,day)
localdate=year
ifis_set(date)then
ifis_set(month)then
localmonth=cfg.months[tonumber(month)]ormonth
date=month..""..year
ifis_set(day)then
ifday=="01"orday=="1"thenday="1º"end
date=day..""..date
end
end
returndate
end
return""
end

--[[ ===============================================================================
Suppone che str sia una data ben formata (una delle varianti "gg mm aaaa",
"gg/mm/aaaa" o "gg-mm-aaaa" ) e restituisce l'articolo da anteporre per citarla
come data di accesso/archivio
===============================================================================]]
localfunctionarticle_date(str)
localstart=mw.ustring.sub(str,1,2)
ifin_array(start,{'08','8 ','8-','8/','11'})then
return"l'"
elseifmw.ustring.find(str,'^pre ')then-- per i valori "pre x/x/x" inseriti da ArchiveBot
return' in data '
end
returnstr~=''and"il"or''
end

--[[ ===============================================================================
Controlla che la stringa passata sia in un formato ammesso in caso contrario
ritorna il codice di errore
===============================================================================]]
localfunctioncheck_time(str)
localh,m,s=string.match(str,'^(%d+):(%d+):(%d+)$')
ifnot(h)thenh,m,s=string.match(str,'^(%d+) h (%d+) min (%d+) s$')end
ifnot(m)thenm,s=string.match(str,'^(%d+) min (%d+) s$')end
ifnot(m)thenm,s=string.match(str,'^(%d+):(%d+)$')end
ifnot(m)thenm=string.match(str,'^(%d+) min$')end
ifnot(m)thenreturn'time_not_valid'end
iftonumber(m)>=60thenreturn'minutes_wrong'end
ifsandtonumber(s)>=60thenreturn'seconds_wrong'end
ifhandnot(tonumber(s))thenreturn'hour_wrong'end
returnnil
end

--[[ ===============================================================================
Formatta una lista di persone (autori o editori)
===============================================================================]]
localfunctionlist_people(control,people)
localsep=control.sep;
locallastsep=control.lastsep
localtext={}
localetal=control.etal
localcoauthors=control.coauthors
localperson_list={}

fori,personinipairs(people)do
locallast=person.last
ifis_set(last)then
localfullname=""
localfirst=person.first
ifis_set(first)then
ifinvertorderthenfirst,last=last,firstend
fullname=table.concat({first,person.last},' ')
else
fullname=person.last
end
ifis_set(person.link)thenfullname=table.concat({"[[",person.link,"|",fullname,"]]"})end
table.insert(person_list,fullname)
end
ifetalthen
break
end
end
localcount=#person_list
localresult=""
ifcount>0then
ifcoauthorsthen
result=table.concat(person_list,sep)
elseifetalthen
result=person_list[1]..cfg.messages['et al']
else
result=mw.text.listToText(person_list,sep,lastsep)
end
end
returnresult,count
end

--[[ ===============================================================================
Genera un id per un ancora CITEREF
===============================================================================]]
localfunctionanchor_id(options)
return"CITEREF"..table.concat(options);
end

--[[ ===============================================================================
Estrae una lista di nomi (autori o editori) dalla lista argomenti
===============================================================================]]
localfunctionextract_names(args,list_name,parent_name)
localnames={};
locali=1;
locallast;
localparameters={
first=cfg.aliases[list_name..'-First'],
last=cfg.aliases[list_name..'-Last'],
link=cfg.aliases[list_name..'-Link'],
}

ifparent_namethen
fork,tinpairs(parameters)do
localnew_values={}
for_,vinipairs(t)do
table.insert(new_values,substitute(v,parent_name))
end
parameters[k]=new_values
end
end

whiletruedo
last=select_one(args,parameters.last,'redundant_parameters',i);
ifnotis_set(last)then
localfirst=select_one(args,parameters.first,'redundant_parameters',i)
ifnotis_set(first)then
break;
else-- nel caso sia definito "nome" ma non "cognome"
names[i]={
last=first,
first='',
link=select_one(args,parameters.link,'redundant_parameters',i),
}
end
else
names[i]={
last=last,
first=select_one(args,parameters.first,'redundant_parameters',i),
link=select_one(args,parameters.link,'redundant_parameters',i),
};
end
i=i+1;
end
returnnames;
end

--[[ ===============================================================================
Estrae dagli argomenti i codici bibliografici riconosciuti usando la
tabella cfg.id_handlers
===============================================================================]]
localfunctionextract_ids(args)
localid_list={};
fork,vinpairs(cfg.id_handlers)do
v=select_one(args,v.parameters,'redundant_parameters');
ifis_set(v)then
ifk=='ISBN'thenv=string.gsub(v,'^ISBN%s*','')end-- hack per eliminare l'ISBN ripetuto
id_list[k]=v;
end
end
returnid_list;
end

--[[ ===============================================================================
Formatta gli id bibliografici presenti nella tabella id_list
===============================================================================]]
localfunctionbuild_id_list(id_list,options)
localnew_list,handler={};

localfunctionfallback(k)
return{__index=function(t,i)returncfg.id_handlers[k][i]end}
end;

localfunctioncomp(a,b)
returna[1]<b[1];
end

fork,vinpairs(id_list)do
-- fallback to read-only cfg
localhandler=setmetatable({['id']=v},fallback(k));

ifk=='DOI'then
table.insert(new_list,{handler.label,doi(v,options.DoiBroken)});
elseifk=='OL'then
table.insert(new_list,{handler.label,open_library(v)});
elseifk=='SBN'then
table.insert(new_list,{handler.label,sbn(v)});
elseifk=='BNF'then
table.insert(new_list,{handler.label,bnf(v)});
elseifk=='ISBN'then
localISBN
ifv=='non esistente'orv=='no'then--la forma lunga per intercettare il valore ritornato dal template NoIsbn
ISBN='ISBN non esistente'
else
ISBN=link_id(handler);
ifnotcheck_isbn(v)andnotis_set(options.IgnoreISBN)then
ISBN=ISBN..set_error('bad_isbn',{},false,"<sup>","</sup>");
end
end
table.insert(new_list,{handler.label,ISBN});
else
table.insert(new_list,{handler.label,link_id(handler)});
end
end
table.sort(new_list,comp);
fork,vinipairs(new_list)do
new_list[k]=v[2];
end

returnnew_list;
end

--[[ ===============================================================================
Genera la stringa per il formato, se format non è definita tenta di ricavarlo dall'url
===============================================================================]]
localfunctionget_format(format,url)
ifformat:lower()=='html'then
return''
elseifnotis_set(format)then
format=mw.ustring.match(url,"^.*%.(.+)$")or''
ifnotcfg.external_link_type[format:lower()]then
format=mw.ustring.match(format,"^(.+)#.+$")or''
ifnotcfg.external_link_type[format:lower()]then
return''
end
end
end

-- Se il formato esterno è tra quelli previsti imita lo stile dei template {{PDF}} o {{doc}}
localf=cfg.external_link_type[format:lower()]
iffthen
returnmw.ustring.format(' (<span style= "font-weight: bolder; font-size:80%%" ><abbr title= "%s" >%s</abbr></span>)',f.text,f.label)
else
table.insert(z.message_tail,{set_error('unknown_format',format,true)});
returnmw.ustring.format(' (%s)',format)
end
end

--[[ ===============================================================================
Genera la citazione
===============================================================================]]
localfunctioncitation0(config,args)
localA=argument_wrapper(args);
locali

localStylename=A['Style']
localStyle=cfg.style
localPPPrefix=(is_set(A['NoPP'])and"")orStyle.ppprefix
localPPrefix=(is_set(A['NoPP'])and"")orStyle.pprefix
-- Pick out the relevant fields from the arguments. Different citation templates
-- define different field names for the same underlying things.
-- local Authors = A['Authors'];
locala=extract_names(args,'AuthorList');

localCoauthors=A['Coauthors'];
localOthers=A['Others'];
localEditors=A['Editors'];
locale=extract_names(args,'EditorList');

------------------------------------------------- Get date data
localPublicationDate=A['PublicationDate'];
localLayDate=A['LayDate'];
------------------------------------------------- Get title data
localTitle=A['Title'];
localConference=A['Conference'];
localOrganization=A['Organization']
localTransTitle=A['TransTitle'];
localOriginalTitle=A['OriginalTitle']
-- local TitleNote = A['TitleNote'];
localTitleLink=A['TitleLink'];
localChapter=A['Chapter'];
localChapterLink=A['ChapterLink'];
localTransChapter=A['TransChapter'];
localTitleType=A['TitleType'];
localArchiveURL=A['ArchiveURL'];
localURL=A['URL']
localURLorigin=A:ORIGIN('URL');
localChapterURL=A['ChapterURL'];
localChapterURLorigin=A:ORIGIN('ChapterURL');
localConferenceURL=A['ConferenceURL'];
localConferenceURLorigin=A:ORIGIN('ConferenceURL');
localAbstract=A['Abstract']
localPeriodical=A['Periodical'];
localIllustrator=A['Illustrator'];
localTranslator=A['Translator'];
localInstitution=A['Institution'];
localCollection=A['Collection'];
localSupplementOf=A['SupplementOf'];

ifis_set(OriginalTitle)andnotis_set(TransTitle)then
TransTitle=OriginalTitle
end

localisPubblicazione=(config.CitationClass=='pubblicazione')or
(config.CitationClass=='testo'andis_set(Periodical))

------------------------------------------------------------------------------
-- Formattazione di Position - contiene la pagina/posizione o punto del video
-- a cui fa riferimento la fonte
------------------------------------------------------------------------------
localPosition=A['Position'];
localPositionOrigin=A:ORIGIN('Position')
ifis_set(Position)then
ifPositionOrigin=="p"then
Position=PPrefix..Position
elseifPositionOrigin=="pp"then
Position=PPPrefix..Position
elseifPositionOrigin~="posizione"then
table.insert(z.error_categories,'Voci con modulo citazione e parametro '..PositionOrigin)
ifPositionOrigin=="pagine"then
ifconfig.CitationClass=="libro"then
iftonumber(Position)then
Position=PPrefix..Position
elseifstring.find(Position,'^%d')then
Position=PPPrefix..Position
end
elseifconfig.CitationClass=="conferenza"orconfig.CitationClass=="pubblicazione"then
Position=(tonumber(Position)andPPrefixorPPPrefix)..Position
end
elseifPositionOrigin=="pagina"then
Position=PPrefix..Position
else
Position=PPPrefix..Position
end
end
end
localHour=A['Hour']
localMinutes=A['Minutes']
localSeconds=A['Seconds']
localTime=A['Time']
ifin_array(config.CitationClass,{"video","tv","audio"})then
localComposeTime={}
localTimeError={}
ifis_set(Hour)then
ifnotis_set(Minutes)thenTimeError[#TimeError+1]=set_error('need_minutes',{'ora'})end
ifnottonumber(Hour)thenTimeError[#TimeError+1]=set_error('timepar_must_be_integer',{'ora'})end
ComposeTime[#ComposeTime+1]=Hour..' h'
end
ifis_set(Minutes)then
localcheck_error=tonumber(Minutes)
ifnotcheck_errorthen
TimeError[#TimeError+1]=set_error('timepar_must_be_integer',{'minuto'})
elseifcheck_error>60then
TimeError[#TimeError+1]=set_error('minutes_wrong')
end
ComposeTime[#ComposeTime+1]=Minutes..' min'
end
ifis_set(Seconds)then
ifnotis_set(Minutes)thenTimeError[#TimeError+1]=set_error('need_minutes',{'secondo'})end
localcheck_error=tonumber(Seconds)
ifnotcheck_errorthen
TimeError[#TimeError+1]=set_error('timepar_must_be_integer',{'ora'})
elseifcheck_error>60then
TimeError[#TimeError+1]=set_error('seconds_wrong')
end
ComposeTime[#ComposeTime+1]=Seconds..' s'
end
if#ComposeTime>1then
ifis_set(Position)thenTimeError[#TimeError+1]=set_error('time_parameter_conflict')end
Position='a '..table.concat(ComposeTime,' ')
end
ifis_set(Time)then
ifis_set(Position)thenTimeError[#TimeError+1]=set_error('time_parameter_conflict')end
localcheck_error=check_time(Time)
ifcheck_errorthenTimeError[#TimeError+1]=set_error(check_error)end
Position='a '..Time
end
if#TimeError>0thenPosition=Position..""..table.concat(TimeError,",")end
else
ifis_set(Hour)oris_set(Minutes)oris_set(Seconds)oris_set(Time)then
table.insert(z.message_tail,{set_error('not_video_citation',{},true)});
end
end
ifis_set(Position)thenPosition=' '..Positionend

------------------------------------------------------------------------------
-- Formattazione di volume/numero/serie/episodio
------------------------------------------------------------------------------
localSeries=A['Series'];
localVolume=A['Volume'];
localIssue=A['Issue'];
ifconfig.CitationClass=="tv"then
ifis_set(Issue)then
ifis_set(Volume)then
Issue=substitute(cfg.messages['season_episode'],{Volume,Issue})
Volume=''
else
Issue=substitute(cfg.messages['episode'],{Issue})
end
end
else
-- formatta Volume e Issue considerando numeri anche le stringhe del tipo n-n o n/n
ifis_set(Volume)then
iftonumber(Volume:gsub('[-/]',''),10)orA:ORIGIN('Volume')=="vol"then
Volume="vol."..Volume
end
end
ifis_set(Issue)then
iftonumber(Issue:gsub('[-/]',''),10)then
Issue="n."..Issue
end
end
end

localEdition=A['Edition'];
localPlace=A['Place']
localPublisherName=A['PublisherName'];
localSubscriptionRequired=A['SubscriptionRequired'];
localVia=A['Via'];
-- local Agency = A['Agency'];
localDeadURL=A['DeadURL'];
localLanguage=A['Language'];
localFormat=A['Format'];
localRef=A['Ref'];

localDoiBroken=A['DoiBroken'];
localID=A['ID'];
localIgnoreISBN=A['IgnoreISBN'];
localQuote=A['Quote'];
localsepc=Style.sep
localsepcspace=sepc..""
localPostScript=first_set(A['PostScript'],Style['postscript']);
localno_tracking_cats=A['NoTracking'];
localuse_lowercase=(sepc~='.');
localthis_page=mw.title.getCurrentTitle();--Also used for COinS

localID_list=extract_ids(args);
if(isPubblicazione)then
ifnotis_set(URL)andnotis_set(TitleLink)then
ifis_set(ID_list['PMC'])then
localEmbargo=A['Embargo'];
ifis_set(Embargo)then
locallang=mw.getContentLanguage();
localgood1,result1,good2,result2;
good1,result1=pcall(lang.formatDate,lang,'U',Embargo);
good2,result2=pcall(lang.formatDate,lang,'U');

ifgood1andgood2andtonumber(result1)<tonumber(result2)then
URL="https:// ncbi.nlm.nih.gov/pmc/articles/PMC"..ID_list['PMC'];
URLorigin=cfg.id_handlers['PMC'].parameters[1];
end
else
URL="https:// ncbi.nlm.nih.gov/pmc/articles/PMC"..ID_list['PMC'];
URLorigin=cfg.id_handlers['PMC'].parameters[1];
end
elseifis_set(ID_list['DOI'])then
URL="https://oadoi.org/"..ID_list['DOI'];
URLorigin=cfg.id_handlers['DOI'].parameters[1];
end
end
end
ID_list=build_id_list(ID_list,{DoiBroken=DoiBroken,IgnoreISBN=IgnoreISBN});

localStation=A['Station'];
ifis_set(Station)then
localwkStation=A['StationLink']
ifis_set(wkStation)then
Station='[['..wkStation..'|'..Station..']]'
end
end
ifconfig.CitationClass=="tv"then
Chapter=Title;
ChapterLink=TitleLink;
TransChapter=TransTitle;
Title=Series;
TitleLink=A['SeriesLink'];
TransTitle='';
Series='';
end

------------------------------------------------------------------------------
-- Se url è in realtà un url archiviato, lo tratta come tale
-- (per ora riconosce solo Internet Archive)
------------------------------------------------------------------------------
localformatoIA='^https?://web%.archive%.org/w?e?b?/?%d+/'
ifis_set(URL)andis_set(Title)andURL:match(formatoIA)andnotis_set(ArchiveURL)then
ArchiveURL=URL
URL=URL:gsub(formatoIA,'')
ifnotURL:match('://')then
URL='http://'..URL
end
end

------------------------------------------------------------------------------
-- Se opera/sito non è specificata, nel caso dei siti usa il dominio dell'URL
------------------------------------------------------------------------------
localauto_Periodical=false
ifin_array(config.CitationClass,{'web'})andnotis_set(Periodical)andis_set(URL)then
Periodical=mw.ustring.match(URL,"//([^/#%?]*)")or''
-- tolgo anche eventuale
ifstring.find(Periodical,"^[Ww][Ww][Ww]%.")then
Periodical=mw.ustring.sub(Periodical,5)
end
-- evito ripetizione se il dominio è stato usato come titolo o editore
ifis_set(Periodical)then
ifmw.ustring.lower(Title)==mw.ustring.lower(Periodical)then
Periodical=''
end
ifmw.ustring.lower(PublisherName)==mw.ustring.lower(Periodical)then
PublisherName=''
end
end
auto_Periodical=true
end

------------------------------------------------------------------------------
-- Se compare uno dei parametri legati a una pubblicazione periodica (opera, rivista, ec...)
-- e non è definito capitolo, ma solo titolo sposto titolo a capitolo
------------------------------------------------------------------------------
ifis_set(Periodical)andnotis_set(Chapter)andis_set(Title)then
Chapter=Title;
ChapterLink=TitleLink;
TransChapter=TransTitle;
Title='';
TitleLink='';
TransTitle='';
end

---------------------------------------------------------------
-- Compone la stringa della lingua
---------------------------------------------------------------
localLanguage_code=""
localfirst_language=""
ifis_set(Language)then
ifLanguage:sub(1,1)=="("then
Language_code=Language
else
localframe_lingue={return_error='true'}
forlinguainmw.text.gsplit(Language,',',true)do
lingua=mw.text.trim(lingua)
iflingua~=''then
frame_lingue[#frame_lingue+1]=lingua
end
end
if#frame_lingue>1or(#frame_lingue==1andframe_lingue[1]:lower()~="it"andframe_lingue[1]:lower()~="it-it")then
first_language=frame_lingue[1]:lower();
locallg_error;
Language_code,lg_error=require("Modulo:Lingue").lingue(frame_lingue)
iflg_errorand#lg_error>0then
localerror_string=mw.text.listToText(lg_error,",","e")
table.insert(z.message_tail,{set_error('unknown_language',{error_string},true)});
end
end
end
end
ifis_set(Edition)then
ifA:ORIGIN('Edition')=="ed"ortonumber(Edition)then
Edition=Edition.."ª ed."
end
end

------------------------------------------------------------------------------
-- Aggiunge il wikilink a Wikisource
------------------------------------------------------------------------------
ifis_set(A['Source'])andnotin_array(config.CitationClass,{"web","video","tv","audio"})then
localsource=A['Source']
-- se s=1 usa lo stesso valore di titolo/capitolo
ifsource=="1"then
source=Title..(is_set(Chapter)and("/"..Chapter)or"")
end
source="s:"..(is_set(first_language)and(first_language..":")or"")..source
ifis_set(Chapter)thenChapterLink=source
elseTitleLink=sourceend
end

------------------------------------------------------------------------------
-- Recupero e formatto lista autori
------------------------------------------------------------------------------
localAuthorSeparator=Style.peoplesep
localcontrol={
sep=AuthorSeparator,
maximum=Style.maximum_authors,
lastsep=Style.lastsepauthor,
invertorder=Style.invertorder,
etal=false,
coauthors=false,
};
localEtal=A['Etal']
-- If the coauthor field is also used, prevent adding ''et al.''
ifis_set(Coauthors)then
table.insert(z.error_categories,'Voci con modulo citazione e parametro '..A:ORIGIN('Coauthors'))
control.coauthors=true
elseifis_set(Etal)then
control.etal=true
end
localAuthors=list_people(control,a)
ifnotis_set(Authors)andis_set(Coauthors)then-- se non sono stati compilati campi autore, ma solo coautori
Authors=Coauthors
Coauthors=""
elseifis_set(Coauthors)then
Authors=table.concat({Authors,AuthorSeparator,Coauthors})
end

------------------------------------------------------------------------------
-- Recupero e formatto lista curatori
------------------------------------------------------------------------------
localmsg_editors
localCuratoriEtal=A['Etalcuratori']
control.coauthors=false
control.etal=is_set(CuratoriEtal)
ifis_set(Editors)then
msg_editors='editors'
else
localEditorCount
Editors,EditorCount=list_people(control,e)
ifis_set(Editors)then
msg_editors=EditorCount<=1and'editor'or'editors'
end
end

------------------------------------------------------------------------------
-- Recupero e formatto lista autori e curatori di un singolo capitolo dell'opera citata
------------------------------------------------------------------------------
localmsg_chapter_editors
localContributors,ChapterEditors="",""
ifis_set(Chapter)then
localChapterEditorCount
control.etal=false
Contributors=list_people(control,
extract_names(args,'ContributorList',A:ORIGIN('Chapter')))
ChapterEditors,ChapterEditorCount=list_people(control,
extract_names(args,'ChapterEditorList',A:ORIGIN('Chapter')))
ifis_set(ChapterEditors)then
msg_chapter_editors=ChapterEditorCount<=1and'editor'or'editors'
end
end

------------------------------------------------------------------------------
-- Se conferenza aggiungo il campo Organizzazione
------------------------------------------------------------------------------
ifconfig.CitationClass=='conferenza'then
ifis_set(Authors)andis_set(Organization)then
Authors=table.concat({Authors,', ',Organization})
elseifis_set(Organization)then
Authors=Organization
end
Organization=""
end

------------------------------------------------------------------------------
-- Formatto la data
------------------------------------------------------------------------------
localDate=get_date(A['Date'])
localYear=A['Year']
ifnotis_set(Date)thenDate=get_date_yyyy_mm_dd(Year,A['Month'],A['Day'])end
localOrigDate=get_date(A['OrigDate'])
ifnotis_set(OrigDate)thenOrigDate=get_date_yyyy_mm_dd(A['OrigYear'],A['OrigMonth'],A['OrigDay'])end
localAccessDate=get_date(A['AccessDate'])
ifnotis_set(AccessDate)thenAccessDate=get_date_yyyy_mm_dd(A['AccessYear'],A['AccessMonth'],A['AccessDay'])end
localArchiveDate=get_date(A['ArchiveDate']);
ifis_set(OrigDate)andnotis_set(Date)then
Date=OrigDate
OrigDate=""
end
OrigDate=is_set(OrigDate)and(""..wrap('origdate',OrigDate))or"";

ifin_array(PublicationDate,{Date,Year})thenPublicationDate=''end
ifnotis_set(Date)andis_set(PublicationDate)then
Date=PublicationDate;
PublicationDate='';
end

-- Captures the value for Date prior to adding parens or other textual transformations
localDateIn=Date;
ifnotis_set(URL)and
notis_set(ChapterURL)and
notis_set(ArchiveURL)and
notis_set(ConferenceURL)then
-- Controlla se Cita web viene chiamato senza URL
ifin_array(config.CitationClass,{'web'})then
table.insert(z.message_tail,{set_error('cite_web_url',{},true)});
end
-- Test if accessdate is given without giving a URL
ifis_set(AccessDate)then
table.insert(z.message_tail,{set_error('accessdate_missing_url',{},true)});
AccessDate='';
end
-- Test if format is given without giving a URL
ifis_set(Format)then
Format=Format..set_error('format_missing_url');
end
end

-- Test if citation has no title
ifnotis_set(Chapter)and
notis_set(Title)and
notis_set(Periodical)and
notis_set(Conference)and
notis_set(TransTitle)and
notis_set(TransChapter)then
table.insert(z.message_tail,{set_error('citation_missing_title',{},true)});
end

-- genera la stringa per il formato
Format=get_format(Format,(is_set(URL)andURL)orChapterURL)

-- In maniera predefinita l'URL non è dichiarato morto
ifis_set(DeadURL)then
DeadURL=DeadURL:lower()~='no'
else
-- A meno che l'archivio non sia specificato
DeadURL=is_set(ArchiveURL)
end

localOriginalURL=URL
ifis_set(ArchiveURL)then
ifDeadURLthen
URL=ArchiveURL
URLorigin=A:ORIGIN('ArchiveURL')
end
end

---------------------------------------------------------------
-- se pubblicazione controlla per i parametro abstract
--------------------------------------------------------------
ifis_set(Abstract)then
ifisPubblicazionethen
ifis_set(ChapterURL)then
TitleType=external_link(ChapterURL,'abstract')
ChapterURL=""
ifnotis_set(URL)thenFormat=""end
elseifis_set(URL)then
TitleType=external_link(URL,'abstract')
URL=""
else
Abstract=''
end
else
Abstract=""
end
else
Abstract=""
end
TitleType=is_set(TitleType)and("("..TitleType..")")or"";

---------------------------------------------------------------
-- Format chapter / article title
---------------------------------------------------------------
localTransError=""
ifis_set(TransChapter)then
ifnotis_set(Chapter)then
TransError=""..set_error('trans_missing_chapter')
Chapter=TransChapter
TransChapter=""
else
TransChapter=wrap(is_italicizable(TransChapter)and'trans-italic-title'or'trans-quoted-title',TransChapter)
end
end
Chapter=is_italicizable(Chapter)andwrap('italic-title',Chapter)orChapter;
ifis_set(TransChapter)thenChapter=Chapter..""..TransChapterend
ifis_set(Chapter)then
ifis_set(ChapterLink)then
Chapter=table.concat({"[[",ChapterLink,"|",Chapter,"]]"})
elseifis_set(ChapterURL)then
Chapter=external_link(ChapterURL,Chapter)..TransError;
ifnotis_set(URL)then--se è settato URL conservo Format per inserirlo dopo questo
Chapter=Chapter..Format;
Format="";
end
elseifis_set(URL)then
Chapter=external_link(URL,Chapter)..TransError;
Chapter=append_links(Chapter,args.altrilink)
Chapter=Chapter..Format;
URL="";
Format="";
else
Chapter=Chapter..TransError;
end
elseifis_set(ChapterURL)then
Chapter=external_link(ChapterURL,nil,ChapterURLorigin)..TransError
end

---------------------------------------------------------------
-- Format main title
---------------------------------------------------------------
TransError="";
ifis_set(TransTitle)then
ifnotis_set(Title)then
TransError=""..set_error('trans_missing_title')
Title=TransTitle
TransTitle=""
else
TransTitle=wrap(is_italicizable(TransTitle)and'trans-italic-title'or'trans-quoted-title',TransTitle)
end
end
Title=is_italicizable(Title)andwrap('italic-title',Title)orTitle;
ifis_set(TransTitle)thenTitle=Title..""..TransTitleend
ifis_set(Title)then
ifis_set(TitleLink)then
Title="[["..TitleLink.."|"..Title.."]]"
elseifis_set(URL)then
Title=external_link(URL,Title)..TransError
Title=append_links(Title,args.altrilink)
Title=Title..Format
URL="";
Format="";
else
Title=Title..TransError;
end
end
---------------------------------------------------------------
-- Format Conference
---------------------------------------------------------------
ifis_set(Conference)then
Conference=wrap('italic-title',Conference)
ifis_set(ConferenceURL)then
Conference=external_link(ConferenceURL,Conference);
end
elseifis_set(ConferenceURL)then
Conference=external_link(ConferenceURL,nil,ConferenceURLorigin);
end

-- se URL non è stato consumato da un capitolo/titolo emette errore
ifis_set(URL)then
URL=""..external_link(URL,nil,URLorigin);
end

--Aggiungo le virgolette alla citazione-
ifis_set(Quote)then
Quote=wrap('quoted-text',Quote);
end
---------------------------------------------------------------
-- Parametro via e subscription
---------------------------------------------------------------
ifis_set(Via)then
ifis_set(SubscriptionRequired)then
Via=wrap('viasubscription',Via);
else
Via=wrap('via',Via);
end
elseifis_set(SubscriptionRequired)then
Via=wrap('subscription')
end

---------------------------------------------------------------
-- Formattazione dati di accesso/url di archivio
---------------------------------------------------------------
ifis_set(AccessDate)then
AccessDate=substitute(cfg.messages['retrieved'],{AccessDate,article_date(AccessDate)})
end
localArchived
ifis_set(ArchiveURL)then
localdecodeArchiveDate=require('Modulo:Webarchive').decodeArchiveDate
localArchiveURLDate=decodeArchiveDate(ArchiveURL)
localArchiveError,ArchiveOutput=''
ifnotis_set(ArchiveDate)then
ArchiveDate=ArchiveURLDateor''
ifnotArchiveURLDatethen
ArchiveError=set_error('archive_missing_date',{},false,' ')
end
elseifArchiveURLDateandArchiveURLDate~=ArchiveDatethen
ArchiveError=set_error('date_mismatch',{ArchiveURLDate},false,' ')
end
ArchiveOutput=ArchiveDate..ArchiveError
localArchiveURL2=A['ArchiveURL2']
localArchiveDate2=get_date(A['ArchiveDate2'])
ifis_set(ArchiveURL2)then
localArchiveURLDate2=decodeArchiveDate(ArchiveURL2)
localArchiveError2,ArchiveOutput2=''
ifnotis_set(ArchiveDate2)then
ArchiveDate2=ArchiveURLDate2or''
ifnotArchiveURLDate2then
ArchiveError2=set_error('archive_missing_date2',{},false,' ')
end
elseifArchiveURLDate2andArchiveURLDate2~=ArchiveDate2then
ArchiveError2=set_error('date2_mismatch',{ArchiveURLDate2},false,' ')
end
ArchiveOutput2=ArchiveDate2..ArchiveError2
ArchiveURL2=substitute(cfg.messages['archived-second-copy'],
{external_link(ArchiveURL2,cfg.messages['archived2']),ArchiveOutput2,article_date(ArchiveDate2)});
end
ifnotDeadURLthen
Archived=substitute(cfg.messages['archived-not-dead'],
{external_link(ArchiveURL,cfg.messages['archived']),ArchiveOutput,article_date(ArchiveDate),ArchiveURL2});
ifnotis_set(OriginalURL)then
Archived=Archived..set_error('archive_missing_url',{},false,' ');
end
elseifis_set(OriginalURL)then
Archived=substitute(cfg.messages['archived-dead'],
{OriginalURL,ArchiveOutput,article_date(ArchiveDate),ArchiveURL2});
else
Archived=substitute(cfg.messages['archived-missing'],
{set_error('archive_missing_url'),ArchiveOutput,article_date(ArchiveDate),ArchiveURL2});
end
else
Archived=""
end

---------------------------------------------------------------
-- Data originale se presente (in ordine di preferenza dopo
-- la data di pubblicazione, quindi l'editore, il luogo di pubblicazione, )
---------------------------------------------------------------
ifis_set(OrigDate)then
ifis_set(Date)then
Date=Date..""..OrigDate
elseifis_set(PublisherName)then
PublisherName=PublisherName..""..OrigDate
elseifis_set(Place)then
Place=Place..""..OrigDate
else
Date=OrigDate
end
end

-- sopra si controlla se è vuoto, perciò bisogna formattarlo alla fine.
ifis_set(Periodical)thenPeriodical=wrap('italic-title',Periodical)end

ifis_set(SupplementOf)then
ifnotmw.ustring.find(SupplementOf,"^.+''.+''")then
SupplementOf='supplemento di '..wrap('italic-title',SupplementOf)
end
end

ifis_set(Collection)thenCollection='collana '..wrap('italic-title',Collection)end

ifis_set(Translator)thenTranslator=wrap('translator',Translator)end
ifis_set(Illustrator)thenIllustrator=wrap('illustrator',Illustrator)end

---------------------------------------------------------------
-- Combino insieme i vari componenti della citazione
---------------------------------------------------------------

localfragment_Title
localPostTitle=A['PostTitle']
ifis_set(Title)then
ifDeadURLandnotis_set(ArchiveURL)then
-- Report a dead URL without an archived URL
Title=Title..interrupted_url()
end
fragment_Title=Fragment.new({Title,Format,TitleType,PostTitle},' '):last(",")
else
fragment_Title=Fragment.new({})
ifis_set(Chapter)then
Chapter=DeadURLandnotis_set(ArchiveURL)
andtostring(Fragment.new({Chapter,interrupted_url(),Format,TitleType,PostTitle},' '):last(""))
ortostring(Fragment.new({Chapter,Format,TitleType,PostTitle},' '):last(""))
end
end

localfragment_citation
ifconfig.CitationClass=="tv"then
ifis_set(Chapter)then
fragment_Title:last(":"):append(Fragment.new({Issue,Chapter},sepc))
Issue=""
end
fragment_citation=Fragment.new({Authors},sepc)
fragment_citation:append(fragment_Title)
else
ifis_set(ChapterEditors)and(is_set(Contributors)orargs["anteposizione-curatore"]=="no")then
ChapterEditors='a cura di '..ChapterEditors
fragment_citation=Fragment.new({Contributors,Chapter,ChapterEditors},sepc)
else
ifis_set(ChapterEditors)then
ChapterEditors=wrap(msg_chapter_editors,ChapterEditors)
end
ifis_set(Chapter)andnot(is_set(Contributors)oris_set(ChapterEditors))then
ifis_set(Authors)then
Contributors,Authors=Authors,""
elseifis_set(Editors)andargs["anteposizione-curatore"]~="no"then
ChapterEditors,Editors=wrap(msg_editors,Editors),""
end
end
fragment_citation=Fragment.new({is_set(Contributors)andContributorsorChapterEditors,Chapter},sepc)
end
ifis_set(Chapter)then
-- antepone "su" anzichè "in" per i siti web
ifA:ORIGIN('Periodical')=='sito'orauto_Periodicalthen
fragment_citation:last("su")
else
fragment_citation:last("in")
end
end
ifis_set(Editors)and(is_set(Authors)orargs["anteposizione-curatore"]=="no"andnotis_set(Chapter))then
Editors='a cura di '..Editors
fragment_citation:appends({Authors,fragment_Title,Editors})
else
ifis_set(Editors)then
Editors=wrap(msg_editors,Editors)
end
fragment_citation:appends({is_set(Authors)andAuthorsorEditors,fragment_Title})
end
end
fragment_citation:appends({Conference,Periodical,SupplementOf,Collection,Translator,Illustrator,Others,Series,
Volume,Issue,Edition,Institution,Place,PublisherName,Station,Date,Position})
localfragment_ID_list=Fragment.new(ID_list,sepc):append(ID):start(",")
localfragment_URL=Fragment.new(URL):start(",")
localfragment_AccessDate=Fragment.new(AccessDate):start('.')
localfragment_Archived=Fragment.new(Archived):start(' ')
localfragment_Via=Fragment.new(Via):start(".")
localfragment_Quote=Fragment.new({Quote}):start(".")
fragment_citation:appends({fragment_ID_list,fragment_URL,fragment_AccessDate,fragment_Archived,fragment_Via})
ifPostScript=='nessuno'then
fragment_citation:last("nothing")
else
fragment_citation:last("..")
end
fragment_citation:appends({fragment_Quote})
fragment_citation:start("")
localtext=Language_code..tostring(fragment_citation)
-- aggiungo l'icona per video/audio
ifconfig.CitationClass=="video"thentext=cfg.messages['icon_video']..' '..textend
ifconfig.CitationClass=="audio"thentext=cfg.messages['icon_audio']..' '..textend

-- Now enclose the whole thing in a <span/> element
localoptions={};

ifis_set(config.CitationClass)andconfig.CitationClass~="citation"then
options.class="citation"..config.CitationClass;
else
options.class="citation";
end

-- if string.len(text:gsub( "<span[^>/]*>.-</span>", "" ):gsub( "%b<>", "" )) <= 2 then
-- z.error_categories = {};
-- text = set_error('empty_citation');
-- z.message_tail = {};
-- end

ifis_set(Ref)then
text=table.concat({'<cite id= "CITEREF',Ref,--mw.uri.anchorEncode('CITEREF'.. Ref),
' "class=" ',mw.text.nowiki(options.class),' "style=" font-style:normal ">',text,"</cite>"})
else
text=table.concat({'<cite class= "',mw.text.nowiki(options.class),' "style=" font-style:normal ">',text,"</cite>"})
end

localempty_span='<span style= "display:none;" > </span>';

if#z.message_tail~=0then
text=text.."";
fori,vinipairs(z.message_tail)do
ifis_set(v[1])then
ifi==#z.message_tailthen
text=text..error_comment(v[1],v[2]);
else
text=text..error_comment(v[1]..";",v[2]);
end
end
end
end

-- Chek to insert category error
ifnotis_set(no_tracking_cats)then
fork,vinpairs(cfg.uncategorized_namespaces)do
ifthis_page.nsText==vthen
no_tracking_cats="true";
break;
end
end
end
no_tracking_cats=no_tracking_cats:lower();
ifin_array(no_tracking_cats,{"","no","false","n"})then
for_,vinipairs(z.error_categories)do
text=text..'[[Categoria:'..v..']]';
end
end

returntext
end

--[[ ===============================================================================
Funzione di interfaccia per la generazione della citazione, usata dai vari template
cita libro, cita news, ecc...
===============================================================================]]
functionz.citation(frame)
localpframe=frame:getParent()

localargs={};
localsuggestions={};
localerror_text,error_state;

localconfig={};
fork,vinpairs(frame.args)do
config[k]=v;
args[k]=v;
end
ifconfig['ignore_parent']=='s'then
pframe.args={}
end
localignore_unnamed=(config['ignore_unnamed']=='s')orfalse
-- copy unnamed parameter to named parameter
locallastunnamed=0
ifnot(ignore_unnamed)andcfg.unnamed_parameter[config.CitationClass]then
fori,vinipairs(cfg.unnamed_parameter[config.CitationClass])do
ifpframe.args[i]then
localargs_value=mw.text.trim(pframe.args[i])
ifargs_value~=""then
args[v]=args_value
end
lastunnamed=i
else
break
end
end
end
fork,vinpairs(pframe.args)do
ifv~=''then
ifnotvalidate(k)then
error_text="";
iftype(k)~='string'then
-- Exclude empty numbered parameters
ifv:match("%S+")~=nilandtonumber(k)>lastunnamedandlastunnamed>0then
error_text,error_state=set_error('text_ignored',{v},true);
end
elseifvalidate(k:lower())then
error_text,error_state=set_error('parameter_ignored_suggest',{k,k:lower()},true);
else
if#suggestions==0then
suggestions=mw.loadData('Modulo:Citazione/Suggerimenti');
--suggestions = load_configuration_table( 'Modulo:Citazione/Suggerimenti');
end
ifsuggestions[k:lower()]~=nilthen
error_text,error_state=set_error('parameter_ignored_suggest',{k,suggestions[k:lower()]},true);
else
error_text,error_state=set_error('parameter_ignored',{k},true);
end
end
iferror_text~=''then
table.insert(z.message_tail,{error_text,error_state});
end
end
args[k]=v;
elseifargs[k]~=nilthen
args[k]=v;
end
end

-- hack per l'uso che fanno cita google books e youtube del parametro id
ifargs.idandargs.id~=''then
ifin_array(config.CitationClass,{"googlebooks","video"})then
args.id=nil
end
end
returncitation0(config,args)
end

-- Funzione per generare direttamente una citazione da un altro modulo
functionz.cita_da_modulo(classe,args)
-- mi assicuro che le code messaggi di errore siano vuote per evitare problemi in caso
-- per citazioni multiple dall'interno dello stesso modulo
z.error_categories={};-- lista delle categorie di errore
z.error_ids={};-- lista dei codici di errore
z.message_tail={};-- messaggi di errore da visualizzare in coda alla citazione
returncitation0({CitationClass=classe},args)
end

-- Elenco i formati di documenti gestiti
functionz.list_external_links(frame)
localrows={'{| class = "wikitable sortable"\n!codice!!Testo popup'}
localkeys={}
forkey,_inpairs(cfg.external_link_type)do
keys[#keys+1]=key
end
table.sort(keys)
for_,keyinipairs(keys)do
rows[#rows+1]=mw.ustring.format('|-\n|%s||%s',key,cfg.external_link_type[key].text)
end
rows[#rows+1]="|}"
returntable.concat(rows,'\n')
end

-- per formati esterni da altri template
functionz.format(frame)
localgetArgs=require('Module:Arguments').getArgs
localargs=getArgs(frame,{frameOnly=true})
returnget_format(args[1])
end

returnz