Inhaltsverzeichnis
PUG – die Template-Engine
Diese Bändchen beschreibt kompakt und übersichtlich die in der Express-Middleware standardmäßig eingesetzte Template-Engine Pug. Express gehört zum Node.js-Stack. Das heißt, alle hier gezeigten Beispiele und Kommandos sind nur in einer Node.js-Umgebung lauffähig.
Pug ist ehemals unter dem Namen JADE veröffentlicht worden. Die Umbenennung wurde aufgrund von Copyright-Streitigkeiten notwendig.
Zielgruppe
Dieses Bändchen wendet sich an Anfänger und an Webentwickler, die neu in der MEAN-Welt sind. MEAN steht für “MongoDb Express AngularJs Node” und bezeichnet eine komplett auf JavaScript basierendes Entwicklungs-Ökosystem. Pug ist eine Option für die Erstellung von Ansichten in Express.
Vielleicht sind Sie aber auch ein Webdesigner, der JavaScript als eine hervorragende Möglichkeit entdeckt hat, seine Webseiten mit dynamischen Elementen aufzuwerten. Dabei haben Sie mit Texten zu tun, mit Formularen, mit der Darstellung von Datenbankinhalten, also alles, was eine dynamische Website ausmacht. Dann wird Ihnen dieses Bändchen einen der Teilaspekte, nämlich das Erzeugen des HTML auf dem Server, in besonders übersichtlicher Form zeigen.
Auf alle Fälle habe ich mich bemüht, keine Voraussetzungen an den Leser zu stellen. Sie müssen kein Informatiker sein, keine Programmiersprache perfekt beherrschen, keine höhere Mathematik kennen. Egal in welchem Zusammenhang Sie auf Pug gestoßen sind, Sie werden diesen Text lesen können.
MEAN
Um alle Beispiele nachvollziehen zu können, benötigen Sie eine lauffähige Node.js-Umgebung. Diese wird auch als “MEAN” (MongoDb, Express, AngularJs, Node) bezeichnet. Pug ist die standardmäßig benutzte Template-Engine der Middleware- und Routingkomponente Express. Ein weiteres Bändchen der Reihe “Jörgs Webbändchen” widmet sich Express und natürlich steht auch eine Einführung in node.js selbst bereit.
Wenn Sie diesen Text zufällig gefunden haben und mit dem Begriff “MEAN” nichts anfangen können, lesen Sie es trotzdem. Sie werden eine der modernsten Techniken der Webentwicklung kennenlernen und künftig gehören Sie zum Kreis hervorragender Entwickler, die hochperformante und zukunftsorientierte Websites bauen.
Was Sie wissen sollten
Leser dieser Reihe müssen kaum Voraussetzungen mitbringen. Etwas HTML kann nicht schaden und wer schon mal eine statische HTML-Seite gesehen hat (den Quellcode natürlich) kommt sicher gut rein. Ich gehe davon aus, dass Sie wenigstens ein aktuelles Windows-System haben. Sie können die Umgebung direkt auf Windows installieren oder auf Linux. Wenn Sie Windows 8 oder 10 haben, können Sie die Hyper-V-Umgebung nutzen, um darauf ein Ubuntu-Linux zu installieren. Es ist einfacher als Sie denken und auf jeden Fall einen Versuch wert.
Wie Sie diesen Text lesen können
Ich will Ihnen nicht vorschreiben, wie Sie diesen Text lesen sollten. Beim ersten Entwurf der Struktur habe ich mehrere Varianten ausprobiert und dabei festgestellt, dass es die ideale Form nicht gibt. Wenn ich mich an den verschiedenen Anwendungsarten orientiere, zerfällt der Text in mehrere Kapitel, die nicht im Zusammenhang miteinander stehen. Der eine oder andere Leser würde sich dann ärgern, dass er viel Geld für ein Buch ausgibt, das nur zu einem Fünftel verwendbar ist. Diese Bändchen löst das Problem, indem es auf ein sehr kleines Thema fokussiert ist und kein “bla-bla” zur Aufblähung des Umfangs dabei ist.
Anfänger sollten den Text als Erzählung lesen, von der ersten bis zur letzten Seite. Wer sich schon etwas auskennt, kann die für ihn weniger interessanten Abschnitte gefahrlos überspringen. Falls Bezüge notwendig sind, habe ich entsprechende Querverweise eingefügt.
Schreibweisen
Das Thema ist satztechnisch nicht einfach zu beherrschen, denn Skripte sind oft umfangreich und es wäre schön, wenn man die beste Leseform optisch unterstützen könnte. Ich habe deshalb oft zusätzliche Zeilenumbrüche benutzt, die der Lesbarkeit dienen, im Editor Ihrer Entwicklungsumgebung aber nichts zu suchen haben.
Generell wird jeder Programmcode mit einer nicht proportionalen Schrift gesetzt. Außerdem verfügen Skripte über Zeilennummern:
Wenn Sie etwas am Prompt oder in einem Dialogfenster eingeben müssen, wird dieser Teil der Anweisung fett geschrieben:
$ npm start
Ausdrücke und Befehlszeilen sind manchmal mit allen Arten von Zeichen gespickt und in fast allen Fällen kommt es auf jedes Zeichen an. Besonders das Leerzeichen ist nicht, wie in anderen Programmiertexten, beliebig verwendbar. Sie müssen genau so viele Zeichen eingeben, wie angegeben sind. Damit Sie Leerschritte richtig erkennen, werden diese wo es darauf ankommt mit dem Symbol • gekennzeichnet (ein kleiner Punkt in der Mitte der Zeile):
Oft werde ich die Verwendung bestimmter Zeichen in einem solchen Ausdruck genau erläutern (ich lasse Sie wirklich nicht mit solchen Zeichenschlangen allein). Dann werden die “wichtigen” Zeichen durch Zeilenumbrüchen alleingestellt und auch in diesem Fall werden Zeilennummern dazu dienen, das betroffene Symbol im Text exakt zu referenzieren (Beachten Sie das #-Zeichen in Zeile 6):
Jade nutzt Einrückungen zur Struktur. Die Leerzeichen am Anfang einer Zeile haben eine semantische Bedeutung. Die Schrift ist nicht-proportional, sodass die Zeichen abzählbar sind.
Symbole
Um die Orientierung bei der Suche nach einer Lösung zu erleichtern, gibt es eine ganz Palette von Symbolen, die im Text genutzt werden.
Über den Autor
Jörg arbeitet als Trainer, Berater und Softwareentwickler für große Unternehmen weltweit. Bauen Sie auf die Erfahrung aus 25 Jahren Arbeit mit Web-Umgebungen und vielen, vielen großen und kleinen Projekten.
Jörg sind vor allem solide Grundlagen wichtig. Statt immer dem neuesten Framework hinterher zu rennen wären viele Entwickler besser beraten, sich eine robuste Grundlage zu schaffen. Wer dies kompakt und schnell lernen will ist hier richtig. Auf seiner Website www.joergkrause.de sind viele weitere Informationen zu finden.
Jörg hat über 60 Titel bei renommierten Fachverlagen und im Eigenverlag texxtoor in Deutsch und Englisch verfasst, darunter einige Bestseller.
Kontakt zum Autor
Neben der Website können Sie auch direkten Kontakt über www.IT-Visions.de aufnehmen. Wenn Sie für Ihr Unternehmen eine professionelle Beratung zu Web-Themen oder eine Weiterbildungsveranstaltung für Softwareentwickler planen, kontaktieren Sie Jörg über seine Website oder buchen Sie direkt über http://www.IT-Visions.de.
1. Einführung in Pug
Pug ist eine Template-Engine für Express, der Middlware- und Routing-Lösung für Node.js. Sie ist der Standard für Express. Wenn Sie sich also intensiv mit Node.js und Express auseinandersetzen, führt kein Weg an Pug vorbei.
1.1 Übersicht
Pug nutzt eine vereinfachte Darstellung der HTML-Seite durch simple Textbefehle. Praktischerweise entsprechen diese den Namen der HTML-Tags. Da HTML eine Hierarchie aufbaut und Pug keine schließenden Tags kennt, muss die Baumstruktur anders entstehen. Pug nutzt dazu Einrückungen im Texteditor. 2 Leerzeichen zeigen an, dass das folgende Element ein Kindelement ist.
Vorbereitung
Pug setzt voraus, dass Sie mit node.js arbeiten und die Middleware Express nutzen. Der einfachste Weg zu einer funktionierenden Umgebung geht über ein schrittweises Abarbeiten der Bausteine einer node.js-Installation.
Damit steht die Umgebung, und der Beschäftigung mit Pug steht nichts im Weg.
Installationsanleitung
Zur Installation gibt es wenig Besonderheiten. Pug benötigt Express. Falls dies mit der Videoanleitung bereits installiert wurde, kann dieser Schritt überprungen werden. Ansonsten folgen Sie der Schrittfolge hier.
Installieren Sie nun das Pug-Paket. Ich habe meine Projekte unter /home/joerg/Apps und für dieses Bändchen dann unter Pug abgelegt. Legen Sie dann einen Ordner views an, in dem eine erste Testseite entstehen wird (sie befinden sich in Apps):
npm init erstellt die Node.js-Applikation. Dabei wird eine Paket-Datei erzeugt, deren Werte interaktiv abgefragt werden. Die erzeugte Paket-Datei kann noch manuell angepasst werden.
Legen Sie in dem neu erstellten Applikationsverzeichnis Pug eine Datei mit dem Namen index.js an. Sie hat folgenden Inhalt:
Starten Sie nun den Node-Server:
Geben Sie nun im Browser auf dem Entwicklungssystem folgende URL ein: http://localhost:3000. Sie sollten dann die “Hallo Express!”-Ausgabe sehen.
1.2 Applikationsstruktur
Express bietet eine Reihe spannender Funktionen. Ich will hier jedoch nur auf Pug eingehen und deshalb ist das manuelle Erzeugen und nutzen einer View einfacher. Lesen Sie “Jörgs Webbändchen” zu Express, um mehr über die Applikationsstruktur herauszufinden.
Die einfachste Nutzung von Pug besteht aus zwei Bausteinen. Zum einen die erste View, index.pug:
Zum anderen wird das “Hallo Express”-Beispiel so verändert, dass nun statt des statischen Texts die View benutzt wird:
Zum einen wird hier Pug als Standard vereinbart, sodass keine Dateierweiterung angegeben werden muss und das passende Modul vorab geladen werden kann. Dies passiert durch:
app.set('view engine', 'pug');
Dann wird statt res.send
die Funktion res.render
benutzt. Der erste Parameter ist der Name der View, der ohne Pfad (standardmäßig wird im view-Ordner gesucht) und ohne Dateierweiterung (standardmäßig wird nun pug benutzt) angegeben werden kann. Der zweite Parameter ist ein Objekt, dass lokale Variablen für die View bestimmt. Jede Eigenschaft des Objekts wird als lokale Variable bereitgestellt. Im Beispiel ist das der Wert title.
1.3 Pug-Views
Statt HTML schreiben Sie ab jetzt die Ansichtsseiten in pug. Noch einmal das eben benutzte Beispiel:
Auf jeder Zeile der View steht zuerst ein HTML-Tag. Statt der Schreibweise in XML-Form (<title></title>
) nimmt Pug hier eine vereinfachte Darstellung.
title= title
Der linke Teil ist das HTML-Element. Es folgt ein Gleichheitszeichen, dass die Kodierung bestimmt, also die Behandlung von HTML-spezifischen Entitäten wie <
oder >
. Dann folgt JavaScript. Da eine lokale Variable mit dem Namen title
vereinbart wurde, wird dieser Ausdruck hier hingeschrieben.
Analog funktioniert das mit h1
, dass unterhalb des body
-Elements steht. Der Umgang mit body
zielt darauf ab, dass Views üblicherweise auf Stammseiten (Layout- oder Master-Seiten) basieren und der eigentliche Inhalt über die Variable body
(rechts im Ausdruck) zugeordnet wird. Da HTML aus einer Seite direkt übernommen werden soll, wird der Operator !=
benutzt, der nicht codiert.
Umgang mit Teil-Ansichten
Teil-Ansichten (partial views) erlauben das Strukturieren von Views. Eine Pug-View sieht beispielsweise folgendermaßen aus:
Mit dem Befehl include
wird eine weitere View eingebunden, navigation.pug. Beachten Sie, dass diese ohne Anführungszeichen und Klammern angegeben wird.
Diese Navigation wird nun in einer weiteren Datei erstellt: views/navigation.pug:
Umgang mit Layout-Seiten
Eine Layout-Seite ist ein Master, eine Stammseite deren Inhalte von Inhaltsseiten bestimmt werden. Das entspricht der Layout-Seite in ASP.NET MVC oder der Master-Seite in ASP.NET.
Eine Layout-Seite sieht beispielsweise folgendermaßen aus:
Dies unterscheidet sich in kaum von dem vorherigen Beispiel. Lediglich das h1
-Element am Ende fehlt.
Im nächsten Schritt wird die Inhaltsseite erstellt. Sie heißt views/content.pug:
Sie verweist auf die Layout-Seite. Nun wird das Startskript angepasst, denn Pug rendert zuerst die Inhaltsseite, die ihrerseits die Layout-Seite aufruft.
Beachten Sie die res.render
-Funktion, die nun content statt vorher index aufruft (Zeile 5).
Jetzt kann der node-Server gestartet werden (im Ordner wo die Datei package.json steht):
npm start
Soweit der Standardport nicht anderweitig vergeben wurde zeigt der Browser die gerenderte HTML-Seite nun an:
http://127.0.0.1:3000/
Der Einstiegspunkt ist der Aufruf von res.render mit dem Argument der Inhaltsseite, content.pug. Die Engine sorgt dann für das Laden der Layout-Seite und die Verarbeitung. Der gesamte Vorgang findet also auf dem Server statt.
Dabei fällt auf, dass die Navigation verschwunden ist. Das ist das normale Verhalten. Denn nun wurde der Inhalt des body
-Elements tatsächlich durch eine Inhaltseite geliefert und damit wird der statische Inhalt überschrieben. Freilich gibt es hier einige Optionen, dieses Verhalten zu verändern. Dies wird in der Sprachreferenz genau beschrieben.
2. Sprachreferenz
Im Folgenden finden Sie eine systematische Sprachreferenz basierend auf der Original-Dokumentation. Der Einstieg in die online verfügbaren Informationen ist Github.
2.1 Doctype
Der typische HTML 5-Doctype wird direkt folgendermaßen geschrieben:
Das erzeugte HTML sieht dann folgendermaßen aus:
Kurzschreibweisen
Wegen der häufigen Nutzung von Doctypes gibt es ein paar Kurzschreibweisen.
Das erzeugte HTML sieht dann folgendermaßen aus:
Das erzeugte HTML sieht dann folgendermaßen aus:
Das erzeugte HTML sieht dann folgendermaßen aus:
Das erzeugte HTML sieht dann folgendermaßen aus:
Das erzeugte HTML sieht dann folgendermaßen aus:
Das erzeugte HTML sieht dann folgendermaßen aus:
Das erzeugte HTML sieht dann folgendermaßen aus:
Das erzeugte HTML sieht dann folgendermaßen aus:
Eigene Doctypes
Falls davon abweichende Doctypes notwendig sind, lässt sich folgende Syntax nutzen:
Folgendes HTML wird daraus erstellt:
Optionen
Die Doctypes sind nicht nur eine Information für den Browser. Sie sollten unbedingt die Pug-Version nehmen, denn diese wirken sich auch auf den HTML-Generator aus, beispielsweise auf den Umgang mit schließenden Tags.
Hier der direkte Aufruf des Renderers mit dem Doctype ‘XHTML’:
Folgendes HTML wird daraus erstellt:
Wird dagegen HTML erzeugt, wird das Tag nicht geschlossen:
Folgendes HTML wird daraus erstellt:
2.2 Attribute
Attribute sehen aus wie in HTML, die Argumente sind allerdings JavaScript, sodass hier einfach dynamisch gearbeitet werden kann.
Übersetzt sieht das folgendermaßen aus:
Alle üblichen JavaScript-Ausdrücke funktionieren problemlos. Sie werden mit -
abgetrennt, damit Pug sie nicht als HTML interpretiert:
Übersetzt sieht das folgendermaßen aus:
Mehrere Attribute lassen sich zur Verbesserung der Lesbarkeit auf mehrere Zeilen aufteilen:
Übersetzt nach HTML sieht das folgendermaßen aus:
Nicht codierte Attribute
Standardmäßig werden alle Attribute codiert, d.h. Sonderzeichen werden durch entsprechende Entitäten ersetzt (<
durch > und >
durch < usw.). Mit den Zuweisungszeichen =
und !=
lässt sich das Verhalten steuern:
In HTML sieht das folgendermaßen aus:
Logische-Attribute
Logische (boolean) Attribute werden in Pug als Funktionen dargestellt, die Argumente verarbeiten können, die ihrerseits true
oder false
ergeben. Wird kein Argument angegeben, ist der Standard true
.
Übersetzt sieht das folgendermaßen aus:
Wenn der Doctype des Dokuments HTML ist, werden die verkürzten Attribute benutzt, wie sie alle Browser verstehen:
Übersetzt sieht das folgendermaßen aus:
Stil-Attribute
Das style
-Attribut ist etwas komplexer, weil die Parameter ein Stil-Objekt darstellen. Im Gegensatz zur reinen HTML-Version, die nur als Zeichenkette gelesen werden kann, verarbeitet Pug hier in der Tat ein JSON-Objekt.
Dies sieht in HTML dann folgendermaßen aus:
&-Attribute
Diese spezielle Form, genannt “und-Attribute” (engl. “and attributes”) wird benutzt, um ein Objekt in Attribute zu zerlegen:
In HTML wird dann daraus folgendes:
Dabei muss es sich nicht um ein Objekt-Literal handeln, eine Variable die ein Objekt liefert eignet sich ebenso.
Hier entsteht dasselbe HTML draus:
2.3 Umgang mit CSS-Klassen
CSS-Klassen werden durch Attribute oder Literale beschrieben.
Das class-Attribut
Das class
-Attribut kann wie jedes Attribut mit einer Zeichenkette benutzt werden. Nun kommt es häufig vor, dass mehrere Klassennamen gesetzt werden. Dafür sind auch Arrays erlaubt.
Wie in Zeile 3 gezeigt, kann das Atribut wiederholt werden. Pug kombiniert die Einträge dann. In HTML wird dann daraus folgendes:
Wenn Klassennamen über Bedingungen gesetzt werden, muss meist eine separate Logik her. In Pug eignet sich dafür ein Objekt-Mapping:
Dies sieht in HTML dann folgendermaßen aus:
2.4 Das Class-Literal
Noch einfacher ist die direkte Nutzung der Literale aus CSS:
Dies sieht in HTML dann folgendermaßen aus:
Eine Besonderheit bei den Literalen ist das <div>
-Tag. Dies ist der Standard, wenn kein Element angegeben wird:
In HTML wird dann daraus folgendes:
2.5 ID-Literal
IDs nutzen die #idname-Syntax:
Dies sieht in HTML dann folgendermaßen aus:
Da das div
-Element sehr häufig benutzt wird, können Sie es weglassen:
In HTML wird dann daraus folgendes:
2.6 Befehle
Befehle bringen interaktive Abschnitte in die Vorlage. Sie ähneln den Möglichkeiten von JavaScript, werden jedoch vor der Skript-Ebene verarbeitet. HTML kann direkt eingebettet werden.
Fallunterscheidung (case)
case
ist eine Prozessanweisung und entspricht dem switch
in JavaScript. Die case
-Zweige in JavaScript werden bei Pug als when
geschrieben:
In HTML wird dann daraus folgendes:
Weiterleitung zum nächsten Fall
Ebenso wie in JavaScript fällt die Anweisung zum nächsten Zweig durch, wenn keine Anweisung folgt:
In HTML wird dann daraus folgendes:
Erweiterung von Blöcken
Statt der mehrzeiligen Schreibweise können kurze Texte auf derselben Zeile platziert werden und sind dann auf diese Zeile begrenzt:
Das HTML sieht dann folgendermaßen aus:
Bedingungen (if)
Bedingungen sind ein elementarer Baustein in pug. Gegenüber JavaScript ist die Schreibweise geringfügig vereinfacht – so können Sie die Klammern um die Bedingung weglassen.
Die Eingabedaten bestimmen dann, welches HTML entsteht:
Es gibt weiterhin das Schlüsselwort unless
für negierte Bedingungen:
Dies ist vollkommen identisch zum folgenden Ausdruck:
Iterationen
Mit each
und while
stehen zwei Möglichkeiten bereit, Schleifen zu bilden.
each
Die Anwendung von each
ist weitgehend intuitiv:
Das HTML wird auf Basis des Arrays auf dem Server gebildet:
Mit zwei Parametern besteht Zugriff auf den Index und den Laufwert:
Das HTML zeigt, dass der Index 0-basiert ist:
Werden Hashes (Objekt-Maps) benutzt, so lassen sich Index und Wert noch genauer bestimmen:
Das HTML zeigt, dass der Index vom Quellobjekt bestimmt ist:
Statt der direkten Angabe lässt sich natürlich jeder JavaScript-Ausdruck benutzen, der eine passende Struktur erzeugt oder enthält:
Da das Array im Beispiel leer ist, wird folgendes HTML erzeugt:
while
Eine Schleife mit while
verfügt über eine Abbruchbedingung. Die Schleife wird durchlaufen. solange der Ausdruck true
ergibt.
Das dynamisch erzeugte HTML sieht nun folgendermaßen aus:
2.7 JavaScript-Code
Mit Pug können JavaScript-Fragmente direkt in die Seite geschrieben werden. Diese Teile werden dann serverseitig ausgeführt. Es gibt dabei drei Arten von Code:
- Ungepufferte Codes
- Die Ergebnisse beim Verarbeiten werden sofort in die Ausgabe geschrieben.
- Gepufferte Codes
- Die Ergebnisse beim Verarbeiten werden zuerst in einen Puffer geschrieben und am Ende der Anweisung komplett gesendet.
- Gepufferte und nicht codierte Codes
- Die Ergebnisse beim Verarbeiten werden zuerst in einen Puffer geschrieben und am Ende der Anweisung komplett gesendet. Dabei erfolgt keine Codierung der Ausgabe.
Ungepufferte Codes
Ungepuffert und auch nicht codiert sieht das folgendermaßen aus:
Im HTML entsteht aus dem letzten Beispiel folgendes:
Dies funktioniert auch mit Blöcken (das -
-Zeichen ist alleinstehend abgesetzt und der folgende Text eingerückt):
Auch diese Schleife generiert pures HTML:
Gepufferte Code
Der gepufferte Teil startet mit einem =
-Zeichen und gibt das Ergebnis der Berechnung in JavaScript aus. Hier die codierte Variante (beachten Sie die Einrückung auf Zeile 2):
Im HTML sehen Sie, wie die Sonderzeichen konvertiert wurden:
JavaScript-Ausdrücke lassen sich auch hier einsetzen:
Es ergibt sich dasselbe Ergebnis wie im vorherigen Beispiel:
Gepufferte und nicht codierte Codes
Die Codierung startet wieder mit dem !=
-Operator. Beachten Sie auch hier, dass dies in Bezug auf Daten aus Benutzereingaben nicht sicher ist.
Das folgende HTML wird daraus erstellt:
Auch in dieser Nutzung können JavaScript-Ausdrücke eingesetzt werden:
Das folgende HTML wird daraus erstellt:
2.8 Kommentare
Kommentare werden wie in JavaScript geschrieben, werden dann jedoch in HTML-Kommentare konvertiert, also nicht komplett entfernt:
Das folgende HTML wird daraus erstellt:
Wird hinter das Kommentarzeichen ein Strich gesetzt, wird der Kommentar entfernt und im HTML nicht wiederholt:
Das folgende HTML wird daraus erstellt:
Kommentarblöcke
Soll sich ein Kommentar über mehrere Zeilen erstrecken, so wird das Kommentarzeichen alleine auf eine Zeile gestellt:
Das folgende HTML wird daraus erstellt:
Bedingte Kommentare
Der Internet Explorer kann Abschnitte bedingt ausführen, um abwärtskompatiblen HTML-Code zu schreiben. Pug hat dafür keine spezielle Syntax. Da jeder nicht weiter erkannte Text aber unverändert ausgegeben wird werden Zeilen, die mit dem <
-Zeichen beginnen, direkt ins HTML transportiert:
2.9 Erben von Vorlagen
Zum Erben von Vorlagen wird das Schlüsselwort extends
benutzt. Damit lassen sich auch vordefinierte Bereiche der Layout-Seite gezielt überschreiben. Zuerst die Layout-Seite:
Die eigentliche Seite nutzt (erbt) nun diese Layout-Seite. Der Bereich block
und darin der Bereich title
wird überschrieben. Die Angaben sind freiwillig und wenn sie nicht vorhanden wären, würde der Inhalt der Layout-Seite angezeigt werden.
Das finale HTML sieht nun folgendermaßen aus:
Details zum Vererben von Vorlagen
Das einfache Vererben von Vorlagen kann erweitert werden, indem mit block
Bereiche festgelegt werden, die gezielt überschrieben werden können. Ein “Block” ist dabei pug-Code, der ersetzt werden kann. Der Vorgang ist rekursiv.
Wenn der Platzhalter mit Inhalt bestückt ist, fungiert dieser als Standard. Betrachten Sie die folgende Layout-Seite:
Diese wird nun mittels extends
benutzt. Die Seite index.pug im folgenden Beispiel überschreibt dabei die Blöcke scripts und content. Der Block foot bleibt dagegen unverändert und wird aus der Layout-Seite übernommen.
In einem Block können weitere Blöcke definiert werden, die bei weiteren Ableitungen verschachtelter Layout-Seiten wiederum überschrieben werden. Die weitere Layout-Seite sub-layout.pug wird folgendermaßen definiert:
Die Seite page-b.pug nutzt diese abgeleitete Layout-Seite nun:
Die Blöcke sidebar und primary werden hier überschrieben.
Blöcken Inhalt voran- und hintenanstellen
Neben dem blanken Ersetzen lassen sich Inhalte auch voranstellen (prepend
) oder ergänzen (append
). Bei der Definition ändert sich erstmal nichts:
Weitere Skripte lassen sich nun wie folgt ergänzen:
Das Schlüsselwort block
ist bei der Benutzung von prepend
oder append
optional:
2.10 Filter
Filter dienen dazu, innerhalb des Quelltextes andere Sprachen zu nutzen. Typische Beispiele sind Markdown und CoffeeScript.
Der Sprachblock wird mit dem :
-Zeichen eingeleitet und entsprechend interpretiert. Das vorangegangene Beispiel sieht in HTML wie folgt aus:
2.11 Partielle Seiten
Komplexe Seiten lassen sich in Teile – partielle Seiten – zerlegen. Das Einbinden erfolgt mit dem Schlüsselwort includes
und der Angabe des Dateinamens, gegebenenfalls mit dem relativen Pfad.
Daraus entsteht folgendes HTML:
Text einbinden
Partielle Seiten müssen nicht nur Pug sein, auch einfacher Text kann benutzt werden. Pug erkennt dies automatisch:
Daraus entsteht folgendes HTML:
Kombination aus Filtern und partiellen Seiten
Bei der Kombination aus Filtern und partiellen Seiten werden Seiten eingebunden, die Inhalte in anderen Sprachen enthalten.
Die eingeschlossene Seite wird hier als Markdown interpretiert:
Daraus entsteht folgendes HTML:
Vor allem die Kombination mit Markdown ist interessant, weil bereits vorliegende Inhalte unverändert übernommen werden können.
2.12 Interpolationen
Interpolationen ersetzen Variablen in Zeichenfolgen. Vergleichbare Techniken kennt wohl fast jede Programmiersprache. Pug kennt folgende Operatoren:
- Codierte Zeichenketten-Interpolation
- Nicht codierte Zeichenketten-Interpolation
- Tag-Interpolation
Codierte Zeichenketten-Interpolation
In der folgenden Vorlage werden einige Variablen definiert und dann in Ausdrücken eingesetzt, ohne erneut auf JavaScript-Syntax zuzugreifen:
Das folgende HTML zeigt das Ergebnis der Interpolation:
Der Code zwischen #{
und }
wird ausgewertet, codiert und als gepuffertes Ergebnis an die Ausgabe gesendet. Der Ausdruck selbst kann wiederum JavaScript sein, sodass sogar hier komplexere Ausdrücke entstehen können.
Daraus entsteht in diesem Fall ziemlich cooles HTML:
Nicht codierte Zeichenketten-Interpolation
Falls Sicherheit nicht notwendig ist oder HTML gewünscht ist, geht auch hier wieder die nicht codierte Variante:
Das HTML wird unverändert ausgegeben:
Tag-Interpolation
Interpolationen lassen sich auch direkt in Tags einsetzen. Hierzu wird #[]
benutzt.
Hieraus ensteht recht kompaktes HTML:
Der Renderer nutzt intern seinen Puffer zur Ablage und zum Weiterleiten, sodass dies besser ist als direkt HTML einzubinden.
2.13 Mixins (Funktionen)
Mixins erzeugen wiederverwendbare Blöcke aus Pug-Code. Damit lassen sich endlose Wiederholungen gleicher HTML-Bausteine vermeiden. Besonders im Zusammenhang mit Bootstrap lassen sich so komplexere Konstrukte vorbereiten und dann jederzeit einsetzen.
Ein Mixin (lies: Funktion) wird folgendermaßen deklariert:
Die Benutzung basiert auf einem speziellen Operator:
Die Benutzung wird mit dem +
-Zeichen eingeleitet. Im HTML ist davon nichts mehr zu finden:
Mixins sind JavaScript-Funktionen und können wie diese mit Parametern versehen werden:
Folgendes HTML entsteht daraus:
Mixin-Blöcke
Mixins können eine Block mit Pug-Code aufnehmen und gewinnen damit weiter an Dynamik:
Folgendes HTML entsteht daraus:
Mixin-Attribute
Ähnlich wie bei JavaScript-Funktionen können Mixins Parameter über ein implizites attributes
-Objekt aufnehmen:
Folgendes HTML entsteht daraus:
Folgendes HTML entsteht daraus:
Weitere Argumente
Ist die Anzahl der Argumente nur teilweise variabel, lässt sich eine Definition der Art “der ganze Rest” aufbauen:
Folgendes HTML entsteht daraus:
2.14 Umgang mit Text
Einfacher Text wird nicht interpretiert und unverändert ausgegeben, auch wenn darin Steuerzeichen enthalten sind.
Text verbinden
Der |
-Operator (“pipe”) setzt vorhergehende Zeilen mit Text einfach fort.
Der Text kommt unverändert in der HTML-Seite an:
Inline im Tag
Tags in Tags sind in HTML an der Tagesordnung. Denn in fast jedem Blockelement sind diverse Inline-Elemente zu finden (<span>
im <div>
). Text nach einem Element wird unverändert übernommen und kann HTML enthalten. Das ist oftmals einfacher, als die komplette Hierarchie zu definieren:
Das HTML kommt unverändert in der Seite an:
Block im Tag
Oft werden große Blöcke mit Text benötigt. Skripte oder längere Stil-Definitionen sind gute Beispiele dafür. Hier wird selten Interaktivität verlangt. Um solch einen Block einzuleiten, wird dem Element-Befehl ein Punkt .
nachgestellt:
Der Inhalt kommt unverändert in der Seite an:
Umgang mit Tags
Tags werden lediglich durch Ihren Namen beschrieben, ohne die Markup-Klammern. Die Hierarchie wird durch die Einrückung (zwei Leerzeichen) festgelegt.
Aus diesem Beispiel entsteht gültiges HTML:
Wenn der Doctype dies verlangt werden selbstschließende Elemente automatisch erzeugt. Für das Element img
sieht das folgendermaßen aus:
Hier entsteht gültiges HTML mit schließendem Tag:
Erweiterungen von Blöcken
Verschachtelte Blöcke lassen, solange keine Inhalte folgen, auch in einer Zeile definieren. Dies erfolgt durch den :
-Operator. Dies spart Platz bei häufigen typischen Kombinationen, beispielsweise mit Hyperlinks:
Aus diesem Beispiel entsteht gültiges HTML wie folgt:
Selbstschließende Tags
Einige Tags, wie img
, meta
und link
enthalten nie Inhalt. Sie sind deshalb selbstschließend, ausgenommen mit dem XML-Doctype. Solle dies unabhängig vom Doctype angezeigt werden, kann dies mit einem abschließenden /
-Zeichen erfolgen.
Aus diesem Beispiel entsteht folgendes HTML:
3. Die Pug-API
Pug ist ein Paket das neben der Verarbeitung der Vorlagen einige Funktionen als Programmierschnittstelle (API) bereitstellt. Diese API wird nachfolgend kurz beschrieben.
3.1 API-Optionen
Jede Methode der API akzeptiert ein Optionen, die als JSON-Struktur übergeben werden:
Die einzelnen Parameter haben folgende Bedeutung:
- filename
- Der Dateiname; wird beispielsweise in Ausnahmen angezeigt
- doctype
- Der Doctype, wenn dieser nicht als Teil einer Vorlage angegeben werden soll
- pretty
- Zeigt an, ob Leerzeichen zum ausgegebenen HTML hinzugefügt werden sollen, um lesbaren Code zu erzeugen. Wenn eine Zeichenkette angegeben wird, ist dies der Wert, der zum Einrücken benutzt wird, z.B.
\t
. - self
-
self
-Namensraum für lokale Variable (standardmäßigfalse
) - debug
- Protokolliert Ausgaben nach
stdout
- compileDebug
- Der Quellcode wird in die gerendete Ausgabe übertragen
- cache
- Funktionen werden gecachet. Schlüssel ist der Dateiname der Vorlage.
- compiler
- Ein alternativer Compiler kann angegeben werden.
- parser
- Ein alternativer Parser kann angegeben werden.
- globals
- Globale Variablen, die in allen Vorlagen bekanntgegeben werden
3.2 API-Funktionen
In allen Funktionen ist der Parameter options
das zuvor beschriebene Options-Objekt. Nicht alle Optionen sind in allen Fällen sinnvoll.
pug.compile(source, options)
Diese Funktion übersetzt Pug-Code, sodass dieser dann mehrfach mit verschiedene Werten ausgeführt werden kann. Gibt eine Funktion zurück, die ausgeführt werden kann. Der Befehl auf Zeile 2 erstellt die Funktion, auf Zeile 3 wird diese dann ausgeführt.
Dieses Skript erzeugt folgende Ausgabe:
pug.compileFile(path, options)
Diese Funktion übersetzt Pug-Code aus einer Datei, sodass dieser dann mehrfach mit verschiedenen Werten ausgeführt werden kann. Gibt eine Funktion zurück, die ausgeführt werden kann. sourcepath
ist der Pfad zur Pug-Datei. Der Befehl auf Zeile 2 erstellt die Funktion, auf Zeile 3 wird diese dann ausgeführt.
Dieses Skript erzeugt folgende Ausgabe, wenn die Datei index.pug den Text “p pug ist cool!” enthält:
pug.compileClient(source, options)
Hier wird eine JavaScript-Funktion gerendert, die dann später clientseitig ausgeführt werden kann und dort das erstellte HTML erzeugt.
Die Rückgabe ist dann JavaScript:
pug.compileClientWithDependenciesTracked (source, options)
Diese Methode entspricht der vorhergehende methode compileClient
, erzeugt jedoch ein Objekt, das folgende Struktur hat:
Damit können Änderungen an Quelldateien überwacht werden. Ansonsten ist die einfache Variante zu bevorzugen.
pug.compileFileClient(path, options)
Hier wird eine JavaScript-Funktion gerendert, die dann später clientseitig ausgeführt werden kann und dort das erstellte HTML erzeugt. Die Quelle muss als Datei vorliegen.
Das Options-Objekt hat einen weiteren Parameter name
. Diese bestimmt den Namen der Funktion, die erzeugt wird und auf dem Client aufgerufen werden kann. Hier ein Beispiel mit einer Quelldatei pugFile.pug:
Diese wird nun dynamisch übersetzt (Zeile 4):
Nehmen Sie an, Sie wollen alle Ihre Vorlagen in eine einzige Datei übersetzen und diese dann an den Client übertragen. Dann kann die Ausgabe des letzten Beispiels jsOut folgendermaßen gespeichert werden:
Die Datei templates.js, die daraus entsteht, enthält dann die oben definierte Funktion templateFunction:
Damit das funktioniert, muss auch die Laufzeitumgebung von Pug verfügbar sein. Sie steht unter dem Namen runtime.js zur Verfügung. Im HTML des Clients sieht das dann folgendermaßen aus:
pug.render(source, options)
Diese Funktion rendert direkt in HTML:
Das HTML sieht nun so aus:
pug.renderFile(filename, options)
Auch diese Funktion rendert direkt in HTML, nutzt aber als Eingabe eine Datei:
4. Die Kommandozeile
Die Kommandozeile kann Hilfsfunktionen direkt ausführen, beispielsweise Seiten vorab in statisches HTML übersetzen.
4.1 Installation
Die Installation erfolgt via npm (-g steht für global):
4.2 Benutzung und Optionen
Die Benutzung der Kommandozeile sieht folgendermaßen aus:
Optionen | |
---|---|
-h, --help |
Hilfe zur Benutzung |
-V, --version |
Version der Bibliothek |
-O, --obj <path|str> |
JavaScript-Optionen oder JSON-Datei mit einem passenden Objekt darin |
-o, --out <dir> |
Ausgabeverzeichnis für das HTML |
-p, --path <path> |
Dateipfad zum Auflösen von includes
|
-P, --pretty |
HTML Ausgabe wird lesbar gestaltet |
-c, --client |
Übersetzungsfunktion für die clientseitige runtime.js |
-n, --name <str> |
Der Name des übersetzten Templates (erfordert –client) |
-D, --no-debug |
Ohne Debugger übersetzen (kleinere Funktionen) |
-w, --watch |
Überwacht Dateien auf Änderungen und rendert neu |
-E, --extension <ext> |
Gibt die Dateierweiterung für die Ausgabe an |
--name-after-file |
Name des Templates nach dem letzten Segment des Dateipfades beim Lesen der Vorlage |
|
(erfordert –client, überschrieben durch –name) |
--doctype <str> |
Bestimmt den Doctype auf der Kommandzeile (sinnvoll, wenn das Template nichts enthält) |
Anwendungsbeispiele für die Kommandozeile
Übersetzen Sie Vorlagen lokal wie folgt:
Erzeugen Sie zwei HTML-Dateien , “foo.html” und “bar.html”:
Pug-Ergebnisse können über stdio
ausgegeben werden:
Eine Umleitung auf Pug erfolgt durch das Pipe-Symbol:
Rendern Sie die Verzeichnisse “foo” und “bar” nach /tmp: