Syntax Highlighting in Drupal

5 Juli, 2009 - 11:44

Dies ist eigentlich kein richtiges Tutorial, sondern eher ein Memo an die Mitautoren dieser Seite. Ich zeige, wie man Syntax Highlighting in Texten nutzen kann. Da es vielleicht aber auch den einen oder anderen interessiert, habe ich mir gedacht, den Text gleich online zu stellen. Die Beschreibungen beziehen sich dabei primär auf das Content Management System (CMS) Drupal.

In technischen Beschreibungen verwendet man gerne kleinere Code Beispiele, um z.B. ein Programmierkonstrukt besser verständlich zu machen. Der eingebettete Code soll dann natürlich möglichst farblich hervorgehoben werden, so wie das auch im Lieblingseditor oder der IDE der Fall ist. Zum Beispiel würde man sich wünschen, dass ein Java "Hello World" Programm folgendermaßen dargestellt wird:

/**                                                                             
 * Jedes Java Programm besteht aus mindestens einer Klasse.
 */
public class javatest {
   /**
    * die main Methode dient als Einstieg in das Programm
    */
   public static void main(String[] args) {
      System.out.println("Hello World");
   }
}

Dies ist natürlich wesentlich leichter zu verstehen, als wenn der Code lediglich ohne Syntax Formatierung angezeigt würde:

/**                                                                             
 * Jedes Java Programm besteht aus mindestens einer Klasse.
 */
public class javatest {
   /**
    * die main Methode dient als Einstieg in das Programm
    */
   public static void main(String[] args) {
      System.out.println("Hello World");
   }
}

Hinzu kommt, dass man im zweiten Fall keine Zeilennummern hat, auf die man sich im Text beziehen kann.

Basiert eine Homepage auf dem CMS Drupal, eben wie diese Seite hier, dann gibt es momentan 2 prinzipielle Möglichkeiten, wie man Syntax Hervorhebung in den Seiten einbauen kann:

  1. Mit dem GeSHi Filter Plugin bindet man eine PHP Bibliothek ein, die das Syntax Highlighting direkt auf dem Server durchführt. Die GeSHi PHP Bibliothek unterstützt eine Vielzahl von Sprachen. Momentan wird laut Nutzungsstatistiken von drupal.org diese Lösung von der Mehrzahl der Nutzer verwendet.
  2. Mit dem Syntax Highlighter Plugin wird eine JavaScript Bibliothek verwendet. Diese JavaScript Bibliothek existiert erst seit einem knappen Jahr und unterstützt deshalb noch nicht alle erdenklichen Sprachen. Da hier JavaScript verwendet wird, geschieht das Syntax Highlighting erst auf dem Client, also direkt im Browser.

Beide Möglichkeiten haben ihre Vor- und Nachteile. Das größte Problem beim Einsatz der GeSHi Bibliothek (übrigens: Generic Syntax Highlighter) ist, dass entweder der verwendete Server diese Bibliothek bereits anbieten muss oder man den Server mit dieser Bibliothek erweitern muss. Letzterer Punkt ist aber nur möglich, wenn man Administrationszugriff auf seinen Server hat, was bei typischen Shared Hosting Lösungen mit Sicherheit nicht der Fall ist. Mit folgendem PHP Skript kann man überprüfen, ob die GeSHi Bibliothek im eigenen Server geladen wurde:

<?php                                                                           
   phpinfo();
?>

Die durch das PHP Skript erstellte Seite listet neben vielen anderen Informationen auch die verfügbaren Bibliotheken auf. Durchsucht man diese Seite nach "geshi" und findet keinen Eintrag, dann steht die Bibliothek auch nicht zur Verfügung und man kann deshalb diese Möglichkeit schon einmal streichen.

