In questo articolo presenteremo due soluzioni Javascript per evidenziare la sintassi di listati di codice incorporati in pagine web. Si tratta di SyntaxHighlighter e Highlight.js. Fanno esattamente la stessa cosa: identificano blocchi di codice, individuano il linguaggio ed evidenziano la sintassi nel modo opportuno. Le differenze sono per lo più a livello di opzioni disponibili e visualizzazione a schermo del codice. A voi la scelta.
SyntaxHighlighter
Il codice di SyntaxHighlighter può essere scaricato dalla pagina dedicata alla libreria su Google Code. È anche disponibile un wiki che contiene la documentazione ed espone le principali funzionalità. Nel pacchetto zip allegato a questo articolo trovate comunque tutti i file necessari.
Nella cartella 'Scripts' sono presenti (in versione compressa) il file principale (shCore.js), i file relativi ai singoli linguaggi per cui si vuole evidenziare e formattare la sintassi e un piccolo file .swf (clipboard.swf) con cui viene implementata la funzionalità che consente di copiare negli appunti il codice del listato.
Nella cartella 'Styles' troverete invece un CSS (SyntaxHighlighter.css) che contiene le regole di formattazione del codice.
Nella configurazione di base, per usare la libreria dovremo inserire nella pagina:
- il richiamo al foglio di stile SyntaxHighlighter.css;
- il richiamo al file shCore.js;
- il richiamo ad almeno uno dei file .js di linguaggio;
- il codice per attivare la funzione
HighlightAll
che provvede all'evidenziazione della sintassi e per attivare la funzioneClipboardSwf
(copia negli appunti).
Nel primo esempio che abbiamo preparato, tutto è stato inserito nella sezione head
della pagina, così (il codice usato nel listato è Javascript, per cui si è usato il file corrispondente, shBrushJScript.js):
<link type="text/css" rel="stylesheet" href="Styles/SyntaxHighlighter.css"></link>
<script type="text/javascript" src="Scripts/shCore.js"></script>
<script type="text/javascript" src="Scripts/shBrushJScript.js"></script>
<script>
window.onload = function () {
dp.SyntaxHighlighter.ClipboardSwf = 'Scripts/clipboard.swf';
dp.SyntaxHighlighter.HighlightAll('codice');
}
</script>
Nulla comunque impedisce di inserire l'intera parte relativa a Javascript, soprattutto il richiamo alle funzioni con l'evento window.onload
, in fondo alla pagina (l'autore della libreria, anzi, consiglia di seguire questa via).
Due piccole osservazioni. Attenzione, intanto, al percorso verso i file CSS, JS e .swf. Poi, è importante sapere qualcosa di più sulla funzione dp.SyntaxHighlighter.HighlightAll()
.
Nell'esempio abbiamo usato come argomento l'unico obbligatorio: il nome (non l'id, come vedremo) dell'elemento pre
o textarea
che contiene il codice da formattare.
Per poter operare correttamente la libreria ha bisogno di individuare i listati di codice presenti nella pagina. Nella parte HTML, quindi, sarà necessario racchiudere il codice all'interno di un elemento pre
a cui assegnare un nome attraverso l'attributo name
e una classe che corrisponda al linguaggio (su questa pagina del wiki trovate la lista dei valori che è possibile usare per ciascun linguaggio).
Ecco come si presenta il breve listato del nostro esempio:
<pre name="codice" class="javascript">
..............
</pre>
In alternativa all'elemento pre
si può usare una textarea (esempio 2). Ecco la parte HTML:
<textarea name="codice" class="javascript">
...............
</textarea>
Attraverso il meccanismo delle classi è possibile specificare ulteriori opzioni di visualizzazione. I valori possibili sono:
- nogutter: nasconde i numeri di riga;
- nocontrols: nasconde i controlli posti nella barra superiore (visualizzazione come testo, copia, stampa);
- collapse: mostra il listato in stato non espanso;
- firstline[value]: imposta la riga da cui iniziare la visualizzazione del codice (per listati molto lunghi);
- showcolumns: mostra le indicazioni delle colonne in cima al listato.
Tali valori vanno aggiunti al valore dedicato al linguaggio separati dai : (due punti). In questo esempio, derivato dal primo, abbiamo deciso di nascondere i numeri di riga e mostrare l'indicazione delle colonne:
<pre name="codice" class="javascript:nogutter:showcolumns">
..................
</pre>
E se volessimo visualizzare più listati con linguaggi diversi? Semplice. Per prima cosa va ricordato di richiamare il file .js di linguaggio che ci interessa. Poi creeremo il pre
con il codice nel modo già visto. Nell'esempio seguente al listato di Javascript ne abbiamo aggiunto uno in CSS. Ecco come si presenta la sezione head
:
<script type="text/javascript" src="Scripts/shCore.js"></script>
<script type="text/javascript" src="Scripts/shBrushJScript.js"></script>
<script type="text/javascript" src="Scripts/shBrushCss.js"></script>
<script>
window.onload = function () {
dp.SyntaxHighlighter.ClipboardSwf = 'Scripts/clipboard.swf';
dp.SyntaxHighlighter.HighlightAll('codice');
}
</script>
Nel codice HTML abbiamo:
<pre name="codice" class="javascript">
............
</pre>
<pre name="codice" class="css">
............
</pre>
Tutto facile? Tutto bene? A dire il vero un problema c'è. Come si è notato, la libreria usa l'attributo name
su elementi pre
o textarea
per individuare i blocchi di codice. Purtroppo questo attributo, nelle specifiche del W3C, non è previsto per pre
. Per cui la pagina non sarà validata.
Vi ricordo in conclusione che per la formattazione di codice HTML/XHTML il file di linguaggio da usare è shBrushXML.js.
Highlight.js
Highlight.js non offre la ricchezza opzioni di SyntaxHighlighter: in effetti funzionalità come la possibilità di stampare il listato o quella di copiare il contenuto negli appunti sono molto comode. Risulta però nel complesso più facile da configurare e supporta ugualmente un gran numero di linguaggi.
L'analisi del codice del primo esempio renderà evidente quanto appena detto. Ecco come si presenta la sezione head
:
<link type="text/css" rel="stylesheet" href="sample.css" />
<script type="text/javascript" src="highlight.js"></script>
<script type="text/javascript">
initHighlightingOnLoad();
</script>
Intanto, come per SyntaxHighlighter, andrà richiamato un file CSS (sample.css) che provvede a formattare opportunamente il codice.
Segue il richiamo al file principale: highlight.js.
Anche questa libreria, però, usa un approccio modulare, con file .js di linguaggio. Non c'è però bisogno di richiamarli direttamente. È tutto automatico.
Per finire l'inizializzazione della funzione initHighlightingOnLoad()
.
Nella parte HTML sarà sufficiente racchiudere il codice tra un elemento pre
e uno code
:
<pre>
<code>
// Copies the original source code in to the clipboard. Uses either IE only method or Flash object if ClipboardSwf is set
CopyToClipboard: {
label: 'copy to clipboard',
check: function() { return window.clipboardData != null || dp.sh.ClipboardSwf != null; },
func: function(sender, highlighter)
{
var code = dp.sh.Utils.FixForBlogger(highlighter.originalCode)
.replace(/</g,'<')
.replace(/>/g,'>')
.replace(/&/g,'&')
;
</code>
</pre>
Come si vede, non è necessario indirizzare la libreria verso il linguaggio giusto usando l'attributo
class
. Di fatto la libreria è in grado di capire quale specifica di formattazione usare analizzando il codice e le sue caratteristiche precipue.
Il risultato non è però sempre garantito, soprattutto per frammenti molto brevi. Ecco allora che il meccanismo della classe ritorna. Vogliamo far capire alla libreria che quel listato è Javascript? Semplice (secondo esempio):
<pre>
<code class="javascript">
.......
</code>
</pre>
Per velocizzare il riconoscimento, poi, è possibile indicare i linguaggi usati nella pagina direttamente nella funzione di inizializzazione:
<script type="text/javascript">
initHighlightingOnLoad('javascript', 'css');
</script>