Select Page

NETWAYS Blog

HUGO: Statische Websites generieren aus Markdown-Dateien

Im Studium hatte ich ein Seminar zur Webentwicklung – da haben wir einfache Websites in reinem HTML-Text mit etwas CSS drum herum geschrieben. Alternativ dazu wurde uns da noch die Benutzung des CMS (Content-Management-Systems) WordPress erklärt.

Im Zuge meiner Ausbildung bei der NETWAYS Professional Services durfte ich mich nun mit dem Static Site Generator Hugo auseinandersetzen. Ein Static Site Generator ist im Prinzip ein Tool das auf Basis von Rohdaten und Templates eine ganze statische HTML-Seite generieren kann. Im Falle von Hugo entscheidet man sich am Anfang der Seite für ein Theme. Je nachdem was herauskommen soll bieten sich verschiedene Themes an – so gibt es beispielsweise für Präsentationen und zum Schreiben von Dokumentationen spezielle Themes. Besonders zum Schreiben von Blogs existieren sehr viele (fast 300) Themes.

Es empfiehlt sich die Website lokal auf dem Client mit einer Hugo-Installation zu erzeugen und diese anschließend auf einen Webserver zu übertragen. Alternativ dazu bietet Hugo auch einen integrierten Webserver, der sich unter anderem mit einem LiveReload-Feature besonders gut zum Entwickeln der Seite eignet. Der Inhalt der Website wird bei Hugo grundsätzlich in Markdown-Dateien geschrieben, falls zusätzliche Formatierungen gewünscht sind kann auch HTML & ggf. auch JavaScript-Code integriert werden. Anstatt Inline-HTML-Code zu nutzen ist auch das Abrufen von Shortcodes möglich. Shortcodes sind im Prinzip kleine Codeschnipsel die eingebaute oder benutzerdefinierte Templates abrufen. Davon sind einige bereits von vornherein integriert, etwa zum simplen Einbetten von Videos auf bekannten Plattformen. Natürlich können Shortcodes in Hugo auch selbst angelegt werden. Hier mal exemplarisch ein Shortcode in der Datei ‘toc.html’:

{{ .Page.TableOfContents }}

Dies würde das vordefinierte TableOfContents-Template abrufen, welches auf Basis von Markdown-Überschriften dann ein Inhaltsverzeichnis generiert. Außerdem können in einem bestimmten Ordner auch Daten in den Formaten JSON, TOML und YAML abgelegt werden und in Hugo wieder eingelesen werden. Auch hier ein Beispiel, diesmal Produktdaten in einer YAML-Datei:

responsible: "Bjoern Berg"
product: "Gohugo"
id: [12345]

Falls gleich mehrere Leute (auch gleichzeitig) an einer Hugo-Website bauen sollen kann die Hugo-Seite auch als Git-Repository umgesetzt werden, so dass alle Personen Zugriff auf die Rohdaten der Website haben. Da es auf Websiten oft einige gleichartige Arten von Beiträgen gibt, können dafür Archetypen erstellt werden. Diese beinhalten dann bspw. bereits ein Grundgerüst für einen solchen Artikel wie Überschriften, Unterüberschriften, Tabellen und Metadaten. Per default erzeugt Hugo die URL-Struktur aus der Ordnerstruktur in den Rohdaten (die sich wiederum aus den vorher erwähnten Archetypen erzeugt). Alternativ dazu kann die URL-Struktur auch selbst spezifiziert werden (was dann für einen ganzen Archetyp gilt). Damit ist z.B. eine Terminologie a la example.com/2021/11/hugo-static-site-generator/ möglich. Dies wird dann im Buildprozess der Website umgesetzt (was bei Nutzung des in Hugo integrierten Webservers direkt nach Speichern der Markdowndatei geschieht). Ebenso im Buildprozess kann Hugo Bilder umformen – dabei ist das unter anderem das Konvertieren zwischen verschiedenen Dateiformaten, Bildgrößen und die Rotation des Bildes möglich.

