Licht in Sicht

Die Strukturierung und Vereinfachung der Entwicklung von Webanwendungen voranzutreiben, war schon Ziel von Ruby on Rails. In Ruby implementiert – und außerdem für sich nutzbar – setzt HAML diesen Weg fort.

vorlesen Druckansicht 5 Kommentare lesen
Lesezeit: 7 Min.
Von
  • Jan Krutisch
Inhaltsverzeichnis

Welche Template Engine zu verwenden ist, führt unter Webentwicklern immer wieder zu heißen Diskussionen. Designer möchten viel HTML und wenig Code in den Templates haben. WYSIWYG-Editoren scheitern an (exotischen) Konstrukten. Vielen Template-Sprachen ist allerdings eins gemein: Code und Content sind miteinander vermischt. Man denke nur an PHP oder die PHP-Template-Sprache Smarty, Embedded Ruby (ERB), JSP-Seiten inklusive Taglibs et cetera. Das HAML-Projekt von Hampton Caitlin geht einen anderen, geraden Weg ohne Mix und schafft dadurch erstaunliche Freiräume.

HAML, derzeit bei Version 2.0.6 angekommen, steht für (X)HTML Abstraction Markup Language, ist in Ruby implementiert und findet daher vor allem in Frameworks wie Rails, Merb oder Sinatra Anwendung. Primäres Ziel von HAML ist die effiziente und übersichtliche Abbildung der Dokumentstruktur unter Minimierung der Tipparbeit für den Entwickler. In Anlehnung an das japanische Kurzgedicht lautet der Slogan von HAML deswegen „markup haiku“.

Mehr Infos

Ein weiteres Ziel ist eine Annäherung der Markup-Sprache an CSS. So werden CSS-Selektor-ähnliche Konstrukte zur Auszeichnung von Tags mit id- und class-Attributen verwendet. Zusätzlich zur Template-Sprache HAML enthält das Softwarepaket die CSS-Abstraktion SASS (Syntactically Awesome Stylesheets) – eine eigene Sprache, die ansatzweise CSS ähnelt, aber durch Ergänzen der Syntax echte Kaskadierung, Konstanten und Makros ermöglicht. In den oben genannten Frameworks generiert SASS auf Anfrage automatisch CSS-Dateien (siehe die „Onlinequellen“).

Eine stabile Version von HAML lässt sich über den Rubygems-Paketmanager per gem install haml installieren – oder übers Web für die Stand-alone-Anwendung herunterladen. Die Verwendung von HAML erfolgt entweder als Plug-in (in Rails) oder über das Kommandozeilen-Tool haml, mit denen sich .haml- und .sass-Dateien in HTML und CSS wandeln lassen, indem man diese mit Quell- und Zieldatei aufruft (beispielsweise haml simple.haml simple.html).

Um HAML/SASS in ein Rails-Projekt einzubinden, kann das haml-Kommando das nötige Rails-Plug-in erzeugen, indem man es in RAILS_ROOT mit haml –rails . aufruft. Damit HAML als Template Engine zum Einsatz kommt, müssen die View-Dateien auf .haml enden, daher muss man beispielsweise über Generatoren erzeugte Dateien von .erb in .haml umbenennen.

Die grundlegende Syntax ist in Listing 1 dargestellt, in der der HAML- und der daraus generierte HTML-Code zu sehen sind.

Mehr Infos

Listing 1: HAML-Code

%html
%head
%title Dies ist ein Titel
%body
#header
%h1 Ăśberschrift
.content
%p
Absatz


<html>
<head>
<title>Dies ist ein Titel</title>
</head>
<body>
<div id='header'>
<h1>Ăśberschrift</h1>
</div>
<div class='content'>
<p>
Absatz
</p>
</div>
</body>

