Jekyll Blog: Markdown aus HTML wiederherstellen
Ich habe den markdown-Code meines Blogs gelöscht. Hier beschreibe ich, wie ich ihn restauriert habe.
Beim Aufräumen habe ich versehentlich das falsche Verzeichnis von einem Server gelöscht, nämlich das Git-Repository, in dem Jekyll aus Markdown-Dateien und Metadaten das HTML des Blogs rendert. Das gerenderte Resultat war auf blog.heinle.cc natürlich noch vorhanden, nur kann man ohne den Markdown-Code und die Metadaten neue Beiträge nur schwer anlegen oder alte bearbeiten. Also muss der Code restauriert werden.
Voraussetzungen
Man braucht:
ein Backup vom Repository, das man einfach wiederherstelltBackup hatte ich keins, weil das Repository am falschen Ort lag. Am richtigen wäre es natürlich gesichert worden. Zu spät, sich darüber zu ärgern.- pandoc um HTML nach Markdown zu konvertieren. Die Hauptarbeit.
- Ein Python-Script, das sich um den Rest kümmert. Posts einsammeln, Metadaten extrahieren, etc
- (optional) Typora oder einen anderen Markdown-Editor, der gut mit Tabellen umgehen kann. Hilfreich, wenn man Tabellen hatte.
- Den HTML-Code und die Bilder des Blogs
GitHub-Repo
Wer nur den Code will, um es selbst zu versuchen, findet ihn in meinem GitHub Repo: jekyll-restore. Wie die Scripte benutzt werden, steht dort in der README.
Im weiteren Post werde ich erklären, was der Code tut und wieso. Es gibt mehrere Baustellen:
Inhalt einzelner Beiträge extrahieren
Generell hat man mit Jekyll relativ viel Glück beim Restaurieren, da die meiste Komplexität des HTML-Codes im Theme steckt und der eigentliche Text des Blogposts relativ simpel bleibt. Damit kommt pandoc gut klar und kann taugliches Markdown aus dem HTML-Code übersetzen. Das komplizierteste sind meist Code-Snippets mit Syntax-Highlighting. Weniger glücklich ist der Umgang mit Tabellen. Je nach Aufbau der Tabelle kommt pandoc überhaupt nicht damit klar. Darum kümmert sich dann gegebenenfalls Typora.
Wichtig ist, dass man pandoc nicht das komplette HTML-Dokument zum Übersetzen
gibt. Darin wären Theme-Details wie Header des Blogs, Navigation, Footer und
weitere Stile-Elemente enthalten, die man später wieder über das Theme bekommt
und die im Markdown-Code nichts zu suchen haben. Der Hauptteil des Blogposts
ist in einem <div itempromp="articleBody">
enthalten. Mit einem HTML-Parser
kann man so die Eingabedaten schon auf das Wesentliche reduzieren. Ich nutze
dazu BeautifulSoup.
Hat man den HTML-Code auf den Text des Posts reduziert, kann man ihn schon
einmal durch pandoc schicken und von HTML nach Markdown konvertieren lassen.
Danach müssen Code-Snippets mit und ohne Syntax-Highlighting noch korrigiert
werden. Pandoc ist zwar schlau genug, sie dank der <code>
-Tags im HTML
drum herum nicht als tausend verschiedene <span>
-Tags zu interpretieren,
kommt aber mit den umgebenden <div>
-Tags nicht gut klar. Auch das Erkennen
der jeweiligen Sprache des Syntax-Highlightings gelingt nicht. Die notwendigen
Informationen sind glücklicherweise aber nicht verloren, müssen nur richtig
umgebaut werden. Was Pandoc von <div>
mit Klassen nach :::
-Tags mit
Attributen im Markdown übersetzt, lässt sich mit ein paar regulären Ausdrücken
einfach reparieren; selbst die Sprache für das Highlighting kann wieder richtig
in die Backticks der Code-Blöcke geschrieben werden.
Metadaten
Nebst den eigentlichen Beitragstexten sind die Metadaten der Posts wichtig. Nur wenn das Datum des Posts, der Titel in Slug-Form und die Konfiguration der Permalinks gleich wie vor der Restauration sind, ergeben sich bei Jekyll die gleichen URLs für die Beiträge. Stellt man nicht sicher, dass die URL der Posts alle gleich bleiben, brechen interne Verlinkungen im eigenen Blog, Verlinkungen von außen und man verliert etwaige bei Suchmaschinen schon verdiente Ränge für den eigenen Inhalt. Es ist also wichtig, auch die Metadaten korrekt zu extrahieren.
Wichtig für das korrekte Wiederherstellen der Linkstruktur sind vor allen Dingen
das Datum der jeweiligen Beiträge sowie der Titel in seiner Slug-Form, also wie
er im Link vorkommt. Das Datum lässt sich sehr einfach wieder mit dem HTML-Parser
aus dem Blogpost extrahieren, für den Slug nimmt man einfach den Dateinamen der
jeweiligen HTML-Datei, ohne Suffix. Daraus kann man dann wieder den für Jekyll
notwendigen Dateinamen in der Form %Y-%m-%d-slug.md
rekonstruieren. In der
Konfigurationsdatei der neuen Jekyll-Instanz muss später dann die Einstellung
für die Permalinks wieder so gewählt werden, dass die gleichen Links herauskommen
wie früher.
Kleine Korrekturen
Stört man sich daran, dass pandoc für die ersten Ebenen einer Überschrift den Setex-Stil verwendet und für die folgenden den atx-Stil, kann man einfach alles so lassen wie es aus pandoc heraus kommt. Das zu HTML gerenderte Ergebnis ist natürlich jeweils das gleiche. Will man das unbedingt einheitlich haben, hilft hier die großzügige Anwendung regulärer Ausdrücke.
Überschrift im Setex-Stil
=========================
Unterüberschrift im Setex-Stil
------------------------------
### Unter-Unterüberschrift im atx-Stil
Wie schon erwähnt hat pandoc Probleme mit Tabellen, die ich nicht automatisch habe beheben können. Aufgrund der überschaubaren Anzahl an Tabellen in meinen Blogposts habe ich die lieber manuell von HTML nach Markdown konvertiert. Behilflich sind dabei der Browser sowie ein guter Markdown-Editor wie Typora. Zuerst löscht man die kaputte Tabelle im Markdown-Code, dann kopiert man im Browser die gewünschte Tabelle und fügt sie mit Hilfe von Typora aus der Zwischenablage an die richtige Stelle ein. Für gewöhnlich formattiert der Editor dabei die Tabelle bereits korrekt.
Blog restaurieren
Hat man die Posts wieder als Markdown-Dateien vorliegen und die Metadaten korrekt
eingelesen und in Form der Dateinamen abgespeichert, kann alles zu einem
funktionierenden Blog zurückgespielt werden. Dazu muss ein neues Jekyll-Blog
angelegt werden. Ein ganz grundlegender reicht erst mal. Die Markdown-Dateien
kommen wie gewohnt nach _posts
, die restlichen Dateien aus dem Verzeichnis
mit dem Blog in HTML-Format kommen einfach ins Hauptverzeichnis - das betrifft
etwa Verzeichnisse mit Bildern. Nicht zurückkopiert werden muss CSS, das wird
vom jeweiligen Theme bereitgestellt. Je nachdem, welche Themes verwendet wurde,
ist also etwa der assets
-Ordner nicht wichtig. Nicht vergessen werden darf auch
eine etwaige .htaccess
-Datei, die mit ihrem führenden Punkt im Dateinamen
meist als versteckte Datei behandelt und vergessen wird.
Der Inhalt der _config.yaml
muss nun eben aus dem Gedächtnis
wiederhergestellt werden. Besonderes Augenmerk gilt den Einstellungen
permalink
(Dokumentation zu
Permalinks), baseurl
sowie
default
-Einstellungen für Posts (Dokumentation zu
Default-Einstellungen). Letztere regeln unter anderem, welches Layout Blog-Posts annehmen sollen,
bei denen nicht explizit eines im Front-Matter gewählt wurde.
Zu guter Letzt sollten noch etwaige zuvor auch verwendete Plugins wieder
aktiviert werden, also zum einen über das Gemfile
installiert werden und
dann auch in der _config.yaml
wieder aktiviert werden.
Ausprobieren
Damit sollte das Gröbste geschafft sein und das Blog sollte sich wieder mit Jekyll rendern lassen. Die Kontrolle mit dem Browser sollte Fehler im Design oder Markup offenbaren, etwa wenn ein Codeblock kaputt ist oder eine Tabelle falsch gebaut wurde.
Sicherheitshalber ist auch schlau, das Resultat auf 404-Fehler in den
Verlinkungen zu prüfen. Das muss glücklicherweise auch nicht von Hand gemacht
werden, dafür gibt es wget
. Ein einfacher Aufruf aller Seiten lässt sich etwa
folgendermaßen bewerkstelligen. Dazu muss zunächst mit jekyll serve
der
lokale Entwicklungsserver gestartet werden, dann kann wget darauf angesetzt
werden:
wget -o ~/404.txt -l 10 -r --spider http://localhost:4000
Man erhält eine sehr unübersichtliche Datei 404.txt
im Heimverzeichnis. Die
kann mit einem geeigneten Texteditor dann nach 404
durchsucht werden und
jeweils der Kontext nachvollzogen werden. Damit sollten dann auch tote Links
aufzufinden sein.
Backups
Der ganze Aufwand wäre ohne Backups nicht notwendig gewesen. Hat man das Blog erfolgreich wiederhergestellt, sollte danach ein Backup das erste sein, was man macht. Schlau ist, ein git-Repository anzulegen und dessen Inhalt dann auch irgendwohin zu pushen. Nachdem im Repository nichts enthalten ist, was nicht auch öffentlich im Internet lesbar wäre, kann das auch GitHub sein oder ein vergleichbares Hosting.