Mein Eindruck von Hugo ist, dass es damit sehr einfach ist, eine schöne Website zu erstellen und diese auch effizient mit Daten zu befüllen. Durch die große Auswahl an Themes gehen auch viele verschiedene Websites und Designs. Wenn Du auch so tolle Projekte in Deiner Ausbildung zum Fachinformatiker machen möchtest, kannst du Dich gerne für einen Ausbildungsbeginn im Herbst 2022 bewerben!

Björn Berg
Björn Berg
Junior Consultant

Björn hat nach seinem Abitur 2019 Datenschutz und IT-Sicherheit in Ansbach studiert. Nach einigen Semestern entschied er sich auf eine Ausbildung zum Fachinformatiker für Systemintegration umzusteigen und fing im September 2021 bei NETWAYS Professional Services an. Auch in seiner Freizeit sitzt er viel vor seinem PC und hat Spaß mit diversen Spielen, experimentiert auch mit verschiedenen Linux-Distributionen herum und geht im Sommer gerne mal campen.

Introduction to SVG: The Basics

Lately I’ve been spending a some time building SVGs.
When I told my colleagues about what I was doing they asked me to write a short guide about what exactly that is and what you can do with it.
Since I got those questions, i thought that might be interesting for others out there, so here goes nothing:

First of all: what is SVG?

Just like JPEG or PNG, SVG is an image format, which lets us display images or graphics on the web.
SVG stands for ‘Scalable Vector Graphics’ – You might have heard about vectors in a different context already, like maths class or physics maybe?
The concept is the same: there is a direction and a force which helps to describe a path.
This means, that those graphics do not consist of fixed pixel values, but instead they’re a set of directions for whoever renders it (usually the user agent / browser) to follow.

SVG is written in a format that resembles XML, which means you have your image in a human readable plaintext file!

Why does that make it special?

The fact, that the graphics are made up with vectors comes with a bunch of useful qualities:

  • Scalability: It doesn’t matter, if you make the image 30x30px or 3000x3000px, it will stay sharp
  • Responsiveness: Because of its’ scalability you can have it take up whatever space you need it to
  • Programmable: Since your image is basically a text file, you can modify it programmatically as well, which gives it a flexibility unmatched by other common options.
  • Performance: Since we’re not sending out a binary blob of pixels but a text file, there is next to no loading time for the images.

The most common use cases are logos, icons and icon fonts, animations and diagrams.

What does it look like?

This is a simple svg, which we will be building together over the course of this blogpost:

First we define a simple 20×20 “coordinate system”, where 0,0 is in the top left corner.
In the viewBox we define what part of the SVG we will see when it is rendered. Positive x values move to the right and positive y values move downwards.
<svg viewBox="0 0 20 20"></svg> For a better understanding of the slightly mind-fucky topic of the viewBox property, check this out.

 

To start of with we want to draw the head:
For that we just use a <rect> element to draw a rectangle that fills the entire space.
<rect class="body" width="20" height="20"></rect>

 

The eyes consist of two <circle> elements that we position with cx and cy and give them a radius r of 1 unit.
<circle class="eye" cx="5" cy="15" r="1"></circle>
<circle class="eye" cx="15" cy="15" r="1"></circle>

 

When you put everything together the code for it looks something like this:

<svg viewBox="0 0 20 20">
  <rect class="body" width="20" height="20"></rect>
  <circle class="eye" cx="5" cy="15" r="1"></circle>
  <circle class="eye" cx="15" cy="15" r="1"></circle>
</svg>

So far we’d only have a black box, but as you might have noticed, I also added the class attribute into the elements.
This is for styling the SVG via CSS.
It is also possible to style the elements within their tags, but using CSS is usually preferred, since it makes it possible to style images with user themes as well!
This is the CSS:

.eye {
fill: #444;
}

.body {
stroke-width: 2;
stroke: #444;
fill: #f15a22;
}

 

The drawn lines can be edited with stroke  and if the fill attribute changes the colour that fills up the shape:

You can find the pen here.

Drawing our own images

Combining shapes is all nice and cool, but there are a lot more you can do with SVGs – for example create your own shapes.
We can do this with the path element. For it to know what to draw it needs the d attribute in which we can describe the path of the element.

<path d="M1,2 l4,4 h10 l4,-4 v17 h-18 Z"></path>

 

The d attribute has a syntax consisting of a few letters and a lot of numbers, that can look quite scary and unreadable at first, but when we break it down, it should look a lot clearer:
The letters are the commands and the numbers are their passing values.

 

M is the first command used. It’s the move command – so what it does is move the cursor to the position indicated by the numbers and is the starting point for our path.
M1,2 means it starts one unit to the right and two down.

 

The letters for the commands can either be uppercase to indicate absolute values or lowercase to indicate values that are relative to the last point we drew.
While m4,0 means “Move the cursor 4 units to the right”, M4,0 means move it to the position 4,0.

Basic commands for drawing lines

The next commands we want to look at describe straight lines:
L: any direction
H: horizontal
V: vertical
Z: last element for closing path

 

<path d="M1,2 L5,6 H15 L19,2 V19 H1 Z"></path>
We’re starting at M1,2.
First line is to position 5,6, so 4 to the right and 4 down with L5,6.
Then a horizontal line to H15.
Another line that goes up and to the right with L19,2.
Down to y value 19 with V19.
All the way left to x position 1 with H1
Finally, we close the path with the Z command.

 

It’s entirely up to you if you want to draw with relative or absolute values, in a 20×20 grid those two would draw the same image:

<path d="M1,2 l4,4 h10 l4,-4 v17 h-18 Z"></path>
<path d="M1,2 L5,6 H15 L19,2 V19 H1 Z"></path>

Adding the path together with the circles from our first head and applying the CSS again the image looks like this:

You can find the pen here.

Getting those round corners

The little fox looks a little square still, so we want to edit it to give it some round cheeks.

For this we use the q command, which stands for ‘quadratic curve’.

The q command requires two points, the one around which the curve should be and the point to which the line will go.

We draw the ears like we have before but instead of going down to the 19,19 corner, we stop 2 units further up.

From the point 19,17 we use the command Q19,19 17,19.
This indicates, that we want to wrap around the 19,19 and end at the 17,19 point.

The d value for this fox looks like this:

d="M1,2 L5,6 H15 L19,2 V17 Q19,19 17,19 H3 Q1,19 1,17 Z"

You can find the pen here.

 

Next in the series is going to be a bit more in depth about the more advanced commands and we will extend on the foxes head to make it look like this:
So stay tuned!

If you thought this was fun, maybe you want join our development team, to learn more about the SVGs and the like?

Feu Mourek
Feu Mourek
Developer Advocate

Feu verbrachte seine Kindheit im schönen Steigerwald, bevor es sich aufmachte die Welt zu Erkunden. Seit September 2016 unterstützt es Icinga zunächst als Developer und seit 2020 als Developer Advocate, und NETWAYS als Git und GitLab Trainer. Seine Freizeit verbringt es hauptsächlich damit Video-, und Pen and Paper Rollenspiele zu spielen, sich Häuser zu designen (die es sich nie leisten können wird) oder ganz lässig mit seinem Cabrio durch die Gegend zu düsen.

Entwicklerazubis: Jahr 1, das Projekt

Man bekommt nicht immer das, was man will… außer, man ist bei NETWAYS Azubi!

 

Mein erstes Jahr bei NETWAYS ist fast vorüber, und meine jugendlichen Ambitionen haben den Wunsch in mir erweckt, mit den beiden anderen Dev-Azubis meines Jahres, Loei und Niko, ein eigenes Projekt zu übernehmen, um unsere erlernten Fertigkeiten zu prüfen, eine Übersicht davon zu bekommen, auf welchem Stand wir alle sind, den ein oder anderen Trick voneinander aufzuschnappen und eigenverantwortlich und kooperativ ein Projekt zu vervollständigen. Und alles, was es gebraucht hat, um diesen Wunsch zu erfüllen, war diese Idee zu pitchen und klar und deutlich zu vermitteln, warum dieses Interesse besteht, und was wir uns davon erhoffen. Meine Vorgesetzten scheinen von der Idee zumindest angetan genug gewesen zu sein, dass wir drei Wochen eingeräumt bekommen haben, um uns um dieses Projekt zu kümmern. Danke, NETWAYS!