Wie das Listing zeigt, drückt HAML die Struktur des Dokuments allein durch Einrückungen aus (es besteht sogar strikt auf der Ruby-typischen Einrückung mit zwei Leerzeichen), und es fehlen die schließenden Elemente. Dies mutet zunächst befremdlich an, und man wähnt sich kurz in einem Traum von Python-Erfinder Guido Rossum. Allerdings hat dieses Vorgehen ein paar massive Vorteile: Zum einen ist es kaum möglich, mit HAML invalides Markup zu erzeugen, da es schließende Elemente automatisch hinzufügt und die logische Struktur des Dokuments strikt prüft. Zum anderen enthalten HAML-Templates deutlich weniger „Rauschen“ in Form der HTML/XML-Tag-Suppe.

Außer den Grundelementen gibt es in HAML diverse Konstrukte, um beispielsweise Ruby-Code einzubinden, komplexere Attribute zu setzen und Ähnliches. Ruby-Code lässt sich über mehrere Varianten einbinden. Zunächst gibt es eine Variante, um Ausgaben über Ruby-Code zu generieren, etwa um Daten in das Template zu setzen. Hierzu dient das Gleichheitszeichen. Es kann entweder auf derselben Zeile wie der Tag oder eigenständig in einer neuen stehen. Aus dem HAML-Code

%h1= "Headline".downcase
%p= "Absatz".upcase

ergibt sich als HTML

<h1>headline</h1>
<p>
ABSATZ
</p>

Je nach Konfiguration kann HAML diese Ausgaben schon automatisch „escapen“ (Sonderzeichen entfernen), um die üblichen Cross-Site-Scripting-Attacken zu vermeiden. Mit &= und != gibt es darüber hinaus zwei explizite Varianten für Escaped- und Unescaped-Ausgaben. Wer Schleifen und Bedingungen über Ruby-Code ausdrücken will, kann dies durch ein Minus-Zeichen erreichen, das keinen Output erzeugt. So mutieren die Zeilen

%ul
- %w{eins zwei drei}.each do
|word|
%li= word</pre>

zu folgendem HTML:

<ul>
<li>eins</li>
<li>zwei</li>
<li>drei</li>
<li>vier</li>
</ul>

HAML schließt Ruby-Blöcke genau wie HTML-Tags automatisch nach Berücksichtigung der Einrückung.

Ein weiteres HAML-Konstrukt sind die sogenannten Filter, mit denen man größere Textblöcke automatisch durch verschiedene Prozessoren schicken kann. So kann man längere Texte mit Textile formatieren, was gelegentlich einfacher zu lesen ist, als den Text komplett mit HAML auszuzeichnen (siehe Listing 2). Außerdem kann man eigene Filter definieren. Die Liste der momentan vorhandenen Filter führt die Tabelle unten auf.

Mehr Infos

Listing 2: HAML mit Textile

.about
:textile
h2. Dies ist eine Ăśberschrift

Dies ist ein Absatz

* Dies ist eine Liste

# Dies ist eine andere Liste


<div class='about'>
<h2>Dies ist eine Ăśberschrift</h2>
<p>Dies ist ein Absatz</p>
<ul>
<li>Dies ist eine Liste</li>
</ul>
<ol>
<li>Dies ist eine andere Liste</li>
</ol>
</div>

Manche HTML-Elemente können außer class- und id deutlich mehr Attribute enthalten. Hierzu kann man an einen HAML-Tag einen Hash in Ruby-Syntax anhängen. Dieser Hash wird als Ruby-Ausdruck analysiert, sodass man dort Methodenaufrufe unterbringen kann. Schließt man einen Methodenaufruf, der einen kompletten Hash zurückliefert, in die Hash-Klammern ein, wird er verwendet. Im Folgenden dient die Methode html_attrs aus dem Modul Haml::Helpers dazu, den Start-Tag html zu erzeugen:

%html{html_attrs(lang = 'de-DE')}

bewirkt

<html lang='de-DE' xml:lang='de-DE' xmlns='http://www.w3.org/1999/xhtml'>

