Artikel mit Tag serendipity
Verwandte Tags
autotitle bartleby blogs ursprung buzz commentedit dbclean listsearch projekt markupcomment nl2p photo android feedtragón ice-prefer ice-win icewm idesk-helper image-sacon izulu nachhaltigkeit pc-kombo rsspusher simdock spamblock_bayes sustaphones pubsubhubbub reallivecomment realtimecomments template_editor dsnblog rubySerendipity 2.4.0 ist draußen (das stabile Release für PHP 8.0)
Wednesday, 23. November 2022
Hier lief schon eine Weile die Beta der nun als Version 2.4.0 fertiggestellten neuen Serendipityversion, die jetzt auch hier der neuen Version weichen musste.
Hauptthema PHP 8
Was hat sich seit der Beta getan? Ein paar Beispiele:
Stephan hatte erkannt, dass das automatische Speichern des Editorinhalts kaputt war. Der Fix folgte. Matthias reparierte einen Fehler im Installer. Markus beschleunigte die Permalinkerstellung. Hanno machte die Artikelseite Spec-konformer. Mich nervte, dass beim Speichern von Templatekonfigurationen dessen Cache nicht immer neu erstellt wurde, und änderte das.
Aber der Fokus lag klar auf dem PHP-Support, wozu es auch seit Betabeginn noch einige Fixes gab. Im Kern und bei den Plugins.
Denn PHP 7.4 wird bei vielen Hostern nun abgeschaltet, deswegen auch das Release jetzt. Wir hätten ansonsten länger warten können und sicher noch mehr Bugs gefunden, nach Fehlerberichten mehr Plugins zum Laufen gebracht. Aber nun ging Warten nicht mehr und es ist auch gut, dass irgendwann der Zahn gezogen wird.
Führt euch bitte kurz vor Augen, was das für ein Projekt war und damit, was das für ein Release ist. PHP 8.0 hat vielen alten PHP-Code invalid gemacht, als altes Projekt besteht Serendipity zu 100% aus alten Code. Praktisch jede Codedatei schmiss nun Warnungen, es war anfangs erschreckend überfordernd. Im Kern wurden schließlich in einer gemeinsamen Anstrengung alle solchen Vorkommnisse angepasst, aber bei den Plugins war das illusorisch: Weder kennen wir alle Plugins, noch haben auch nur alle Spartacus-Plugins aktive Maintainer (hier wird Hilfe gebraucht!). Daher werden diese zumeist irrelevanten Warnungen nun unterdrückt (nur bei Beta und stabilen Versionen von Serendipity), was allerdings bei einem Serendipity-Teammitglied nicht zuverlässig funktioniert. Wenn es funktioniert macht es automatisch viele Plugins wieder kompatibel, ohne störende Warnmeldungen.
Allerdings hatte PHP 8.0 auch komplett inkompatible Änderungen, z.B. wenn von PHP-Kernfunktionen die Reihenfolge der Parameter geändert wurde. Das könnte gerade noch manche weniger populäre Plugins betreffen, die trotz der langen Betalaufzeit nicht getestet wurden und dann echte Fehler werfen. Da hilft nur Fehler melden, Fehler reparieren oder das Plugin zu löschen.
Ich wünsche viel Spaß mit der neuen Version und viel Erfolg beim Upgrade. Aktualisiert alle Plugins, deaktiviert das Kommentar-Seitenleistenplugin (wegen diesem Bug), habt während des Upgrades PHP 7.3 oder PHP 7.4 am Laufen. Das Upgrade sollte kein Problem sein (außer vll, wenn MySQL benutzt wird und die Beta noch nicht lief, wegen der utf8mb4-Umstellung, da braucht es dann ein Datenbankbackup), kritischer wird der dann folgende Test mit PHP 8.0. Wenn es dabei Probleme gibt hilft das Forum, aber bei inkompatiblen Plugins sollte wer kann die Ärmel hochkrempeln und sie (per Pull-Request im Github-Repo) für alle reparieren.
Tatsächlich freu ich mich riesig, dass dieses Release nun erschienen ist und auch über die drumherum gesehene Projektaktivität :) Auf dieser Grundlage wird das nächste Release (für PHP 8.1?) wohl wesentlich einfacher werden.
Das perfekte Blogsystem
Wednesday, 11. May 2022
Ich fand mich bei einem Gedanken: Wie sähe das perfekte Blogsystem aus? Mit Serendipity bin ich mit dem hier laufendem klassischen PHP-Blogsystem ziemlich vertraut, mit ursprung habe ich mich an einem auf Ruby/Sinatra-basierendem Blogsystem mit ein paar alternativen Ideen versucht. Ich kenne Grundzüge von anderen Systemen wie Jekyll, Wordpress und ProcessWire, außerdem habe ich zwei Generatoren für statische Seiten geschrieben. All diese Lösungen haben Stärken und Schwächen, aber gibt es eine perfekte Kombination für Blogs?
Statisch und dynamisch
Wenn vom Leser eine Blogseite aufgerufen wird sollte diese nicht vom System dynamisch gerendert werden. Es sollte eine statische HTML-Seite sein, die der Webserver direkt ausliefern kann. Dem nahezukommen, das ist was die Cache-Plugins bei Wordpress und Serendipity versuchen, was aber nie optimal funktionieren kann wenn das Grundsystem dynamisch ist. Der Vorteil davon ist Performance: Zum einen geht der Server viel später in die Knie wenn ein Artikel mal populär wird, zudem ist im Normalbetrieb der statische Blog immer schneller als ein dynamisch generierter.
Das Blogsystem sollte aber nicht einfach ein statische Seiten auswerfender Generator sein. Denen fehlt zu viel was einen Blog ausmacht: Kommentare, Trackbacks/Pingbacks, auch das Backend mit seinen Moderatorfunktionen, dem Artikeleditor und der Mediendatenbank. Das sind nur ein paar der wichtigsten Funktionen, auf die ein perfektes System nicht verzichten würde. Dazu kommen beispielweise Dinge wie die Unterstützung mehrerer Nutzer, Veröffentlichungsworkflows, Rechteverwaltung und sicher noch viel mehr, was ich teilweise unten beschreibe.
Das perfekte Blogsystem wäre also zweigeteilt: Im Frontend würden statische Seiten generiert, aber parallel liefe ein dynamisches Backend, das Aufgaben wie das Entgegennehmen von Kommentaren übernimmt.
Stabilität, Erweiterbarkeit und Kompatibilität
Ein perfektes System wäre stabil. Damit meine ich inbesondere den Code und seine Sprache. PHP mit seinen fortwährenden Kompatiblitätsbrüchen ist beispielsweise eine besonders instabile Grundlage, die fortlaufend Entwicklungsarbeit verlangt. Das ist absurd für die Webumgebung, ist die doch grundsätzlich stabil: Selbst vor 30 Jahren erstellte HTML-Seiten können Browser von heute noch anzeigen. Es wäre also viel gewonnen, wenn das System um den Blog zu erstellen ebenfalls einmal gebaut werden könnte und dann gleichsam in 30 Jahren noch HTML/CSS und JS ausspuckt, dann zwar auf veraltetem Stand, der aber sicher noch verstanden werden würde.
Gleichzeitig sollte das System einfach erweiterbar sein. Was derzeit gute Blogsysteme auszeichnet ist ihr Pluginsystem und die Themebarkeit, sodass Entwickler mit wenig Aufwand das System anpassen können. Neue Logik hinzufügen und mit einem Theme die HTML-Ausgabe bzw das Design anpassen zu können, das ermöglicht die Anpassung an sich ändernde Zeiten ohne dauernd der Kern überarbeiten zu müssen.
Weil Blogs im Zweifel schon existieren bräuchte es im Sinne der Stabilität Importer. Die müssten Artikel so importieren können, dass ihre URL sich nicht ändert, wobei unter der alten URL Weiterleitungen auf eine neue sein könnten und Übersichtsseiten meiner Meinung nach nicht unbedingt erhalten bleiben müssen. Auch die Kommentare würden importiert. Bei der Frage wo die Daten dann landen bin ich zwiegespalten: Was ist perfekter, ein System das viele Datenbanken unterstützt oder eines, das sich auf SQLite konzentriert?
Umfassende Kompatibilität bedeutet auch die vollständige Unterstützung von Unicode. Wobei die Realität nunmal ist, dass alte Blogs in anderen Encodings geschrieben wurden. Ein perfekter Importer würde das konvertieren können.
Viele Standardfunktionen
In die großen Blogsysteme sind tausende Arbeitsstunden geflossen, in die meisten kleinen bestimmt immer noch hunderte. Entsprechend groß ist ihr Umfang. Schauen wir uns nur mal an was diesen Artikel hier von einem rohen handgeschriebenen HTML-Artikel unterscheidet.
So ist er nicht einfach in HTML geschrieben, sondern ist der rohe Text eine Mischung aus HTML und einer individuellen Markupsprache. Mit ihr sind Links einfacher setzbar. Umbrüche brauchen dank den nl2p-Plugin keine HTML-Tags. Zum Formatieren des Textes kann ich HTML oder die Markupsprache schreiben, aber alternativ sind hier auch Buttons beim Editor die das übernehmen können. Andere Systeme (und Serendipity optional) haben eine WYSIWYG-Ansicht oder eine Autovorschau, sodass der rohe Text schon beim Schreiben umgewandelt wird. Serendipity mit meinen Einstellungen hat dafür immerhin eine verlässliche Vorschau per Buttonklick, sodass ich Layoutfehler sehen kann bevor ich Artikel veröffentliche.
Im <head>
ist in der Artikelansicht eine Anweisung für Suchmaschinen den Artikel zu indexieren, auf Übersichtsseiten dagegen wird das indexieren verboten. Es sind Tags gesetzt um den Artikel auf Twitter etc hübscher zu machen wenn er verlinkt wird, dabei wird auch ein Vorschaubild gesetzt, falls ich diesem Text noch ein Bild aus der Bibliothek hinzufüge wird dieses dafür benutzt werden. Thema Bilder: Die sind responsiv, kleine Bildschirme bekommen so kleinere und sparen Bandbreite.
Beim Schreiben kann ich komfortabel Schlagwörter und Kategorien zuweisen. Ich könnte den Artikel als Entwurf speichern oder die Veröffentlichung auf einen Moment in der Zukunft festsetzen. Er könnte dann sogar passwortgeschützt werden. Veröffentliche ich ihn, werden automatisch Trackbacks ausgesendet, was ich im Backend aber auch abstellen kann.
Gibt es nachher Kommentare kümmern sich direkt drei Plugins mit verschiedenen Ansätzen darum Spam auszusondern. Die sind so gut, dass Spam nur selten durchkommt. Wenn doch bekomme ich eine Email, wie auch bei legitimen Kommentaren. So kann ich auf die schnell reagieren. Eingehende Kommentare werden in einer Thread-Ansicht dargestellt, sodass Kommentatoren einander antworten können. Und natürlich gibt es für die Kommentare einen RSS-Feed, wie auch für die Artikel selbst und alle Kategorien.
Würde ich den Artikel dagegen in ursprung schreiben wäre der Editor komfortabel im Frontend auf der Startseite, der Kontextwechsel in ein Backend unnötig. Auch das ist eine Qualität, die ein perfektes System abdecken oder trumpfen müsste.
Und so ginge das jetzt sicher noch eine Weile weiter wenn ich alles aufzählen wollte. Man sieht schnell wie breit dieses Feld ist, wie viel ein neues System unterstützen müsste um auch nur gleichwertig zu sein.
Konkurrenz und Entwickler
Es gibt ziemlich viele Blogengines und CMS. So viele, dass es unmöglich ist einen Überblick zu behalten. Gleichzeitig gibt es mit Wordpress einen absoluten Gewinner, mit dem das halbe Internet läuft. Tatsächlich sehe ich das als Faktor: Ein perfektes System würde in einer Umgebung existieren in der es sichtbar werden kann, sodass seine Existenzberechtigung auch klar wird. So erwarte ich fast, dass ein Kommentator mir ein System benennen wird was den oben beschriebenen Ansatz teilt.
Und klar: Ein perfektes Blogsystem würde von einem aktiven Team netter und fähiger Entwickler geschrieben. Es wäre so perfekt, dass ich es nicht schreiben müsste (und auch nicht könnte). FOSS wäre es selbstverständlich auch. Sein Code wäre minimal, hätte keine instabilen Abhängigkeiten und wäre hervorragend lesbar.
Fazit
Wie seht ihr das, was habe ich vergessen? Ist was ich oben beschreibe überhaupt perfekt oder hätte sogar das beschriebene schon Macken?
Natürlich juckt es mich in den Fingern mich an einem solchen System zu versuchen. Dabei wäre das Ergebnis unzweifelhaft nicht perfekt – viele der Details wie die richtige Unterstützung der Markupsprachen und ob man das Markup oder das HTML speichert haben nicht die eine richtige Lösung – und einige der Anforderungen oben wie die Importer sind eine fast umstemmbare Mammutaufgabe, aber die Grundidee des statischen Frontends und dynamischen Backends umzusetzen hätte was. Sie hat generell derzeit etwas Aufwind, so geht Jamstack in die gleiche Richtung, ich sah in dem Kontext nur noch keine Umsetzung eines vollständigen Blogsystems.
Aber selbst wenn ich alle meine anderen Projekte zur Seite legen und mich der perfekten Blogengine widmen wollte: Scheiterte es nicht schon an der Sprachwahl? PHP wäre hier wegen seiner Instabilität offensichtlich Unsinn, wobei sein riesiger Vorteil der Hosterunterstützung damit wegfällt und schon deswegen eine Lösung ohne PHP kaum perfekt sein kann. Ich liebe Ruby, aber auch diese Sprache liefert nicht die Stabilitätsgarantien die das Projekt bräuchte. Ob Python da besser wäre erscheint nach dem Sprung auf Python 3 unwahrscheinlich. Vielleicht bräuchte es statischere Sprachen wie Rust, C oder Golang, aber komfortabel für Webanwendungen sind die nicht – und bei ihnen stolpere ich immer wieder über Projekte, die sich auf meinem System nicht kompilieren lassen. Stabilitätsgarantien in meinem Sinne gibt es da also nicht.
Was bleibt da? Etwas Lispiges wie Erlang, Common Lisp oder Racket? Etwas altgedientes wie TCL oder Perl? Eine Nischenlösung wie D?
Da erscheint direkt der erste Schritt zu schwierig.
Man nehme trotzdem den Gedanken mit, dass unsere Blogsysteme ziemlich gut, bessere Lösungen aber vorstellbar sind.
Immer sichtbare Seitenleisten im Blog via CSS-Grid
Monday, 13. December 2021
Dieser Blog mit seinem vom Theme codeschmiede abgwandelten Design verwendete ein klassisches Float-Layout:
<div id="mainpane"> <div id="serendipitySideBarContainer">...</div> <div id="content">....</div> </div>
Das #content-div war 75% lang, das #serendipitySideBarContainer-div 25% und war mit float nach rechts positioniert. Damit das ganze auf kleinen Displays lesbar blieb schaltete ein Mediaquery auf diesen die Seitenleiste aus, per display: none;
, und setzte die Breite von #content auf 100%.
Die fehlende Seitenleiste auf kleinen Bilschirmen war mir aber inzwischen nervig geworden. Sie sollte doch besser noch irgendwo sein, damit die Suche erreichbar bleibt. Gleichzeitig eine Chance, die Abfolge zu verbessern, sodass mit #content der Inhalt des Blogs oben steht. Dass das vorher nicht ging hatte ich schon damals bedauert.
Mittlerweile ist CSS weiter und man kann das besser machen. Das HTML wird via der index.tpl nun andersrum ausgegeben:
<div id="mainpane"> <div id="content">....</div> <div id="serendipitySideBarContainer">...</div> </div>
Die Anordnung erledigt ein bisschen CSS, das Grid-Layout, das in allen Browsern verstanden wird:
#mainpane { display: grid; } #content { grid-column-start: 1; } #serendipitySideBarContainer { grid-column-start: 2; }
Schon funktioniert die Standardanordnung wieder!
Die Anpassung an die kleinen Telefonbildschirme ist nun einfach. Statt die Seitenleiste zu verstecken kann sie per Grid einfach unter die Blogartikel gesetzt werden:
@media all and (max-width: 500px) { #serendipitySideBarContainer { grid-column-start: 1; grid-row-start: 2; padding-left: 1em; } }
Das ist alles hier im Blog auch schon aktiv. Wer wie ich auf ein altes Theme aufsetzt, kann hiervon hoffentlich profitieren und sich hierdran orientieren.
Bitte geb mir Bescheid, wenn hier im Blog jetzt etwas kaputt ist.
Serendipity 2.4-beta1 bringt Kompatibilität mit PHP 8.0
Monday, 13. September 2021
Serendipity hat gestern eine neue Version bekommen: Die 2.4-beta1, die jetzt auch hier in meinem Blog läuft.
Die Hauptänderung: PHP 8.0 wird sauber unterstützt
Wer hier mitgelesen hat kennt die Hauptmotivation hinter dem neuen Release: PHP 8.0 kam raus, brachte viele Änderungen und forderte damit auch viele Änderung vom alten Serendipity-Quellcode. Nicht alles davon Sisyphusarbeit, weil die Änderungen bei den Warnungen auch ein paar Bugs entlarvten, doch vieles war unnötiges Gedrängsel wo sich die Sprache künstlich dumm stellt – aber gut, jetzt ist es halt erledigt. Der PR von surrim gibt glaube ich einen besonders guten Eindruck davon, was für diese Kompatibilität erledigt werden musste.
Man beachte den PHP8-Upgrade-Guide falls mit dieser Serendipity-Version die Gelegenheit zum Upgrade auf PHP 8 genutzt wird.
Wer eigene Erweiterungen an Serendipity vorgenommen oder eigene Plugins laufen hat sei etwas beruhigt: Man sollte die zwar gut testen, aber Serendipity verschweigt jetzt auch in der Beta einfache Warnungen, was alten Plugins und Themes zugute kommt. Wohlgemerkt: Im Kern sind alle Warnungsquellen repariert worden, beim schweigsameren Warnungsverhalten geht es um Kompatibilität mit PHP 8 für alten Code der nicht vom Projekt kommt. Wobei das manche Plugins und alte Themes auf Spartacus einbezieht, denn auch dort gibt es welche ohne Maintainer.
Diese Änderung des Warnungslevels geht zusammen mit dem Beheben einiger Bugs bei der internen Fehlermeldungsfunktion, wodurch die erst jetzt so funktioniert wie sie einmal gedacht war. Das betrifft allerdings vor allem Entwickler, die Alpha-Versionen benutzen.
Dazu: UTF8MB4
Aber PHP 8.0 war tatsächlich nicht die einzige große Änderung. Bei MySQL ist Serendipity vor vielen Jahren in eine Falle gerannt: UTF8 konnte man zwar aktivieren, aber das war gar kein UTF8, sondern nur eine Teilmenge. UTF8MB4 wurde gebraucht, aber das war inkompatibel mit wichtigen Funktionen. Mittlerweile gibt es dafür Lösungen, die schon letztes Jahr in Serendipity aktiviert wurden. Sie brauchten noch Feintuning. Diese erste Beta dient auch der Frage: Funktionieren diese Änderung auch außerhalb unserer Testumgebungen?
Bei Neuinstallationen ist es einfach: Da wird einfach die neue Datenbank mit dem richtigen Zeichensatz angelegt, wenn die Datenbankengine neu genug ist. Upgrades sind das schwierigere Thema. Die Intention des Codes ist, die gleiche Prüfung zu machen und wenn dann schon UTF8 sowieso an ist, dann den Zeichensatz zu wechseln, was in Tests funktionierte. Im Idealfall ist das unsichtbar und danach können einfach mehr Zeichen gespeichert werden, wie Emojis.
Und eine Sammlung an Änderungen und Fixes
Abgesehen von diesen großen Brocken würde ich das Release als ein konservatives einschätzen. An der Oberfläche im Frontend hat sich praktisch gar nichts sichtbares, im Backend nur wenig sichtbares getan. Aber nicht nichts, und hinter den Kulissen noch etwas mehr.
Im Eintragseditor ist das Datumsfeld nun aufgeteilt, weil Browser mit einem Widget für datetime
nach jetzt zu vielen Jahren Wartezeit immer noch nicht angekommen sind. Jetzt gibt es eben ein Eingabefeld fürs Datum und eins für die Zeit, was Browser dann doch unterstützen. So sieht es bei mir im Firefox aus:
Ähnliche Verbesserungen betreffen den Umgang mit Bildern. Die responsiven Bilderfunktion sollte etwas geschickter Thumbnails wählen, sodass kleine Bilder nicht so leicht unscharf werden. Und die Mediendatenbank hat einen Bug behoben bekommen, bei der nach dem Upload von Bildern vom Editor aus ein anschließendes Ordnerwechseln zur Standardmediendatenbank führte, von wo der Upload nicht durchzuführen war. Der Bug hat mich hier persönlich im Blog lange genervt. Nette neue Bonusfunktion: Beim Einbinden neuer Bilder in Einträgen wird das Attribut loading="lazy"
gesetzt, wodurch sie nicht sofort Laden, sondern erst wenn weiteres Scrollen sie bald sichtbar machen würde. Das sollte vielen Blogs einen netten Performanceboost in der Praxis bringen, gerade ihren Startseiten.
Natürlich, wie bei jedem neuen Release, gab es Updates der gebündelten Libraries. Dort hab ich etwas Chaos aufgeräumt, das ich mit einer umständlichen composer-Einbindung angerichtet hatte. Die Updates betreffen auch den CKEditor. Bei dem wurden zum einen ein paar alte Zöpfe abgeschnitten, sodass seine Konfigurierbarkeit sehr viel beherrschbarer sein sollte. Außerdem wurde die Standardkonfiguration angepasst (nach Rückmeldung im Forum), sie sollte jetzt ein paar typische Probleme im WYSIWYG-Modus umschiffen.
Es gab relativ tiefgreifende Fixes für die Multisprachunterstützung, die der Performance dienen sollten und auch Fehler in dieser Funktion beheben (von stephanbrunker). Die Tokengenerierung für die Aktionen bei den Emails ist jetzt sicherer (von hannob). Der Installer prüft jetzt, ob das benötigte XML-Modul vorhanden ist (von UweKrause). Und die Liste ginge noch deutlich weiter, wenn ich jetzt weiter durch die Commits gehen würde.
Ich hoffe, die neue Version gefällt den Serendipity-Bloggern. Mir liegt diese Version sehr am Herzen – zum einen, weil sie angesichts des sich langsam nähernden Endes von PHP 7 (7.4 bekommt reguläre Updates bis November 2021, Sicherheitsupdates bis November 2022) notwendig war, aber auch weil die Arbeit am Code meiner Wahrnehmung nach diesem sehr geholfen hat. Es tat gut, das lange schwelende MySQL-Zeichensatzproblem anzugehen, und auch einige alte Zöpfe im Code abzuschneiden. Und gefühlt war ich seit 2.0 mit der Smartymigration des Backends nicht mehr so involviert, davor sowieso nicht.
Bis alle Plugins mit PHP 8.0 kompatibel sind steht noch etwas Arbeit an, aber damit das in einem guten Tempo im Ganzen gelingt braucht es Hilfe, kurz: Mehr aktive Entwicklung. Serendipity ist einfach insgesamt ein ziemlich großes System. Auch bei den alten Themes könnte man viel machen und mit PHP 8.1 steht im Kern dann die nächste Migration an. Das schafft Modernisierungsdruck, aber auch -potential. Für neue Entwickler wäre Serendipity gerade und in naher Zukunft ein ziemlich spannendes Projekt, da kann ich nur einladen.
YouTube-Videos einbinden, ohne dass die Seite lahm wird (+Serendipity-Plugin)
Friday, 4. June 2021
Wenn mehrere YouTube-Videos auf einer Seite landen wird diese ziemlich schwer. Zumindest, wenn man den Einbindungscode nutzt den YouTube selbst vorschlägt. Da das hier im Blog schnell mal passiert, so wie jetzt, da mehrere Artikel mit Videos auf der Hauptseite sind, habe ich mich nach Alternativen umgesehen.
Normalerweise sieht das Iframe so aus:
<iframe width="560" height="315" src="https://www.youtube.com/embed/XhG-4zdVx0I" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
Auf den ersten Blick harmlos. Das Problem ist all das Javascript, das in diesem Iframe dann bezogen wird. Was sofort geschieht, da nach dem Laden die Iframe-Zielseite sofort den Player initialisiert.
Auf dev.to schlug Arthur vor, stattdessen ein alternatives Iframe zu nutzen:
<iframe width="560" height="315" src="https://www.youtube.com/embed/XhG-4zdVx0I" srcdoc="<style>*{padding:0;margin:0;overflow:hidden}html,body{height:100%}img,span{position:absolute;width:100%;top:0;bottom:0;margin:auto}span{height:1.5em;text-align:center;font:48px/1.5 sans-serif;color:white;text-shadow:0 0 0.5em black}</style><a href=https://www.youtube.com/embed/XhG-4zdVx0I ?autoplay=1><img src=https://img.youtube.com/vi/XhG-4zdVx0I/hqdefault.jpg><span>▶</span></a>" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen ></iframe>
Das ist schon von mir leicht verändert und der Artikel beschreibt verschiedene Zwischenschritte auf dem Weg zu dieser Lösung. Schaut euch das ruhig im Originalartikel an.
Aber die Kernidee ist, dass in dem Iframe der Videoplayer erst nach einem Klick auf das Vorschaubild geladen werden wird. Statt einem halben MB an Code ein kleines Bildchen zu laden geht beim ersten Laden der Seite wesentlich schneller. Und da das Video nach einem Klick wie zuvor sofort startet, dank dem autoplay=1
, wird dem Seitenbesucher der Unterschied kaum auffallen. Denn das ist das Ergebnis:
Einfluss auf die Seitenperformance
Ich stolperte über diese Baustelle, als ich die neue Version Googles Pagespeed testete. Beim Prüfen dieses Blogs hier erschrak ich über das miserable Ergebnis:
Gut, die Mobilvariante des Tools ist häufig sehr hart, aber so schlecht hatte ich meinen Blog nicht gesehen. Ein Blick auf die Problemliste zeigte dann deutlich, dass Youtube-Videos die Ursache sind:
Was schlicht daran liegt, dass derzeit mehrere Artikel mit Videos von Youtube hier auf der Startseite sind.
So sieht das Ergebnis jetzt aus, da alle diese Videos mit den neuen Iframes ersetzt sind:
Viel besser! Sogar für Telefone wird die Geschwindigkeit der Seite als hervorragend bewertet. Wie es bei einem einfachen Blog ja auch sein soll.
Serendipity-Plugin
Ich wollte die regulären Iframes nicht per Hand ersetzen. Und generell wollte ich den originalen Code beibehalten. Ich gehe davon aus, dass die Kompatibilität mit dem derzeitigen Einbindungscode fast für ewig erhalten bleiben wird. Während bei dem angepassten Iframe Annahmen drin sind die sich ändern könnten, vor allem der Pfad zum Vorschaubild.
Deswegen habe ich ein Plugin geschrieben, das die normalen Iframes umwandelt. Der Blogger schreibt also ganz normal seinen Artikel, bezieht den normalen Einbettungscode von Youtube, und das Plugin serendipity_event_lazyoutube wandelt dann automatisch diesen Code von Youtubes lahmen Standard-Iframe zu der hier gezeigten schnellen Alternative um, die den Videoplayer erst nach einem Klick auf das Vorschaubild lädt.
Außerdem kann man damit, angelehnt an oEmbeds, den Einbettungscode vom Plugin erstellen lassen – falls einem das Bewahren des Original-Iframes im Artikelquellcode nicht so wichtig ist. Statt dafür nur einen Link zu setzen geht das mit [Youtube-Link], also [https://www.youtube.com/watch?v=XhG-4zdVx0I] für das Video von oben.
Nur damit der zu erstellende Code einfacher zu erzeugen ist habe ich oben auch das Iframe angepasst. Im Original ist da noch an zwei Stellen der Titel des Videos drin. Aber um den abzufragen müssen wir mit der Youtube-API arbeiten oder den Artikelschreiber das eintragen lassen, beides wollte ich vermeiden.
Das Plugin ist ganz frisch und es fehlt mindestens noch der Versuch, gewählte Anfangszeiten zu unterstützen. Deshalb liegt es bisher nur in einem eigenen Github-Repo. Hier im Blog ist es aber schon aktiv und Tester wären mir hochwillkommen.
Die Entwicklung von Serendipity im Zeitraffer und Optimierungsversuche mit Gource
Wednesday, 2. June 2021
Drüben bei gnulinux.ch bin ich über Gource gestolpert. Gource braucht man nur ein Git-Repository zu geben, damit es aus der der dort gespeicherten Aufzeichung ein Video mit einer Visualisierung der Entwicklung erstellt. Tatsächlich kannte ich die Visualisierung aus einem Youtubevideo, aber ich hatte keine Ahnung, dass sie mit frei verfügbarer Linxusoftware erstellt wurde. Und mir gefiel die Konfiguration der Darstellung, die im Artikel vorgeschlagen wird.
Das ist die nicht ganz komplette Entwicklung von Serendipity:
Ich finde es toll zu sehen, wie viele Entwickler da am Wirken waren und wie Garvin von der Software ins Zentrum gestellt wird. Und natürlich bereitet es ganz besonders Freude, wenn der eigene Name auftaucht und den Dateibaum verändern beginnt.
So ein Video zu erstellen ist einfach. Gource war auch bei Void Linux in den Quellen. Einmal installiert, muss nur das Git-Verzeichnis erstellt, darein gewechselt, Gource gestartet und die Ausgabe an FFmpeg übergeben werden:
git clone git@github.com:s9y/Serendipity.git Serendipity.git cd Serendipity.git gource -1280x720 --date-format %Y-%m-%d --seconds-per-day 0.025 --auto-skip-seconds 0.05 --no-time-travel --stop-at-end --highlight-users --max-user-speed 125 -r 30 -o - | ffmpeg -y -r 30 -f image2pipe -vcodec ppm -i - -vcodec libx264 -preset medium -pix_fmt yuv420p -crf 18 gource.mp4
Tatsächlich habe ich aber viel Zeit in den Versuch versenkt, das zu optimieren. Ich wollte FFmpeg statt .mp4 erst .ogv und dann .webm mit VP9 erstellen lassen. Denn das mit H.264 gebaute und oben eingebundene .mp4 ist immerhin 77 MB groß.
Übrigens das erste mal seit langer Zeit, dass ich mir einen stärkeren Prozessor gewünscht habe. Videos zu enkodieren ist einfach heftig. Aber auch beeindruckend, dass die 4GB große .ppm problemlos auf unter 100MB gebracht werden kann.
Beim Versuch, eine kleinere Datei als die obige für diesen Artikel zu erhalten, orientierte ich mich an der Dokumentation von FFmpeg und den Hinweisen von Google. Aber die Videos waren entweder größer oder mit mehr sichtbaren Kompressionsartefakten. Und das selbst bei der Two-Pass-Enkodierung, die ich so versuchte:
gource -1280x720 --date-format %Y-%m-%d --seconds-per-day 0.025 --auto-skip-seconds 0.05 --no-time-travel --stop-at-end --highlight-users --max-user-speed 125 -r 30 -o gource.ppm ffmpeg -y -r 60 -f image2pipe -vcodec ppm -i gource.ppm -c:v libvpx-vp9 -b:v 0 -crf 37 -pass 1 -row-mt 1 -an gourceq37.webm ffmpeg -y -r 60 -f image2pipe -vcodec ppm -i gource.ppm -c:v libvpx-vp9 -b:v 0 -crf 37 -pass 2 -row-mt 1 -an gourceq37.webm
Das produzierte relativ große Dateien (hier 130MB), während die Google-Vorgaben sehr kleine (22MB), aber deutlich sichtbar komprimierte Videos erstellten:
ffmpeg -y -r 60 -f image2pipe -vcodec ppm -i gource.ppm -vf scale=1280x720 -b:v 1800k -minrate 900k -maxrate 2610k -tile-columns 2 -g 240 -threads 4 -quality good -crf 32 -c:v libvpx-vp9 -an -pass 2 -speed 4-y gource_google.webm ffmpeg -y -r 60 -f image2pipe -vcodec ppm -i gource.ppm -vf scale=1280x720 -b:v 1800k -minrate 900k -maxrate 2610k -tile-columns 2 -g 240 -threads 4 -quality good -crf 32 -c:v libvpx-vp9 -an -pass 2 -speed 4 gource_google.webm
Kein guter Startpunkt.
Die Single-Pass-Kodierung ist laut der Dokumentation nicht empfohlen, und tatsächlich lässt sich mit ihr zwar etwa die gleiche Größe erreichen:
gource -1280x720 --date-format %Y-%m-%d --seconds-per-day 0.025 --auto-skip-seconds 0.05 --no-time-travel --stop-at-end --highlight-users --max-user-speed 125 -r 30 -o - | ffmpeg -y -r 30 -f image2pipe -vcodec ppm -i - -vcodec libvpx-vp9 -preset medium -pix_fmt yuv420p -crf 30 -row-mt 1 gource.webm
Aber das Video sieht ein bisschen schlechter aus. Und mit schlechterer Qualitätsstufe (hier 35) leidet die Darstellung dann deutlich:
Wenn ich mir die Dateigrößen und die Qualität von ja oft deutlich längeren Youtube-Videos anschaue glaube ich, dass das besser gehen müsste.
Kommt VP9 generell schlecht mit dem Blur zurecht? Oder ist der Kodierer in FFmpeg subobtimal? Gibt es doch einen Weg, die Komprimierung des .mp4-Video bei visuell gleicher Qualität zu schlagen?
Trackbacks für Serendipity mit PHP 8
Wednesday, 26. May 2021
Kleine Wasserstandsmeldung aus gegebenem Anlass.
Die Arbeit, um Serendipity mit PHP 8 kompatibel zu machen, ist noch nicht fertig. Aber sie ist weit vorangeschritten. Ich habe mittlerweile alle Backend- und Frontendfunktionen getestet und fast alle mit Standardtheme und vorinstallierten Plugins zum Laufen gebracht.
Ein wichtiger noch fehlender Baustein waren die Trackbacks. Die Kommentare bei Dirks Bloggeburtstag waren sicher der Anlass sie jetzt zu testen, auch wenn mir das gestern Abend gar nicht bewusst war. Es war eine Erinnerung, deretwegen ich den Test vorzog, an die ich in dem Moment nicht mehr direkt dachte. Ihr kennt das bestimmt.
Tatsächlich waren die Trackbacks kaputt. Die Korrekturen sind größtenteils Kleinigkeiten. Auf einem Server, der Warnungen verschluckt, würde wahrscheinlich auch jetzt schon alles laufen. Aber die Warnungen zu reparieren kann der Codequalität nur dienen und Warnungen werden eben nicht immer ausgeblendet, was dann Funktionen kaputtmachen kann.
Bei den Trackbacks speziell ist, dass der Browser ja gar keine Daten sendet. Das machen die Server unter sich aus, was im Zweifel schwer zu beobachten ist. Wir haben Logs, aber die zeigen bei PHP-Fehlern nur wo der Empfang abbricht. Um das richtig zu debuggen sendete ich den Trackback stattdessen mit curl:
curl -X POST -d 'type=trackback&entry_id=16&url=https://example.com/s9y_dev/index.php?/archives/19-trackbacktest-2.html&title=trackbacktest 2&blog_name=John Doe personal blog&excerpt=link2' https://example.com/s9y_dev/comment.php
So waren die Fehler schnell sichtbar und relativ einfach zu reparieren.
Es fehlt, das gleiche mit Pingbacks (ggf. via Wordpress) zu testen. Ansonsten müssten noch die restlichen Plugins und Themes durchgegangen werden. Ich habe mir vorgenommen, die mitgelieferten Plugins, die populären in Spartacus und die modernen Themes tatsächlich noch selbst anzusehen. Damit müsste eine PHP-8-kompatible Beta dann in Reichweite sein, wobei gerade die Plugins selbst bei Beschränkung auf die populäreren noch ein ziemlicher Brocken sein könnten.
Ein Printstylesheet für den Blog
Tuesday, 4. May 2021
Dieser Blog hat neues CSS für die Druckdarstellung bekommen. Der Artikel zur Witcherserie als Beispiel sieht im Web so aus:
Ausgedruckt – bzw mittels der Druckfunktion zum PDF umgewandelt – und dabei auf ein Blatt herunterskaliert kommt das dabei raus:
Erreicht wird die angepasste Darstellung durch dieses CSS, das ich einfach der regulären CSS-Datei hinzugefügt habe:
@media print { #serendipitySideBarContainer { display: none; } #content { width: 100%; } #serendipityCommentFormC { display: none; } .shariff { display: none; } .dsgvo_gdpr_footer { display: none; } #siteNav { display: none; } body { font-family: Iowan Old Style, Apple Garamond, Baskerville, Droid Serif, Times, Source Serif Pro, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Times New Roman, serif; border: none; } html { background-color: white; } .serendipity_entry_body { column-width: 17em; column-gap: 3em; } .serendipity_entry_body a[href*='//']::after, serendipity_commentBody a[href*='//']::after { content: " (" attr(href) ")"; } a { color: black !important; text-decoration: underline !important; } #serendipity_banner { display: none; } #mainpane::before { content: "onli-blogging"; display: block; } .serendipity_title a { text-decoration: none !important; } .serendipity_title, .serendipity_date { break-after: avoid; break-after: avoid-page; } br + .serendipity_commentsTitle, .nocomments { display: none; } .serendipity_entryFooter, .serendipity_comment footer { display: none; } }
Wer das in seinen eigenen Serendipity-Blog übernehmen will müsste manche der Klassen wahrscheinlich anpassen, denn mein Design basiert mit codeschmiede auf älteren Code, den ich selbst nach HTML5 umgewandelt habe. Deswegen gibt es ein paar Unterschiede bei den Klassennamen zu 2k11 und anderen modernen Themes. Aber die Grundideen sind:
Ausgeblendete Seitenleiste und andere Elemente
Wer einen Artikel ausdrucken will kann auf dem Papier mit den Links in der Seitenleiste nichts anfangen, daher konnte die weg. Dazu habe ich den Header, der bei Einzelartikeln nur den Artikeltitel doppelte, den Footer des Blogs, die Artikelunterzeile und das Kommentarformular ausgeblendet.
Links ohne Farbe
Links sind hier im Blog normalerweise farblich markiert. In der Druckversion sind sie stattdessen schwarz, aber unterstrichen, und ihnen folgt das Linkziel als Text.
Serif-Schriftart
Für das richtige Papierdesign. Übernommen vom systemfontstack – es war gar nicht so einfach, passende Systemschriftarten für Serif- statt Sans-Serif-Schriftarten zu finden – aber leicht angepasst, denn Times New Roman war mir zu prominent platziert.
Spaltenansicht
Der Artikel wird wenn Platz ist in Spalten aufgeteilt. Auf dem Bild oben sind mehr Spalten als normal, da die Skalierung auf 60% reduziert war. Normalerweise sind es bei Din-A4 zwei Spalten im Querformat und nur eine, wie am Monitor, im Hochformat. Die Idee habe ich von sitepoint übernommen.
Titel hinzugefügt
Damit der Blogname trotz ausgeblendetem Header wenigstens irgendwo auftaucht wird er als Pseudoelement vor den Artikel gepackt.
Ganz bewusst nicht ausgeblendet sind die Kommentare, denn die könnten ja zum Artikel beitragen bzw das sein, was jemand ausdrucken wollte. Und auch das Videoelement ist absichtlich noch da, denn ohne es würde dieser Abschnitt des Artikel fehlerhaft wirken. Man kann es zwar nicht anklicken, aber sieht so zumindest dass es da war.
Insgesamt ging es also darum die Artikel auf dem Papier lesbarer zu machen, interaktive Elemente möglichst zu entfernen und auch die angezeigten Farben auf ein Minimum zu reduzieren. Damit wenn schon etwas ausgedruckt wird, es möglichst sparsam geschieht und das Ergebnis so lesbar wie möglich ist.
Reviews im Blog per Plugin mit Schema.org auszeichnen
Thursday, 22. April 2021
Das im letzten Jahr hier vorgestellte Schema.org-Plugin setzt automatisch Markup, um Blogartikel als Blogartikel zu beschreiben. Das ist zwar nett, aber der Nutzen ist beschränkt – so hat Google diese Auszeichnung bisher nicht aufgegriffen.
Was mir aber im pc-kombo-Blog wahrscheinlich einige Besucher beschert hat war das Markup für Reviews. Das ist eigentlich logisch: Was soll es auch viel helfen wenn die Suchmaschine sich sicherer ist, dass die Blogartikel hier Blogartikel sind. Wovon sie handeln und was sie aussagen, das sind die verwertbaren Informationen um den Artikel im richtigen Moment besser dargestellt anzuzeigen.
Ich habe damals mit recht simplem JSON-Markup gearbeitet und das manuell in die Artikel eingebaut. Jetzt habe ich das Schema.org-Plugin erweitert, um das gleiche Markup in Serendipity-Blogs halbautomatisch zu erstellen. Zum Beispiel sieht der vom Plugin generierte JSON-Code in meinem Artikel zum Sharkoon-DAC so aus:
{"@context": "http://schema.org", "@type": "Product", "name": "Sharkoon DAC Pro S V2", "image": , "description": "", "brand": { "@type": "Thing", "name": "Sharkoon" }, "review": { "@type": "Review", "author": { "@type": "Person", "name": "onli" }, "datePublished": "2021-04-02T06:34:00+0000", "reviewRating": { "@type": "Rating", "ratingValue": "4.0" } } }
Der Code ist teilweise automatisch generiert, der Rest muss manuell über die freien Felder des Entrypropertyplugins eingegeben werden.
Dafür erstellt man vier freie Felder in dessen Pluginkonfiguration:
schemaType, schemaName, schemaBrandName, schemaRating
Die ersten drei beschreiben das Thema des Artikels. Hier war schemaType
ein Product
, schemaName
der Name des DAC, und schemaBrandName
der Name des Herstellers. Wäre ein Film das Thema gewesen hätte ich Product
mit Movie
ausgewechselt – Googles Dokumentation beschreibt das als gültigen Wert, andererseits hat der Markuptester bei mir mit vielen der dort angegebenen Werten nichts anfangen können, auch wenn er nicht meckerte.
Das vierte Feld schemaRating
ist schließlich die Bewertung. Da ich keine Skala angeben möchte geht die von 0 bis 5. Eine numerische Bewertung angeben zu müssen ist manchmal blöd, da meine Artikel normalerweise keine finale Bewertung abgeben. Aber für das Snippet wird sie verständlicherweise gebraucht.
Der Schema.org-Reviewcode wird nur ausgegeben, wenn alle vier Felder gefüllt sind. Er ist ein Zusatz zum regulären Blogartikelbeschreibungscode, den das Plugin bisher ausgegeben hat. Der bleibt unverändert erhalten.
Das Plugin ist nicht auf Spartacus, aber kann von seinem Github-Repo heruntergeladen werden. In dessen Readme ist auch die Konfiguration nochmal erklärt.
Zur Zukunft von Serendipity mit PHP 8.0
Tuesday, 16. March 2021
Uberspace hat PHP 8.0 aktivierbar gemacht. Da dort meine Entwicklungsinstallation lebt habe ich mir angeschaut, was da genau auf die Blogsoftware zukommt. PHP 8.0 ist zwar schon draußen, PHP 7.4 wird aber noch eine ganze Weile unterstützt, es eilt also nicht. Andererseits gibt es viel zu tun. Zumindest ist das meine Einschätzung.
Die inkompatiblen Änderungen von PHP 8.0
PHP 8.0 ist inkompatibel mit einigem Code, der in den letzten 20 Jahren bei Serendipity zusammengekommen ist. Vor allem diese Änderungen (von hier) machen der Software zu schaffen:
A number of notices have been converted into warnings:
Attempting to read an undefined variable.
…
Attempting to read an undefined array key.
…
Serendipity macht beides sehr, sehr oft. Und noch öfter, wenn man die Smarty-Templates hinzurechnet, die nun ebenfalls bei Zugriff auf undeklarierte Variablen solche Warnungen werfen. Werden Warnungen geworfen ist das im Zweifel im Blog sichtbar, kann generiertes HTML und CSS kaputtgehen, bei Entwicklungsversionen bricht die Ausführung ab.
Der Code schaut zum Beispiel oft, ob in $serendipity
ein gesuchter Key gesetzt ist, oder switcht sogar über diesen Wert:
switch($serendipity['POST']['adminAction']) { … }
Wenn $serendipity['POST']['adminAction']
nie gesetzt wurde, wirft das jetzt eine Warnung. Vorher war das Ergebnis einer solchen Abfrage einfach null und machte entsprechend nichts. Wir können das reparieren, mit isset
oder dem ??
-Operator:
switch($serendipity['POST']['adminAction'] ?? '') { … }
Aber will man die Warnungen nicht verstecken muss das eben durch den gesamten Code hindurch gemacht werden.
Der aktuelle Stand
Warnungen zu unterdrücken halte ich wirklich für keine gute Option. Tatsächlich wurden durch dieses neue Verhalten jetzt schon einige Bugs sichtbar, als ich die Warnungen nachverfolgend durch den Code ging. Es ist zwar unangenehm bei altem Code wie diesem – tatsächlich ist Serendipity kein toller Kandidat für die Portierung auf PHP 8 – aber die Änderungen sind grundsätzlich gut. Serendipity sollte da mitgehen.
Ich habe einen ersten Pull-Request vorbereitet. Den will ich so nicht mergen, er ist zu groß geworden, aber ich werde ihn aufsplitten (der erste Folge-PR ist hier). Mit diesen Codeänderungen kann der Blog mit Standardplugins schon wieder fehlerlos dargestellt werden, auch alle Hauptseiten im Backend werfen keine Fehler mehr. Mit etwas mehr Arbeit wird wahrscheinlich bald der Rest des Kerns wieder gehen.
Anstehende Entwicklungen und Entscheidungen
Es würde wohl in ein Serendipity 3.0 münden. Die von PHP 8.0 diktierten Änderungen werden s9y teilweise zu inkompatiblen Änderungen zwingen. Zum Beispiel bei der Redeklarierung von Konstanten, was nun ebenfalls einen Fehler wirft, aber für das Fallback bei den Sprachdateien genutzt wird.
Aber ich könnte mich täuschen. Vielleicht lassen sich solche Änderungen durch Ideen anderer Entwickler vermeiden. Vielleicht sollte man temporär an dieser Stelle doch die Fehlermeldungen unterdrücken, wo wir da doch wirklich wissen, dass davon kein Bug versteckt wird. s9y versucht ja auch sonst immer, inkompatible Änderungen zu vermeiden. Ich hoffe, die jeweilige Änderung in den PRs mit den anderen zu besprechen.
Dann bleiben aber immer noch die alten Themes und Plugins.
Bei den Themes ist es möglich, dass die genutzte Template-Engine Smarty eine neue Version herausbringt, die besser auf PHP 8.0 ausgerichtet ist und die Warnungen bei undeklarierten Variablen vermeidet. Wenn nicht, werde ich die empfohlenen Designs reparieren (und natürlich auch dieses hier im Blog genutzte), wäre dann aber sehr dafür die alten Themes ohne eigenen Maintainer aufzugeben.
Bei den Plugins ist die Situation ähnlich. Auch die werden wahrscheinlich fast alle repariert werden müssen. Die wichtigsten werde ich bei meiner Arbeit an Serendipity selbst mitreparieren, wenn mir niemand zuvorkommt. Man könnte es beim Rest mit automatisierten Tools wie rector versuchen. Und nachbessern falls Nutzer Probleme melden. Dabei sollten wir aber die Plugins markieren, die bereits repariert sind, damit ein etwaig unbedarfter Nutzer nicht unwissentlich ein eventuell inkompatibles Plugin installiert.
Wie gesagt, das ist nur meine unabgesprochene Einschätzung. Durchaus möglich, dass ich gute Alternativen übersehe und mein Ansatz arbeitsintensiver ist als nötig. Aber so oder so schadet es nicht, wieder durch den Code zu gehen und den von Hand geradezubiegen. Das werde ich in nächster Zeit immer mal wieder machen, dabei auf Github PRs vorbereiten und einsenden.
Das positivste: Der für PHP 8.0 angepasste Code lief problemlos mit PHP 7.4, sicher auch mit 7.3. Die Änderungen dürften also nicht zu einem harten Bruch führen. Wenn das Projekt den hier beschriebenen Weg weitergeht sollte die nächste Serendipity-Version mit allen aktuellen PHP-Versionen zugleich funktionieren.
Serendipitys Social-Buttons mit Zähler aktualisiert
Thursday, 4. February 2021
Hier im Blog läuft das Plugin serendipity_event_social/Share Buttons, das unter den Einträgen per shariff umgesetzte datenschutzfreundliche 2-Klick-Buttons anzeigt. Mit denen kann man den Blogartikel in sozialen Netzwerken wie Twitter und Facebook teilen, aber ohne dass allein durch das Laden dieser Seite deren Code geladen wird. Das verhindert Überwachung.
Die Buttons funktionierten weiterhin, aber der Zähler war hier im Blog kaputt. Shariff hat auch ein Backend, das ich für alle Pluginnutzer auf meinem uberspace laufen lasse. Das Backend holt die Zahlen. Aber hier im Blog hatte ich es auf die falsche URL gestellt, das /
am Ende fehlte. Das ist nun korrigiert.
Die Gelegenheit habe ich genutzt, um auch das Backend zu aktualisieren - es lief noch eine ältere Version. Wohl dadurch war die Facebook-API deaktiviert worden, sie ist jetzt wieder an. Das Backend-Update war wohl generell notwendig. Wenn also auch bei euch im Blog der Zähler nicht funktionierte wäre nun ein neuer Test eine gute Idee.
Beim Serendipity-Plugin musste nichts geändert werden, nur die richtige URL habe ich jetzt dokumentiert.
Ich war mir sicher, über das Plugin hier im Blog bereits geschrieben zu haben. Aber ich finde keinen Artikel dazu, nur dass ich vor 9 Jahren schonmal mit shariff experimentiert hatte. Deshalb sei hier noch erwähnt, dass das Plugin mehr macht als nur die Buttons anzuzeigen: Es baut auch das HTML, um das erste genutzte Bild oder eine gesetzte Alternative bei diesen Kästen einzusetzen, die Seiten wie Twitter bauen wenn bei ihnen ein Artikel verlinkt wird. Was ich für ein nettes Feature halte.
Und damit wäre die Vorstellung nachgeholt.
Zusätzliche Serendipity-Plugins: Entrystats, Simplepodcast, Simplestaticpage und Schema.org
Monday, 31. August 2020
Diese vier Plugins sind in unterschiedlichen Entwicklungsstadien. Allen vier gemein ist, dass ich beim Aufräumen über sie gestolpert bin und sie nicht in Spartacus sind. Ich habe sie jetzt auf Github hochgeladen. Es folgt eine Kurzvorstellung und die Frage: Was soll mit ihnen geschehen?
Entrystats
Unfertig. Es sollte eine Alternative zum Statistik-Plugin werden, das nur Artikelaufrufe zählt, dafür nur eine Zeile pro Artikel anlegt und daher nicht die Datenbank aufbläht. Ich kam wohl nicht weit, das SQL wird nur mit MySQL funktionieren. Statistiken führe ich hier nicht (mehr), aber den Ansatz eines solchen simplen Zählers finde ich immer noch interessant.
Besteht Interesse hierdran? Oder haben wir genug bessere Statistiklösungen, bzw benutzt der Großteil wie ich gar keine?
Github: serendipity_event_entrystats
Simplepodcast
Das Podcastplugin war sogar schon auf Github. Ich entwickelte es vor etwa anderthalb Jahren während der Serendipity-Entwicklungswoche, weil ein einfacher zu bedienendes Podcastplugin mit Podlove-Player gewünscht wurde. Das Plugin liefert das, samt angepasstem RSS-Feed, aber ich dachte damals es fehlt der Feinschliff um es in Spartacus zu packen.
Hier bräuchte es einen Serendipity-Blogger mit Podcasterfahrung, der das Plugin nutzt und mitentscheidet ob noch was fehlt und wenn ja, welche Funktionen gebraucht werden. Oder sie direkt einbaut natürlich.
Github: simplepodcast
Simplestaticpage
Das Staticpage-Plugin ist vom Code her schwierig zu warten und auch die Benutzung ist nicht ideal. Ich weiß, dass ich mich zweimal schon an einer Lösung probiert habe: Einmal wollte ich ein neues Plugin schreiben, das die alten Datenbankeinträge übernimmt; Ein andermal eine eigenständige einfache Alternative bauen. Ich verlor wohl das Interesse und weckte den Kommentaren zufolge auch keines (an anderer Stelle möglicherweise schon).
Das ist Kernfunktionalität, gleichzeitig ist unklar ob die Blogsoftware Serendipity so ein CMS-Feature braucht. Um das in Richtung Es braucht solch ein Plugin aufzulösen bräuchte es einen Entwickler, der mit einem solchen Plugin Seiten in seinem Blog einrichten will und das Ganze mit einem Auge auf Benutzerfreundlichkeit umsetzt.
Github: serendipity_event_simple_staticpage
Schema.org
Das Schema.org-Plugin ist relativ neu und auch hier im Blog in Benutzung. Es funktioniert meines Wissens einwandfrei. So hat es in den Eintrag der Pluginvorstellung diesen Code eingebaut:
<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "BlogPosting", "mainEntityOfPage": { "@type": "WebPage", "@id": "https://www.onli-blogging.de/1937/Schema.org-Plugin-fuer-Serendipity.html" }, "headline": "Schema.org-Plugin für Serendipity", "image": "/uploads/Screenshot_2020-06-05_Rich_Results_Test_-_Google_Search_Console.serendipityThumb.png", "datePublished": "2020-06-05T10:02:00+0000", "dateModified": "2020-06-08T09:51:09+0000", "author": { "@type": "Person", "name": "onli" }, "publisher": { "@type": "Organization", "name": "onli", "logo": { "@type": "ImageObject", "width": 100, "height": 100, "url": "https://www.onli-blogging.de/favicon_100.png" } } } </script>
Allerdings greift Google dieses Markup nicht auf. Zumindest den Webmastertools zufolge hat es keinen Effekt. Jetzt ist die Frage: Geben wir also dieses Plugin auf, oder fügen wir es trotzdem Spartacus hinzu?
Github: serendipity_event_schema
Sollte jemand Lust haben eines der Plugins weiterzuentwickeln: Sehr gerne, deswegen sind sie auf Github. Sollte starkes Interesse an einem der Plugins bestehen könnte auch ich nochmal Zeit hineinstecken, wobei es meist mehr bringt wenn es jemand entwickelt der die Funktionen auch nutzen will. Beim Schema.org-Plugin will ich das, da weiß ich nur nicht ob es nach Spartacus soll – seht ihr darin einen Nutzen?
Schema.org-Plugin für Serendipity
Friday, 5. June 2020
Schema.org ist ein Format, mit dem man maschinenverständlich Inhalte auf Webseiten beschreiben kann. Beispielsweise nutze ich es auf pc-kombo, um bei den Komponentenseiten anzugeben über welche Komponente sie genau reden und um Reviews zu markieren. Google unterstützt schema.org stark und greift einige der Beschreibungen in den Suchergebnislisten auf, es gibt dafür eine Liste. Neben so praktischen Dingen wie Produktdaten und Reviews gibt es auch schlicht Artikel. Und ein Untertyp sind Blogartikel.
Damit Blogeinträge zu erweitern ist die vernünftige Alternative zu Googles AMP-Wahnsinn. Möglicherweise – zu der Einschränkung unten mehr – kann Google und auch jede andere Suchmaschine so Artikel besser darstellen, z.B. mit Artikelbild in ein oberes Artikelkarussell einbauen.
Thomas hat in seiner Linkliste einen Artikel von Lukas Murdock verlinkt, der zeigte wie Lukas Schema-Markup in seinem Blog hinzugefügt hat. Mir wurde klar: Das kann auch Serendipity automatisieren.
Bisher habe ich (in ursprung) schema.org direkt ins HTML gepackt. Das ist einer der drei möglichen Wege. Es ist dann also das Theme, das entsprechendes HTML generieren muss, das wäre schwierig gewesen. Aber das alternative JSON-LD kann in einem Rutsch bei der Artikelgenerierung erstellt werden. Diesen Vorteil hatte ich bisher nicht erkannt.
Ich habe das in ein Plugin gepackt:
serendipity_event_schema_0.1.tar.gz
Bei mir funktioniert es. Funktionieren bedeutet: Es produziert valides Schema-Markup, das den Artikel akkurat beschreibt. Z.B. für diesen Artikel:
<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "BlogPosting", "mainEntityOfPage": { "@type": "WebPage", "@id": "https://www.onli-blogging.de/1937/Schema.org-Plugin-fuer-Serendipity.html" }, "headline": "Schema.org-Plugin für Serendipity", "image": "/uploads/Screenshot_2020-06-05_Rich_Results_Test_-_Google_Search_Console.serendipityThumb.png", "datePublished": "2020-06-05T10:02:00+0000", "dateModified": "2020-06-05T10:27:00+0000", "author": { "@type": "Person", "name": "onli" }, "publisher": { "@type": "Organization", "name": "onli-blogging", "logo": { "@type": "ImageObject", "width": 100, "height": 100, "url": "https://www.onli-blogging.de/favicon_100.png" } } } </script>
Aber es gibt zwei Einschränkungen:
- Google gibt vor, dass ein Publisher angegeben werden muss, zusätzlich zum Autor, was bei privaten Blog natürlich Unsinn ist. Das Plugin kann diesen Abschnitt daher auch nicht komplett vorausfüllen, wir haben die notwendigen Daten nicht. Es schlägt vor, eine nach dem Autor benannte Organisation anzugeben, auch der Blogname würde passen. In der Pluginkonfiguration muss dieser Code angepasst werden, insbesondere der Link zum notwendigen Logo.
- Das Markup sollte mit dem Rich-Result-Tester überprüft werden. Der aber unterstützt Blogartikel nicht. Eine Erfolgsmeldung sieht daher so aus:
Was natürlich nicht bedeutet, dass die Daten auch sinnvoll sind, was ohne Vorschau schwierig zu erkennen ist.
Es könnte also sein, dass Google zugunsten von AMP Bogartikelauszeichnungen weitestgehend ignoriert. Das sollte ein Test in unseren Blogs zeigen. Wenn es funktioniert müsste nach einer Weile Googles Searchconsole die Rich results oder ähnliches als Suchergebnisanzeige auflisten.
Nach einer Testphase – und wenn niemand über ein Plugin stolpert, das diese Aufgabe bereits erledigte, ich hatte mir nämlich eingebildet wir hätten schon ein Plugin für Schema.org gehabt – werde ich das Plugin in Spartacus hochladen.
Emails für einen IPv6-Server trotz Cloudflare per Uberspace
Wednesday, 29. April 2020
Ich habe gerade diesen Serendipity-Blog auf einen neuen Server umgezogen (dazu später mehr). Das schwierigste war, die Emails wieder zum Laufen zu kriegen. Deshalb muss ich das unbedingt dokumentieren.
Das Setup sieht so aus: Der Server ist die kleinste Cloud-Compute-Instanz bei Vultr. Ich habe mal wieder den Preis optimiert. Sie kann nur IPv6. Nicht ganz so schlimm, denn die Domain wird von Cloudflare verwaltet, was für jeden AAAA-Eintrag direkt einen A-Eintrag bereitstellt, also Zugang per IPv4. Cloudflare aber ist problematisch, um direkt vom Server Emails zu verschicken. Aber dafür ist noch uberspace dabei, das sowieso meine Emails verwaltet und hier als SMTP-Relay dient.
Ich zeige alles im Detail.
uberspace
Uberspace muss die Domain als Email-Domain führen. Das wird in der Anleitung erklärt und ist nur ein auf uberspace per SSH abzusendender Befehl.
Der vordere Teil der Emailadresse muss auch angelegt sein. Bei mir ist das postmaster@...
. So sieht das in der Verwaltungsoberfläche aus:
Beachte, dass jeder Account bei uberspace bei einem von mehreren Servern liegt. In den Konfigurationen unten werde ich den Servernamen immer mit UBERSPACEHOST
ersetzen, damit niemand aus Versehen den meinen verwendet.
Cloudflare
Ich gehe davon aus, dass Cloudflare als DNS-Server eingerichtet ist. Das variiert je nach Hoster, der die Domain gerade verwaltet, aber man sollte da den Nameserver übertragen können.
Für den Webserver zeigt Cloudflare auf die IP des Server. Für die Email zeigt der MX-Eintrag auf den jeweiligen Uberspace-Host und ein TXT-Eintrag aktiviert SPF:
Mehr muss Cloudflare nicht tun, es braucht auch insbesondere und anders als die Dokumentation für Email-Versand rät keinen Nameserver-Eintrag, der ohne Proxy auf die IP zeigt. Denn der Server versendet die Mails ja nicht direkt.
Server/Postfix
Serendipity ist konfiguriert, Emails als postmaster@onli-blogging.de zu senden. Wordpress müsste man genauso einstellen.
Auf dem Server leitet postfix die Emails an uberspace weiter. Das ist im wesentlichen diese Anleitung. Die /etc/postfix/main.cf muss editiert werden:
smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu) biff = no append_dot_mydomain = no readme_directory = no compatibility_level = 2 smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key smtpd_tls_security_level=may smtp_tls_CApath=/etc/ssl/certs smtp_tls_security_level=may smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination alias_maps = hash:/etc/aliases alias_database = hash:/etc/aliases mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 mailbox_size_limit = 0 recipient_delimiter = + inet_interfaces = all inet_protocols = all myorgin = /etc/mailname mydestination = onli-blogging, localhost.localdomain, localhost myhostname = onli-blogging.de relayhost = UBERSPACEHOST.uberspace.de:submission smtp_sasl_auth_enable = yes smtp_sasl_security_options = noanonymous smtp_sasl_tls_security_options = noanonymous smtp_sasl_password_maps = hash:/etc/postfix/sasl_password
Nur der letzte Abschnitt ist abgeändert. Dort wird der Mailserver und die eigene Domain als Absender gesetzt. In /etc/mailname steht übrigens nur nochmal die Domain:
onli-blogging.de
In /etc/postfix/sasl_password müssen die uberspace-Zugangsdaten angegeben werden. Das ist einfach die Hauptemail und das SSH-Passwort:
UBERSPACEHOST.uberspace.de:submission UBERSPACE_EMAIL:UBERSPACE_PASSWORD
UBERSPACE_EMAIL
könnte beispielsweise xyznutzer@UBERSPACEHOST.uberspace.de
sein. Diese Datei muss noch umgewandelt werden:
postmap /etc/postfix/sasl_password
Jetzt sollten Emails rausgehen und ankommen!
Rückblick auf das virtuelle Serendipity-Camp (und neues zu utf8mb4)
Wednesday, 25. March 2020
Traditionell treffen sich die Mitstreiter des Serendipity-Projekts einmal jährlich im Linuxhotel in Essen. Geplant war es dieses Jahr am gerade vergangenen Wochenende. Corona hat uns das natürlich unmöglich gemacht. Stattdessen haben wir uns online getroffen, am Samstag per Jitsi Meet, am Sonntag gab es noch etwas Aktivität im Slack-Chat.
Es ist natürlich nicht das gleiche. Und Gedanken, da strukturiert mehr zu bieten als nur da zu sein und eventuell gemeinsam zu diskutieren und entwickeln waren nach dem Schwenk auf online (bei mir zumindest) ganz schnell weg. Trotzdem ist so etwas super wertvoll: Niemals sonst kann man sich so gut abstimmen, selten nehmen sich so viele Zeit für das Projekt. Und es ist schön, die anderen zu hören, auch neue Stimmen waren dabei :)
Im Ergebnis haben wir meiner Meinung nach superwichtige Sachen umgesetzt. Spartacus war stehengeblieben und unser uberspace musste umgezogen werden (von uberspace 6 auf uberspace 7), beides wurde angegangen. Wir haben die neue Version 2.3.3 veröffentlicht, sie vorher getestet und die Änderungen angeschaut. Da steckt besonders viel Arbeit von Thomas drin. Und wir haben – endlich! – Fortschritte mit MySQLs kaputtem utf8 gemacht.
Vor Jahren ist Serendipity bei Nutzung von MySQL in die utf8-Falle gelaufen. Es betrifft wirklich nur diese Datenbank. MySQL hat einen Zeichensatz namens utf8, der aber kein volles utf8 unterstützt, sondern nur Zeichen mit drei Byte. 4-Byte-Zeichen, z.B. Emoji wie 💩, kann man damit nicht speichern (hier geht es, weil ich SQLite benutze), Serendipity schneidet Texte dann ab. Daraus herauszukommen ist schwer, denn: Wenn man auf utf8mb4 umstellt braucht ein Zeichen 4 Bytes, Indexe können aber nur 1000 Bytes lang sein. Ein Index über eine varchar(255)
-Spalte würde dieses Limit schon sprengen! Wir hatten darüber schonmal auf einem Treffen geredet und Garvin hatte eine mögliche Lösung gebaut, Code, der die Indexe anpasst und dann die Datenbank umstellt. Aber diese Lösung lebt nun schon eine Weile in ihrem eigenen Branch und wurde nicht getestet (es zu testen ist schwierig! Vor allem, wenn man wie ich bisher das Problem nicht richtig verstanden hatte).
Jetzt haben wir nochmal darüber geredet und sind über einen Umweg über eine alternative Lösung gestolpert, deren Ansatz hier zu finden ist. Wenn die MySQL/MariaSQL-Datenbank neu genug ist, kann man die Storage Engine auf InnoDB setzen, wodurch Indexe 3000 Byte lang sein dürfen. Genug auch mit utf8mb4 für unser Datenbankschema!
Mittlerweile stellte sich raus, es ist nicht ganz so einfach, es müssen auch ein paar Einstellungen stimmen. Die können wir nicht im Code setzen, aber wir können sie prüfen. Dann wird das wohl sicher funktionieren, wenn es denn geht. Hoffentlich also eine praktische Lösung, die ohne die Versuche beim Treffen (wie mein Scheitern an der Idee, Dirks Blog umzustellen, weil da noch nicht durchgängig utf8 benutzt wird -> sowas muss also beachtet werden) nicht zustandegekommen wäre.
Das Ziel des verlinkten Codes ist es, Neuinstallationen mit utf8mb4 zu erstellen wenn möglich. Ich habe zweitens einen Upgrade-Task gebaut, um bestehende utf8-Installationen auf utf8mb4 umzustellen. Dann brauchen wir nur noch einen dritten Schritt, um von alten Zeichensätzen zu utf8mb4 zu kommen, und alle Blogs hätten vollen Unicode-Support.
Mir hat das Treffen Spaß gemacht. Klasse, alle wiederzusehen, toll auch, sich am Samstag nach dem Corona-Wochenendeinkauf voll auf etwas ganz anderes konzentrieren zu können, und am Sonntag nebenher am utf8-Problem zu basteln.
Auf ein nächstes mal, bald oder nächstes Jahr, online oder in Essen.
Edit: Das schrieben die anderen:
- Thomas auf Netz - Rettung - Recht: Das virtuelle #s9ycamp2020