Die Aufgabe klingt einfach, hat es aber doch durchaus in sich – aus Berichten in Icinga sollen PDFs generiert werden. Die Funktionalität ist schon vorhanden – unsere Aufgabe ist es, den Benutzern mehr Features zur Verfügung zu stellen, damit man eigene Anpassungen an dem Aussehen der PDFs vornehmen kann. Das Schöne an dieser Aufgabe ist die Breite der Elemente und Bereiche, welche eine Rolle dabei spielen. Icingaweb, PHP, HTML, CSS, Google Chrome… es ist in gewisser Art und Weise eine große Reise in das Unbekannte, und natürlich können wir alle drei uns nicht sicher sein, welche Probleme und Hürden sich uns in den Weg stellen werden, und wie die zündenen Ideen kommen, die uns helfen, diese Hürden zu überwinden.

 

Boo

Much better

Und zündende Ideen gab’ es bereits! Ein Beispiel: Google Chrome baut sich aus HTML-Code die PDFs zusammen, lässt sich es aber nicht nehmen, automatisch generierte Header und Footer anzufügen, mit Seitenzahl und Datum. Das ist natürlich ein Element, welches wir gerne unter Kontrolle hätten! Der erste Hack, mit dem ich mich über diese Hürde bewegt habe, ist ein CSS-Styleelement an den übergeben HTML-Code anzufügen. Das ist in seinem momentanen Zustand natürlich noch etwas unschön gelöst, wenn einfach nur der HTML-Code um ein fest eingebautes Codeelement erweitert wird, aber wir haben einen Einstiegspunkt, einen Ansatz, mit der wir weiterbauen und -basteln können.

 

Scheue Dich vor Fragen nicht!

Auch wenn der Kerngedanke dieses Projekts natürlich daraus besteht, dass wir uns selbst beweisen, spricht natürlich Nichts dagegen, bei Fragen, die aufkommen, einen der zahlreichen Experten die NETWAYS hat zu involvieren. Was Benutzeroberflächen angeht, ist bei uns UX-Designer Florian der Ansprechpartner Nummer 1. Wir haben uns zusammengesetzt und konnten ihm live beim Bauen eines Mockups in Sketch zusehen. Eine Gelegenheit, durch die großen Augen, die wir gemacht haben, auch etwas über grundlegende Designansätze in Icingaweb zu lernen, und Grundsätze bezüglich Design. Mit diesem Wissen können wir erstmal diesen Pfad weiter selbst beschreiten, aber natürlich werden wir viel Rücksprache führen. Nur weil man bisher nicht dazu kam, sich extensive Kenntnisse in einem Bereich selbst anzueignen, heißt das nicht, dass man dieses Wissen, wenn es einem zur Verfügung steht, nicht nutzen kann. Und immer schön dran denken, selbst den Fundus an Talenten zu erweitern.

A mockup of things to come…

 

Kooperatives Kodieren

Einer der in meiner Einleitung angesprochenen Tricks, den ich einfach für neat halte, und sehr dem Spirit dieses Projektes entspricht, ist die Möglichkeit in git Co-Authoren einzutragen. Dafür muss man in der commit message einfach

 Co-authored-by: Name <e-mail>

angeben, und git verlinkt automatisch zwei Autoren für diesen commit. In diesem Fall meine beiden Kollegen bei diesem Projekt. Gute Arbeit, Jungs!

Da kann man ruhig mal klatschen! ?

 

Willst Du uns vielleicht nächstes Jahr bei dem nächsten Entwicklungsprojekt behilflich sein? Dann raus mit Deiner Bewerbung an NETWAYS! Wir freuen uns schon auf dich!

Verschachtelte Listen mit Sortable.js

Nachdem ich vor einiger Zeit die Ehre hatte Drag & Drop im Business Process Modul für Icinga Web 2 zu integrieren, dachte ich mir ich plaudere heute mal ein wenig aus dem Nähkästchen welche Stolpersteine ich dabei überwinden musste.

Aber erst einmal eine kleine Vorstellung der Bibliothek die eingesetzt wurde: Sortable.js 