Standardmäßig versucht HAML, das erzeugte HTML vernünftig eingerückt zu generieren. Manchmal muss man allerdings Whitespace zwischen Tags unterdrücken, um Abstände zwischen Elementen nicht zu gefährden. Dies kann man in HAML erreichen, indem man mit einem Größer-Zeichen alle Whitespaces um den Tag herum löscht und mit einem Kleiner-Zeichen alle Whitespaces innerhalb des Tag. Gegenüber dem HAML-Code

%p Vorher
%p><
foo
bar
%p Nachher

sieht das generierte HTML kompakt aus:

<p>Vorher</p><p>foo bar</p><p>Nachher</p>

Kommentare gibt es in zwei Varianten. Ein einfacher Schrägstrich erzeugt einen HTML-Kommentar, der einen darunter eingerückten Block enthalten kann. -# erzeugt einen „lautlosen“ Kommentar, der nicht in das HTML übertragen wird, demnach nur der Code-Dokumentation dient. Ein unterstützter Sonderfall sind die bedingten Kommentare für Microsofts Internet Explorer – gern für IE-spezifische Hacks eingesetzt (siehe Listing 3).

Mehr Infos

Listing 3: HAML-Kommentare

/ Esst mehr Obst!
-#
Dies ist ein leiser
Kommentar, der auch
mehrzeilig sein darf
/[if IE]
%a{ :href => 'http://www.mozilla.com/en-US/firefox/' }
%h1 Get Firefox


<!-- Esst mehr Obst! -->
<!--[if IE]>
<a href='http://www.mozilla.com/en-US/firefox/'>
<h1>Get Firefox</h1>
</a>
<![endif]-->

Gute Webentwickler sollten wenig Schwierigkeiten haben, sich auf die etwas exotische Syntax von HAML einzustellen. Schwieriger wird dies, wenn Frontend-Entwickler oder Designer an einem Projekt beteiligt sind. Der wenige Ruby-Code, der sich in (guten) ERB-Templates befindet, ist (guten) Designern in der Regel beizubringen. Der Umstieg auf HAML hingegen erfordert, wie der Name schon andeutet, ein gewisses Abstraktionsvermögen. Hier liegt die eigentliche Herausforderung bei der Benutzung.

Hat man ein Entwicklerteam zur Hand, dem insgesamt die Syntax keine Probleme bereitet, kann der Einsatz der beiden Sprachen deutlich ĂĽbersichtlicheren und besser wartbaren Code bewirken. Die Zeilenorientierung beider Sprachen vereinfacht die Verwendung von Versionskontrollsystemen, und die relativ strikten Syntax-Checks der Konverter erschweren es, invaliden Code zu erzeugen.

Jan Krutisch
ist MitbegrĂĽnder der Deutschen Rails-Usergroup und Rails-Team-Captain bei der mindmatters GmbH&Co. KG, die Webanwendungen entwickelt.

iX-Link

Liste der HAML-Filter
plain gut für lange Blöcke, die HAML nicht analysieren soll
javascript verpackt den Block in script-Tags und CDATA-Tags fĂĽr Inline-JavaScript
escaped dasselbe wie plain, aber mit HTML-Escaping
ruby evaluiert den Block als Ruby-Skript und setzt alle Ausgaben (beispielsweise mit puts) in das resultierende HTML ein
preserve gibt den Text mit Whitespace-Erhaltung aus, etwa fĂĽr die Ausgabe in textfield- oder pre-Tags
erb Block-Auswertung durch ERB ausgewertet. Die Auswertung von Ruby-Code erfolgt im selben Kontext wie im HAML-Template selbst
sass Block-Auswertung durch den SASS-Compiler, um Inline-CSS zu erzeugen
textile Der Block wird durch Textile (nutzt die RedCloth-Bibliothek) gefiltert.
markdown Block-Filterung durch Markdown (benutzt RDiscount, RPeg-Markdown, Maruku oder BlueCloth, wenn vorhanden)
maruku Block-Filterung durch Maruku, das einige Erweiterungen zu Markdown enthält

(hb)