Modulo:Font to span

La funzione principale di questo modulo è la conversione dei tag font, deprecati in HTML 5, in tag span con opportuno stile. Per utilizzarlo (sempre e comunque in subst) è necessario rintracciare un tag font di apertura e il corrispettivo tag di chiusura con un'espressione regolare e inserire tutto il testo trovato come primo parametro. Ad esempio, è possibile procedere così:

  • Utilizzare l'espressione regolare <font[^>]+>[^<]+<\/font> per trovare il testo da sostituire.
  • Sostituirlo con {{subst:#invoke:Font to span|main|1=$&}}, dove $& è l'intero testo trovato; occorre ricordarsi di inserire 1= altrimenti i simboli di uguale contenuti nel tag generano errore.

Il modulo provvede da solo alle operazioni necessarie, convertendo i parametri di dimensione, colore e face del testo. Inoltre, se all'interno dei tag si trova solo un wikilink o un link esterno con titolo, il tag viene spostato dentro al link per mantenere il colore voluto. L'unico caso non supportato è quello in cui i tag contengano soltano un link esterno senza titolo, per i quali sembra non esserci una soluzione semplice. Occorre inoltre fare particolare attenzione al subst, evitando di effettuare la sostituzione all'interno di tag <ref>...</ref> o <includeonly>...</includeonly>.

È inoltre possibile utilizzare il modulo per incorporare due tag, siano essi font o span (anche misti), situati uno dentro l'altro con lo stesso testo in mezzo. In questo caso, il modulo provvede ad estrarre dai due tag lo stile effettivo da utilizzare, cercandolo rispettivamente in:

Style del tag internoParametri sparsi nel tag internoStyle del tag esternoParametri sparsi nel tag esterno

Trovati i parametri finali li converte e semplifica come nella modalità principale e restituisce un unico tag con i parametri corretti. Per utilizzare questa funzionalità, è necessaria un'espressione regolare che trovi tutto il testo dall'apertura del tag esterno alla sua chiusura.

Ad esempio, sul testo <span style="color:green;font-family:Verdana"><font face=Monospace size=2>Testo di prova senza alcun significato messo qui come esempio</font></span> è necessaria una regex come (<(font|span)[^>]+>)(<(font|span)[^>]+>)[^<]+<\/\4><\/\2>, con un gruppo catturante sul tag esterno e uno sul tag interno. Come replace occorre chiamare il modulo nel seguente modo: {{subst:#invoke:Font to span|sempl|1=$1|2=$3|3=$&}}. Il risultato sarà <span style="color:green;font-family:Monospace;font-size:small">Testo di prova senza alcun significato messo qui come esempio</span>

Nota
Le dimensioni troppo grandi (+4, 7 e maggiori) vengono convertite in un formato fisso espresso in pixel, anziché variabile come per le altre.

--ToDo: Aggiungere riconoscimento degli apici oltre alle virgolette in tutte le stringhe
local p={};

--funzione di estrazione per utilizzo multiplo
local function extract(x)
	face=string.match(x, "face%s*=%s*([%d%aæ,]+)") or string.match(x, 'face%s*=%s*"%s*([^"]+)"')
	size=string.match(x, 'size%s*=%s*"?%s*([-+]?%d+[pxtem%%]*)"?') or string.match(x, 'size%s*=%s*"?%s*([%a-]+)"?')
	color=string.match(x, 'color%s*=%s*"?%s*(rgb%([^)]+%))"?') or string.match(x, 'color%s*=%s*"?%s*(#?%w+)"?')
	style=string.match(x, 'style%s*=%s*"([^"]+)"')
	return {face, size, color, style}
end

--funzione per ricostruire lo style
local function build(a,b,c,d)
	--Mette insieme lo style
	if d==nil then d="" end
	if string.match(d, "[^;]$") then d = d .. ";" end

	if a~=nil then d=d .. "color:" .. a .. ";" end
	if b~=nil then d=d .. "font-size:" .. b .. ";" end
	if c~=nil then d=d .. "font-family:" .. c .. ";" end

	--Via le virgolette conclusive e restituisce style impacchettato
	return string.gsub(d, ";+$", "")
end

local function convert(a,type)

if type=="size" then
	--riporto valori fantasiosi di size a quelli reali
	z=tonumber(string.match(a, "(%d+) *pt")) or tonumber(a)
	if z~=nil then
		if z>7 then a="7"
		elseif z<-2 then a="-2"
		elseif z>4 and string.match(a, "^%+%d$") then a="+4" end
	end
	--tabella conversione size
	stab = {
		['1'] = 'x-small',
		['2'] = 'small',
		['3'] = 'medium',
		['4'] = 'large',
		['5'] = 'x-large',
		['6'] = 'xx-large',
		['7'] = '48px',
		['-2'] = 'x-small',
		['-1'] = 'small',
		['+1'] = 'large',
		['+2'] = 'x-large',
		['+3'] = 'xx-large',
		['+4'] = '48px'
	}
	a = stab[a] or a
end

if type=="color" then
	--via gli spazi messi fantasiosamente e l'ancor più fantasioso "solid"
	a = string.gsub(a, " ", "");
	a = string.gsub(a, "solid", "");
	--aggiunge cancelletto a colore se in formato hex e sottinteso. Il pattern è molto brutale ma funziona perché non esistono nomi di colore che lo rispettano
	if string.match(a, "^[a-f0-9]+$") then a = "#" .. a end
	--toglie il cancelletto dai colori non hex (sì, a giro c'è anche questo)
	if string.match(a, "^%#[a-f0-9]*[g-z]") then a = string.gsub(a, "%#", "") end

	--tabella semplificazione colore per i casi più semplici
	ctab = {
		['#ff0000'] = 'red',
		['#ffc0cb'] = 'pink',
		['#ffa500'] = 'orange',
		['#ffff00'] = 'yellow',
		['#800080'] = 'purple',
		['#008000'] = 'green',
		['#0000ff'] = 'blue',
		['#a52a2a'] = 'brown',
		['#ffffff'] = 'white',
		['#808080'] = 'gray',
		['#000000'] = 'black'
	}
	a = ctab[a] or a
end
return a
end

function p.main(frame)
	str=frame.args[1]
	local substype
--substype per eventuale spostamento testo
	if string.match(str, "<font[^>]+>%[%[[^%]]+]]<%/font>") then
		substype=1;  --solo wikilink
	elseif string.match(str, "<font[^>]+>%[http[^%]]+ [^%]]+]<%/font>") or string.match(str, "<font[^>]+>%[\{\{fullurl[^%]]+ [^%]]+]<%/font>") then
		substype=2; --solo link esterno CON TITOLO
	elseif string.match(str, "<font[^>]+>%[http[^%] ]+]<%/font>") or string.match(str, "<font[^>]+>%[\{\{fullurl[^%] ]+]<%/font>") then
		return str; --solo link esterno SENZA TITOLO: il font colora il numero progressivo dall'esterno, lo span no; non ho trovato un modo per colorarlo con span interno.
	end --negli altri casi i risultati sono equivalenti
	
--riduzione stringa al solo font di apertura e minuscolizza il tutto
s=mw.ustring.lower(string.sub(str,1,string.find(str, ">")));

--estrazione attributi
attr=extract(s)

--torno ad attributi con nome per semplicità
face=attr[1]
size=attr[2]
color=attr[3]
style=attr[4]

--conversione size e aggiustamento numeri
if size~=nil then size=convert(size, "size") end
--uscita di sicurezza
if size == "+4" or size =="7" then return str end --font troppo grande, non sono riuscito a convertirlo

--conversione color ed eventuale aggiustamento cancelletto
if color~=nil then color = convert(color, "color") end

-- elimina parametri duplicati, lascia quello in style
if style~=nil then
	style=string.gsub(style, "background%-color", "background%-clor") --workaround per evitare match sul bgcol
	if color~=nil and string.match(style, "color:") then color=nil end
	if size~=nil and string.match(style, "font%-size:") then size=nil end
	if face~=nil and string.match(style, "font%-family:") then face=nil end
	style=string.gsub(style, "background%-clor", "background%-color") --annullo il workaround
end

--Costruisce lo style
style=build(color, size, face, style)

--Controllo "di sicurezza": se lo style è (quasi) vuoto restituisce il testo di partenza e buonanotte
if string.match(style, "^%s*$") then return str end

--Costruisce lo span e ci inserisce il testo (substype 0)
span='<span style="' .. style .. '">'
text=string.gsub(str, "<%/?[Ff][Oo][Nn][Tt][^>]*>", "")
result= span .. text .. "</span>"

--Spostamento per substype = 1
if substype==1 then
	wl=string.sub(str,string.find(str, "%[%["),string.find(str, "]]"))
	if string.match(wl, "|") then
		--Wikilink con pipe
		wl1=string.sub(wl,1,string.find(wl, "|"))
		wl2=string.gsub(string.sub(wl,string.find(wl, "|"),string.find(wl, "]")), "[|%]]", "")
		result=wl1 .. span .. wl2 .. "</span>]]"
	else
		--Wikilink senza pipe, lo aggiunge
		wl1=string.gsub(wl, "[%]%[]", "")
		result="[[" .. wl1 .. "|" .. span .. wl1 .. "</span>]]"
	end

elseif substype==2 then
	l=string.sub(str,string.find(str, "%["),string.find(str, "]"))
	l1=string.sub(l, 1, string.find(l, " "));
	l2=string.sub(string.gsub(string.sub(l,string.find(l, " "),string.find(l, "]")), "%]", ""), 2)
	result=l1 .. span ..l2 .. "</span>]"
end

return result

end

--funzione per accorpare due font/span con lo stesso testo in mezzo
function p.sempl(frame)
	str=frame.args[3]
	--estrazione parametri sparsi
	x=extract(mw.ustring.lower(frame.args[1]))
	y=extract(mw.ustring.lower(frame.args[2]))

	--estrazione parametri dal primo style
	if x[4]~=nil then
		x[4]=string.gsub(x[4], "background%-color", "background%-clor") --workaround per evitare match sul bgcol
		c1=string.match(x[4], 'color:([^;"]+)')
		s1=string.match(x[4], 'font%-size:([^;"]+)')
		f1=string.match(x[4], 'font%-family:([^;"]+)')
		x[4]=string.gsub(string.gsub(string.gsub(x[4], 'font%-family:([^;"]+)', ""), 'font%-size:([^;"]+)', ""), 'color:([^;"]+)', "")
		x[4]=string.gsub(x[4], "background%-clor", "background%-color") --annullo il workaround
	end
	--estrazione parametri dal secondo style
	if y[4]~=nil then
		y[4]=string.gsub(y[4], "background%-color", "background%-clor") --workaround per evitare match sul bgcol
		c2=string.match(y[4], 'color:([^;"]+)')
		s2=string.match(y[4], 'font%-size:([^;"]+)')
		f2=string.match(y[4], 'font%-family:([^;"]+)')
		y[4]=string.gsub(string.gsub(string.gsub(y[4], 'font%-family:([^;"]+)', ""), 'font%-size:([^;"]+)', ""), 'color:([^;"]+)', "")
		y[4]=string.gsub(y[4], "background%-clor", "background%-color") --annullo il workaround
	end
	--Parametro univoco, ordine di priorità: style dentro, tag dentro, style fuori, tag fuori
	f=f2 or y[1] or f1 or x[1]
	s=s2 or y[2] or s1 or x[2]
	c=c2 or y[3] or c1 or x[3]
	
	--conversione size e aggiustamento numeri
    if s~=nil then s=convert(s, "size") end
	--uscita di sicurezza
	if s == "+4" or s =="7" then return str end --font troppo grande, non sono riuscito a convertirlo

	--conversione color ed eventuale aggiustamento cancelletto
	if c~=nil then c = convert(c, "color") end
	
	--Scorre i due style per trovare parametri uguali
	if x[4]~=nil and y[4]~=nil then
		--liste di attributi
		it1= string.gmatch(x[4], "([%a-]+:)")
		it2= string.gmatch(y[4], "([%a-]+:)")
		corr={}; --table vuota di corrispondenze
		for i in it1 do 
			for j in it2 do
    			if i==j then table.insert(corr, i) end --aggiunge il match alle corrispondenze
			end
			it2= string.gmatch(y[4], "([%a-]+:)") --ripristina iteratore per altri giri
		end
		--elimina le corrispondenze e relativo valore dal tag esterno
		for i,v in ipairs(corr) do 
			x[4]=string.gsub(x[4], v.."[^;]+;*", "");
		end
		--formatta i due style eliminando spazi e punti e virgola superflui
		x[4]=string.gsub(string.gsub(x[4], ";[ ;]+", ";"), "^[ ;]+", "")
		y[4]=string.gsub(string.gsub(y[4], ";[ ;]+", ";"), "^[ ;]+", "")
		--unisce ciò che rimane dei due style
		if string.match(x[4], "[^;]$") then x[4] = x[4] .. ";" end
		stile=x[4]..y[4]
	elseif x[4]~=nil then
		stile=string.gsub(string.gsub(x[4], ";[ ;]+", ";"), "^[ ;]+", "")
	elseif y[4]~=nil then
		stile=string.gsub(string.gsub(y[4], ";[ ;]+", ";"), "^[ ;]+", "")
	end
	
	--Ottiene uno style singolo con tutti e soli i parametri da mantenere
	sty=build(c,s,f,stile)
	
	--Seconda uscita di sicurezza
	if string.match(sty, "^%s*$") then return str end
	
	--Costruisce lo span unico, ci rimette dentro il testo e lo restituisce
	text=string.gsub(string.gsub(str, "<%/?[Ff][Oo][Nn][Tt][^>]*>", ""), "<%/?[Ss][Pp][Aa][Nn][^>]*>", "")
	return '<span style="' .. sty .. '">' .. text .. "</span>"
end



return p