Die Entscheidung hierfür fiel erst nicht leicht, da das Angebot jener Bibliotheken die sich Drag & Drop verschrieben haben, nicht besonders klein ist. Aber wo wir gerade von klein reden, ist das bereits der wichtigste Punkt der Sortable.js von anderen abhebt. Weil sie nur das nötigste an Funktionalität abdeckt und keine fancy Animationen nutzt die nicht nur Leistung fressen sondern auch Dateigröße ist diese Bibliothek mit 25kB (minimized) eines der Leichtgewichte unter ihren Vertretern. Außerdem existiert keine Abhängigkeit zu jQueryUI, das alleine hat bereits überzeugt.

Nun aber zum eigentlichen Thema. Während Sortable.js wunderbar mit einfachen Listen arbeiten kann, wird es etwas anspruchsvoller wenn es um verschachtelte Listen geht. Glücklicherweise wurde in diesem Segment in den letzen Wochen einiges getan und die Unterstützung erheblich verbessert. Dennoch gibt es etwas das immer noch existiert und mir einige ruhelose Nächte bereitet hat. Gut, so schlimm war es nun auch wieder nicht, dennoch, es könnte ja einigen genauso wie mir nicht sofort wie Schuppen von den Augen fallen.

Aber erst einmal die Demo die das Problem darstellt. Versucht einmal alles aus der roten Liste zu entfernen und dann wieder Elemente aus der blauen hineinzuschieben. Demo

Klappt nicht so ganz? Tja, das liegt daran, dass die rote Liste zu klein ist sobald keine Elemente mehr enthalten sind. Der findige Leser denkt jetzt eventuell daran der Liste eine Mindesthöhe zu geben. Gar nicht so falsch. Demo

Klappt dennoch nicht? Hehe, willkommen im Club. Ein Blick in die README.md von Sortable.js und man findet emptyInsertThreshold. Leider führt der Name dieser Option eher in die Irre, denn die Lösung ist sie nicht. Euer Blick sollte eher auf invertSwap fallen. Demo

Warum das nun funktioniert? Arr, das geht etwas über das Ziel des Beitrags hinaus. Ich kann euch aber folgendes ans Herz legen.

Johannes Meyer
Johannes Meyer
Lead Developer

Johannes ist seit 2011 bei uns und inzwischen, seit er 2014 die Ausbildung abgeschlossen hat, als Lead Developer für Icinga Web 2, Icinga DB Web sowie alle möglichen anderen Module und Bibliotheken im Web Bereich zuständig. Arbeitet er gerade mal nicht, macht er es sich bei schlechtem Wetter am liebsten zum zocken oder Filme/Serien schauen auf dem Sofa gemütlich. Passt das Wetter, geht's auch mal auf eines seiner Zweiräder. Motorisiert oder nicht.

How css-tricks improved my work life

My relationship with CSS is some kind of a love-hate one and I think that is a sentiment a lot of web-devs share with me.
My biggest issue with it is, that it is really counterintuitive and most of the time it feels a bit like solving puzzles to make things align the way you want it to.

and oftentimes it feels a lot like


Properties that mean the same thing being worded inconsistently – I’m looking at you…

vertical-align: middle;
text-align: center;

And there is also some questionable naming with ‘grey’ (#808080) being darker than ‘darkgrey’ (#a9a9a9)…
In general there are too many quirks you need to just know. Unless you work with it every day, you need to google every second line in order to write your stylesheets.
There you can find all sorts of guidelines, help, blogposts with a nice mix of bad-practices and outdated information.
What helped me a lot is the website css-tricks.
read more…

Feu Mourek
Feu Mourek
Developer Advocate

Feu verbrachte seine Kindheit im schönen Steigerwald, bevor es sich aufmachte die Welt zu Erkunden. Seit September 2016 unterstützt es Icinga zunächst als Developer und seit 2020 als Developer Advocate, und NETWAYS als Git und GitLab Trainer. Seine Freizeit verbringt es hauptsächlich damit Video-, und Pen and Paper Rollenspiele zu spielen, sich Häuser zu designen (die es sich nie leisten können wird) oder ganz lässig mit seinem Cabrio durch die Gegend zu düsen.