Da es nur 2 Möglichkeiten gibt, verbleibt in diesem Fall nur die 2. Lösung: Einsatz des Syntax Highlighter Plugins. Der größte Nachteil bei dieser Lösung ist, dass der Nutzer kein Syntax Highlighting sieht, wenn er die JavaScript Unterstützung in seinem Browser deaktiviert hat. Aus meiner persönlichen Sicht ist dies aber eine Einschränkung, mit der man leben kann.

Die Installation des Plugins ist denkbar einfach:

  1. Zunächst entpackt und kopiert man das Drupal Plugin in den Modulordner auf seinem Server.
  2. Anschließend entpackt und kopiert man die zugehörige JavaScript Bibliothek in den entsprechenden Unterordner des Plugins auf dem Server. Wo genau die Bibliothek hingehört, steht in der Beschreibung des Plugins.
  3. Hat man alle Dateien entsprechend auf dem Server vorbereitet, aktiviert man das Plugin auf der Modulseite im Administrationsbereich von Drupal.
  4. Abschließend passt man die Einstellungen des neuen Moduls an. Dort kann man zum Beispiel auswählen, für welche Sprachen Syntax Highlighting angeboten werden soll.

Hat man diese Punkte abgeschlossen, kann man das Syntax Highlighting direkt ausprobieren. Dazu erstellt man eine neue Seite (in Drupal Speak eine "Node"). Welchen Inhaltstyp ("Content Type") man verwendet, spielt dabei keine Rolle. Als Eingabeformat muss man "Full HTML" wählen. Der einzubindende Quellcode muss mit <pre>...</pre> Tags umgeben werden:

<pre class="brush:XYZ">
...Code in Sprache XYZ...
</pre>

Das XYZ in der 1. Zeile ist natürlich durch das entsprechende Kürzel der verwendeten Sprache zu ersetzen. Dabei können nur die Sprachen verwendet werden, die zuvor im Administrationsbereich auch aktiviert wurden. Laut Dokumentation des Syntax Highlighter Plugins soll man lediglich die Sprachen aktivieren, die auch wirklich verwendet werden, damit es nicht zu Performance Problemen kommt. Die folgende Tabelle gibt Aufschluss über die zu verwendenden Kürzel wichtiger Sprachen.

Sprache Kürzel
HTML Dateien html
JavaScript Quelltext js
PHP Quelltext php
Java Quelltext java
XML Dateien xml
SQL Anweisungen sql
Bash Skripte bzw. Shell Anweisungen bash

Tatsächlich ist die ganze Sache wirklich so einfach. Es gibt auch keine Komplikationen, wenn man einen WYSIWYG Editor in Drupal eingebunden hat. Bevor man den Quelltext samt den <pre> Tags eingibt, muss man natürlich in die Quelltextansicht ("Source") des Editors umschalten.

Hat man den gewünschten Quelltext noch separat als normale Dateien zum Download auf seinem Server liegen, kann man den Inhalt dieser Dateien natürlich auch direkt per PHP einbinden. Dies hat den Vorteil, dass man lediglich die Datei pflegen muss und die zugehörige Seite zeigt immer den aktuellen Code. Damit dies aber funktioniert, muss man für die Node ein Eingabeformat verwendet, das PHP Ausdrücke zulässt. Dürfen unbekannte Nutzer Seiten erstellen, ist diese Variante natürlich zu gefährlich, da sonst jeder beliebigen PHP Code ausführen könnte. Das Einbinden einer Datei in die eigene Seite geschieht mit folgender Anweisung:

<pre class="brush:XYZ">
<?php
	include('pfad/zur/datei/datei.XYZ');
?>
</pre>

Was macht man aber, wenn die gewünschte Sprache nicht von der JavaScript Bibliothek unterstützt wird? Auf einer anderen Seite benötigte ich zum Beispiel Syntax Highlighting von LaTeX Beispielen, aber momentan wird LaTeX Unterstützung nicht mit ausgeliefert. Mein erster Ansatz, wie meist in solchen Fällen, war die Suche danach im Netz. Und tatsächlich, die Suche nach "syntax highlighter brush latex" lieferte auch gleich ein brauchbares Ergebnis unter den ersten Treffern. Dieses Skript habe ich dann noch etwas erweitert, um noch zusätzliche Konstrukte farblich hervorzuheben. Hier mal das Skript, um den prinzipiellen Aufbau solch einer "Brush" zu zeigen:

SyntaxHighlighter.brushes.Latex = function()                                    
{      
   var keywords = 'if fi then elif else for do done until while break continue case function return in eq ne gt lt ge le';
       
   this.regexList = [
      { regex: new RegExp('%.*','gm'), css: 'comments' },
      { regex: SyntaxHighlighter.regexLib.doubleQuotedString, css: 'string' },
      { regex: new RegExp('\\\\\\w*','gm'), css: 'keyword' },
      { regex: new RegExp(this.getKeywords(keywords), 'gm'), css: 'function' },
      { regex: new RegExp('\\\[.*\\\]', 'gm'), css: 'variable' },
      { regex: new RegExp('{.*}', 'gm'), css: 'variable' },
   ];
}      
       
SyntaxHighlighter.brushes.Latex.prototype = new SyntaxHighlighter.Highlighter();
SyntaxHighlighter.brushes.Latex.aliases = ['latex', 'tex'];

Prinzipiell nutzt solch eine "Brush" also reguläre Ausdrücke, um Quelltext hervorzuheben. Ein echtes Parsing des Quelltexts findet nicht statt. Der Aufbau einer Brush ist immer identisch. Will man selbst eine Brush erstellen, kopiert man zunächst eine existierende Brush. Im oben gezeigten Beispiel müsste man dann alle Stellen, an denen "Latex" auftaucht, durch das gewünschte Sprachkürzel ersetzen. Die verwendbaren CSS Klassen der unterschiedlichen Farben findet man in der CSS Datei des verwendeten Themes. In der Datei shCore.js findet man auch ein paar vorgefertigte reguläre Ausdrücke, z.B. um mehrzeilige Kommentare oder eine URL zu matchen. Um diese Ausdrücke zu finden, muss man nach "regexLib" in der shCore.js Datei suchen.

Für jedes Sprachkonstrukt, das man farblich hervorheben möchte, erstellt man einen regulären Ausdruck und gibt die CSS Klasse an, mit der das Konstrukt hervorgehoben werden soll. Für die regulären Ausdrücke muss die Perl Syntax verwendet werden. Anstatt alle regulären Ausdrücke neu auszuknobeln, sollte man in den anderen Brush Dateien schauen, ob es nicht vielleicht schon einen vergleichbaren Ausdruck gibt. Es empfiehlt sich auch nicht komplett neu anzufangen, sondern eine verwandte Sprache zu nutzen.

Die neu erstellte Brush Datei kopiert man zu den anderen Brush Dateien ins "scripts/" Verzeichnis. Nachdem man die neue Datei auf den Server kopiert hat, kann man im Administrationsbereich von Drupal die neue Sprache aktivieren und direkt in eigenen Seiten verwenden.

Das LaTeX Beispiel zeigt, dass man relativ einfach eigene Syntaxhervorhebungen erzeugen kann. Deshalb gehe ich auch davon aus, dass relativ schnell weitere Sprachen von der Syntax Highlighter Bibliothek unterstützt werden. Hat man das Plugin erst einmal in seine Seite eingebunden, ist die farbliche Hervorhebung von Quelltextbeispielen ein Kinderspiel.


Kommentare

Geshi kann eigentlich jeder benutzen. Einfach die Lib hier http://qbnz.com/highlighter/ runterladen und ins Geshifilter Modul packen. Das wäre mir neu das die Lib ein PHP-Modul/Erweiterung ist, wie zb GD2 :D.

Mmmh, das wäre mir neu, aber wenn es so einfach geht, dann ist das natürlich auch gut.