v1.5.3
74
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
9726af9254 |
Fassung 1.5.3: der Editor blieb nach dem Update schwarz
Nach 1.5.2 meldete der Editor im Browser "The requested module './editor-model.js' does not provide an export named 'dropList'", und der Werkzeugkasten war leer. Ursache war nicht der Code, sondern das Zwischenspeichern. public/.htaccess setzt fuer jede .js-Datei Cache-Control: immutable, max-age=31536000 - ein Jahr. Die Fassungskennung haengt aber nur an den Einstiegsdateien, die die Vorlage schreibt. Die fuenf Module, die der Editor ueber import './...js' laedt, tragen keine: der Browser holte das neue editor.js und behielt das alte editor-model.js. Ein neues canvas-overlay.js traf damit auf ein Modell ohne dropList. Beide gemeldeten Symptome hatten diese eine Wurzel. Seit 1.5.1 baut das Skript den Werkzeugkasten auf, und editor.js importiert canvas-overlay.js in Zeile 5; bricht der Import, laeuft keine Zeile danach und die Elementliste bleibt leer. Das gemeldete fehlende Menue war der Werkzeugkasten, nicht die Verwaltungsnavigation - die wurde geprueft und ist in Chrome 152 in Ordnung. Behebung: eine Importkarte in base.html.twig haengt die Fassung an die aufgeloeste Adresse jedes Moduls, ohne dass eine Importzeile sie kennen muss. Das Zwischenspeichern ueber ein Jahr bleibt - die Leistung war nie das Problem, nur die fehlende Kennung. Eine Importkarte muss eingebettet sein; die Spezifikation kennt keine externe. Unter script-src 'self' wurde sie wortlos verworfen. AdminHeadersSubscriber erzeugt deshalb je Verwaltungsseite einen Nonce, nennt ihn in der Richtlinie und legt ihn in die Anfrage; csp_nonce() gibt ihn der Karte mit. Der Nonce erlaubt genau dieses eine Skript, 'self' gilt unveraendert fuer alles andere. Geprueft: der Browsertest verlangt an jeder angeforderten .js-Adresse eine Fassungskennung (vorher fehlten fuenf, jetzt tragen alle acht), dazu ein Test, der jeden Modulimport gegen die Importkarte haelt - Gegenprobe gemacht. npm test 28/28, phpunit 452/452, npm run test:editor vollstaendig. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>v1.5.3 |
||
|
|
7225ae052e |
Fassung 1.5.2: die Optionen selbst
Drei Bedienungen, die Flatsome an jeder Option hat und die hier fehlten. Geraeteschalter je Option. Bisher entschied ein einziger Schalter ueber der Vorschau, welches Geraet das ganze Bedienfeld bearbeitet; "ist die Ueberschrift auf dem Telefon kleiner" liess sich nur durch Umschalten und Hinsehen beantworten. Jetzt traegt jede Option drei Chips (D, T, M): sie zeigen, wo ein eigener Wert liegt, und ein Klick wechselt dorthin. Bedienfeld und Vorschau wechseln gemeinsam - einen Wert fuer ein Geraet zu setzen, das man nicht ansieht, ist blindes Aendern. Abstand als Rahmen. Vier Felder untereinander, beschriftet "Oben, Rechts, Unten, Links", zwangen zum Lesen. Jetzt sitzt jedes Feld an seiner Kante, die Lage ist die Beschriftung; in der Mitte verkettet ein Schalter alle vier. Er startet aus: er ersetzt den frueheren Knopf "Alle Seiten gleich setzen", und das war eine bewusste Handlung. Seiten mit unterschiedlichen Einheiten gelten als "gemischt" und bleiben unangetastet - ein gespeichertes 2rem wird nicht still zu 2px. Ziehfelder. Zahlenfelder lassen sich seitwaerts ziehen, Umschalt grob, Alt fein. Tippen und Pfeiltasten bleiben unveraendert. Nur fuer Maus und Stift: auf einem Tippgeraet ist ein seitliches Ziehen ueber ein Feld die Art, wie das Bedienfeld gescrollt wird. Dabei behoben: der Zug war nach einem Pixel zu Ende, weil jede Aenderung das Bedienfeld neu zeichnete und damit das Feld ersetzte, an dem der Zeiger hing (keepPanel). Der Kettenschalter verlor aus demselben Grund seinen Zustand. Und das Gleichziehen nahm den Wert des ersten Feldes, auch wenn es leer war - ein Druck auf die Kette loeschte damit die Seiten, die einen Wert hatten. Geprueft: npm test 27/27, phpunit 452/452, npm run test:editor vollstaendig mit neuem Abschnitt und ohne axe-Verstoss. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>v1.5.2 |
||
|
|
0e2334d30f |
Fassung 1.5.1: der Werkzeugkasten kennt den Zusammenhang
Umuts Einwand: Zeile und Spalte standen oben in der Auswahl, als waeren sie Seitenanfaenge. Sie gehoeren in den Inhalt - erst eine Sektion, dann eine Zeile darin. Das war nicht nur eine Anzeigefrage: eine Zeile nahm bisher jedes Kind an, eine Ueberschrift konnte neben den Spalten landen, und eine Spalte durfte ueberall stehen. Die Struktur, die der Editor in seinem eigenen Hinweistext beschreibt, galt fuer die Schaltflaechen nicht. Uebernommen ist Flatsomes Regelmodell (Elements.php): ALLOW - eine Zeile nimmt nur Spalten; REQUIRE - eine Spalte lebt nur in einer Zeile. Dazu ein Zusatz, den Flatsome nicht hat: ROOT_NEEDS_CONTAINER - eine Zeile ist kein Seitenanfang. In jedem Behaelter bleibt sie erlaubt, auch in einem Tab. Daraus die Bedienung: - Werkzeugkasten nach Aufbau gruppiert statt flacher Liste aus 31 Typen. - Was nicht hingehoert, ist gesperrt und sagt beim Ueberfahren warum. Eine Regel, die man erklaert bekommt, lernt man; eine Schaltflaeche, die nur nicht mehr reagiert, drueckt man weiter. - Was moeglich ist, sagt wohin es kommt. - Die Zeile wird nach Spaltenzahl angeboten und bringt ihre Spalten mit; der separate Zeilenbereich ist entfallen. - insertionTarget beantwortet "wohin kaeme das?", ohne etwas einzufuegen. Knopf, Einfuegepunkt, Ziehen und die Sperrlogik nutzen dieselbe Funktion - vorher entschied insertBlock allein, und insertRow hatte eine zweite Kopie derselben Platzierungslogik. Ein Element, das der gewaehlte Behaelter nicht nimmt, wird nicht gesperrt, sondern steigt auf, bis ein Elternteil es annimmt. Nebenbei behoben: postnav fehlte seit Schema v18 in labels und icons, der Strukturbaum zeigte dafuer "Unbekannt" und ein Fragezeichen. Geprueft: npm test 27/27, phpunit 446/446, npm run test:editor vollstaendig mit neuem Abschnitt und ohne axe-Verstoss. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>v1.5.1 |
||
|
|
22e4ada830 |
Fassung 1.5.0: die Vorschau wird zur Arbeitsflaeche
Abgleich mit dem Flatsome UX Builder (docs/FLATSOME-ABGLEICH.md): die Gestaltung ist Flatsome voraus, die Luecken liegen beim Elementkatalog und bei der Bedienung. Umuts Entscheidung: Bedienung zuerst, Shop-Elemente ausgelassen. Erste Haelfte der Bedienung: - Werkzeugleiste am Element in der Vorschau. Sie nennt das Element, auf das sie wirkt - die Seitenleiste hat dieselben fuenf Aktionen, und zwei gleichnamige Bedienelemente auf einem Bildschirm sind fuer eine Sprachausgabe nicht unterscheidbar. Beide Wege rufen dieselben Funktionen auf. - Auswahl- und Ueberfahrrahmen mit Beschriftung. - Einfuegepunkte an Ober- und Unterkante: das naechste Element landet dort statt am Ende. - Ziehen aus dem Werkzeugkasten in die Vorschau, mit Ablegemarke zwischen den Elementen und Rahmen um einen aufnehmenden Behaelter. Der Strukturbaum zieht in dieselbe Flaeche. Die Ebene liegt ueber dem Rahmen, nicht darin: die Vorschau wird bei jeder Aenderung ersetzt, eingezeichnete Bedienelemente waeren weg und stuenden in der Auszeichnung, die die Vorschau wahrheitsgetreu zeigen soll. Leiste und Pluszeichen werden gegenskaliert und bleiben in der Mobilvorschau fingergross. Im Modell neu: insertBlockAt, moveBlockTo, dropList. Dabei behoben: die Ebene war aria-hidden und enthielt fokussierbare Schaltflaechen; canContain zerbrach an einem fehlenden Block beim Ziehen aus dem Werkzeugkasten; beim Verschieben ans Listenende wurde der Index begrenzt, bevor die Entnahme verrechnet war. Geprueft: npm test 22/22, phpunit 434/434, npm run test:editor vollstaendig mit neuem Abschnitt und ohne axe-Verstoss. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>v1.5.0 |
||
|
|
af5a2cef86 |
Fassung 1.4.6: das Update schreibt mit, und die Ergebnisseite ist nachsichtig
Zwei Nachtraege zu 1.4.5, beide aus der Generalprobe. - Jeder Schritt des Archiv-Updaters geht sofort nach var/updates.log, waehrend des Laufs und nicht am Ende. Auf Umuts Hosting war die Ergebnisseite tot, und damit war auch verloren, was der Updater berichtet hatte. Genau so wurde der naechste Fehlschlag dann doch lesbar: "bin liess sich nicht beiseitelegen - der alte Stand wurde zurueckgeschoben" (ein Windows-Artefakt der Testumgebung, und zugleich der Beweis, dass der Rueckweg funktioniert). - Die Ergebnisseite versteht auch die Schreibweise bis 1.4.4. Das ist kein Nachgeben, sondern noetig: Beim Update schreibt der alte Code die Schritte in die Sitzung und der neue zeigt sie an. Eine Fassung, die nur die neue Schreibweise kennt, koennte das Update, das sie selbst einspielt, nicht berichten. Nachgestellt mit einer echten Installation aus dem Releasearchiv, die ueber die Oberflaeche aktualisiert wurde - nicht ueber die Konsole. Geprueft: 434 Tests auf PHP 8.2 und 8.4. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>v1.4.6 |
||
|
|
d295757ce0 |
Fassung 1.4.5: drei Fehler, die nur auf fremden Servern auftraten
Alle drei von Umut auf seinem Hosting gefunden, keiner davon auf meinem Rechner sichtbar. - Der Updateknopf endete mit 500. Das Update lief vollstaendig durch - alle neun Schritte, Dateien getauscht, var/ und .env unberuehrt -, aber die Ergebnisseite starb daran: der Updater ueber Git nennt einen Schritt "step", der ueber das Archiv nannte ihn "label", beide legen ihn unter demselben Sitzungsschluessel ab, und die Vorlage liest "step". Damit war auch der zweite Knopf unerreichbar. Zehn Tests prueften das Rueckgabe-Array, keiner die Seite, die es anzeigt; der neue Test rendert sie (ADR 071). - Die Verwaltung zeigte Git-Fehler auf einer Installation ohne Git. "git ist installiert" und "das hier ist eine Arbeitskopie" waren derselbe Schalter; auf dem Hosting ist Git vorhanden, die Installation kam aber aus dem Archiv. Dort stand "fatal: Not a git repository" an der Stelle der Fassungsnummer. Ohne Arbeitskopie verschwinden die Git-Karten jetzt (ADR 072). - "Sicherung anlegen" endete mit 500: VACUUM INTO gibt es erst seit SQLite 3.27, das Hosting hat eine aeltere Fassung - alt genug fuer die Installation, zu alt fuer die Sicherung. Bei aelteren wird jetzt unter einer Schreibsperre kopiert, und der Knopf faengt jeden Fehler ab statt mit einer 500-Seite zu enden (ADR 072). Nachgestellt wurde das mit einer echten 1.4.3-Installation aus dem Releasearchiv, eigener Datenbank, eigenem Port. Der Archiv-Updater laeuft dort vollstaendig durch: 1.4.3 -> 1.4.4, neun Schritte, var/ und .env unberuehrt. Geprueft: 433 Tests auf PHP 8.2 und 8.4, Editor-Browsertest. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>v1.4.5 |
||
|
|
4153ba0f65 |
Fassung 1.4.4: Migrationen im Browser, und ein Fehlschlag sagt warum
Zwei Luecken, die erst das Veroeffentlichen von 1.4.3 gezeigt hat. - Es gab keinen Weg, ausstehende Migrationen im Browser auszufuehren. Wer die Dateien per FTP hochlaedt - und das muss genau einmal jeder tun, dessen Installation die Updatekarte noch nicht kennt -, hatte danach neuen Code und eine alte Datenbank, und dafuer nur die Konsole. Also genau das, was auf geteiltem Hosting fehlt. Der Bildschirm "System" zeigt jetzt eine Karte, sobald etwas aussteht, nennt die Namen und fuehrt sie auf Knopfdruck aus. - "Die Releaseseite antwortet nicht" waren drei Ursachen in einem Satz. Beim Gegenpruefen des frischen Releases holte der Updater von hier gar nichts - nicht weil die Leitung zu waere, sondern weil diesem PHP der Zertifikatsspeicher fehlt. Auf einem Webhosting ist das der haeufigste Grund und der einzige, den man in einer Minute behebt; er steht jetzt in der Meldung. Bei genau diesem Fehler wird zusaetzlich der Weg ueber den Dateizeiger versucht - damit funktioniert der Abruf auf diesem Rechner. Abgeschaltet wird die Pruefung nicht: ein Update ohne Zertifikatspruefung koennte unterwegs ausgetauscht worden sein. Dazu der manuelle Weg Schritt fuer Schritt in docs/UPDATE.md und ein Test, der beides festhaelt: dass die Karte auffaellt und dass nur ein angemeldeter Administrator mit gueltigem Formular migrieren kann. Geprueft: 431 Tests auf PHP 8.2 und 8.4, Editor-, Browser- und Linkpruefung, Editor-Modelltests. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>v1.4.4 |
||
|
|
d6d476177a |
Fassung 1.4.3: Update ohne Git, Verwaltung auf dem Telefon, eigene Symbole
Vier Wuensche und ein Fund beim Nachmessen. - Farbwaehler im Designbereich. Das Textfeld bleibt massgeblich, damit "@akzent" ein Verweis auf die Palette bleibt und nicht beim ersten Klick zu einem festen Hexwert erstarrt (ADR 066). - Die Verwaltung auf dem Telefon: das Menue klappt unter 760 px zu und nennt den Bereich, in dem man steht; Ziele 44 px, kein Skript. - Eigene SVG-Symbole statt Unicode-Zeichen - ein Telefon ersetzt die sonst durch Emoji in fremdem Stil. Zwei Eintraege trugen dabei denselben Pfad; ein Test findet beides (ADR 067). - Update aus dem Releasearchiv: der Weg fuer Installationen ohne Git. Zwei Schritte, weil ein Prozess, der sich selbst ausgetauscht hat, mit dem alten Code weiterarbeitet. var/, .env, hochgeladene Schriften und das erzeugte Buendel bleiben unberuehrt; public/ wird dazu Datei fuer Datei zusammengefuehrt. Geprueft ohne Netz gegen eine Releaseseite im Speicher (ADR 068). Beim Nachmessen der echten Startseite statt einer Testseite: das groesste Element ueber der Falz ist dort kein <img>, sondern der Hintergrund des ersten Abschnitts - und der steht nur im Stylesheet. Drei Vorabverweise mit denselben Geraetegrenzen wie der Compiler holen genau die Variante, die die Regel auch nimmt. LCP 1,3 s -> 1,1 s. Dabei gefunden: dasselbe Bild wurde je Geraeteregel neu abgefragt - Startseite 19 -> 15 Abfragen (ADR 069). Geprueft: 428 Tests auf PHP 8.2 und 8.4, Editor-, Browser- und Linkpruefung, Lighthouse auf drei echten Seiten (alles ausser der Leistung der Startseite 100). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>v1.4.3 |
||
|
|
ea3dd4ddf2 |
Fassung 1.4.2: die Systempruefung nennt die SQLite-Fassung
Auf dem Hosting brach die Installation im dritten Schritt ab: near
"(": syntax error. Dort laeuft SQLite in einer Fassung vor 3.16, und
Doctrine liest das Schema mit Tabellenfunktionen wie
pragma_table_info(...), die es erst seit 3.16 gibt.
Die Pruefung nennt die gefundene Fassung jetzt vor der Wahl der
Datenbank, und der Datenbankschritt bietet SQLite gar nicht erst an,
wenn sie zu alt ist - mit dem Hinweis auf MySQL. Eine Voraussetzung,
die erst mitten in der Installation auffaellt, ist keine Pruefung wert.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
v1.4.2
|
||
|
|
c517173579 |
Fassung 1.4.1: dem Releasearchiv fehlten migrations.php und cli-config.php
Auf dem Hosting brach die Installation im dritten Schritt ab - "The configuration file does not exist", genau dort, wo die Tabellen entstehen sollten. Beide Dateien standen weder in der Mitnahme- noch in der Ausschlussliste des Releaseskripts. Ein Test ordnet jetzt jeden Eintrag im Projektstamm einer der beiden Listen zu: was neu dazukommt und unbedacht bleibt, laesst ihn fehlschlagen. Der Installationsweg wurde danach vollstaendig durchgespielt - 3504 Dateien entpackt, 14 Migrationen ausgefuehrt, 15 Tabellen angelegt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>v1.4.1 |
||
|
|
c5e85e4db0 |
Release 1.4.0 veroeffentlicht und der Installationsweg geprueft
Archiv, Pruefsumme und install.php haengen am Release des Tags v1.4.0. Einmal vollstaendig durchgespielt: install.php anonym geladen, in ein leeres Verzeichnis gelegt, aufgerufen - laedt 4,7 MB, prueft die Summe, entpackt 3502 Dateien mit vendor/ und loescht sich selbst. Die frische Installation antwortet mit der Systempruefung unter /install. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
43c20b14c7 |
Release veroeffentlichen: Ablauf dokumentiert, ADMIN_PATH in der Vorlage
Das Archiv und install.php gehoeren als Anhang an das Git-Release des passenden Tags - genau dort erwartet install.php sie. Ein privates Repository liefert diese Adresse nicht ohne Anmeldung aus; das steht jetzt in docs/UPDATE.md, samt der Alternative ueber --url=. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
b218dc79ff |
Fassung 1.4.0
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>v1.4.0 |
||
|
|
aaea385422 |
Die Verwaltung kann umziehen: /admin ist frei waehlbar
php bin/console cms:admin:path <neu> legt die Verwaltung auf eine andere Adresse. Geprueft wird, dass der Name frei ist und keine Seite verdeckt; der Wert steht in .env.local und fuellt einen Parameter, der als Praefix in jeder Verwaltungsroute steht, in der Firewall, in den Schutzkopfzeilen und in der Statistik. Die robots.txt nennt einen geaenderten Namen nicht - sie ist oeffentlich und waere sonst ein Wegweiser. Beim Standardnamen bleibt die Zeile, weil diese Adresse ohnehin jeder kennt. Die Auffangroute fuer Seiten steht jetzt zuletzt: sie kann einen frei gewaehlten Namen nicht per Regex ausschliessen, und die Reihenfolge ist ohnehin die richtige. Der Befehl raeumt den Zwischenspeicher auf, aber nicht den, in dem er selbst laeuft. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
9f1ac39251 |
Doku zu Schema v19: Knopf nach oben, Bildbetrachter, Rechtszeile, kaputte Stylesheet-Regeln
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
de1e66350b |
Knopf nach oben, Bildbetrachter, Rechtszeile als Baustein (Schema v19)
Der Knopf "nach oben" ist ein Anker, kein Skript: er springt an den Seitenanfang, eingeblendet ueber eine Scroll-Zeitachse. Abschaltbar und vollstaendig einstellbar - Seite, Form, Groesse, Farben, Schwelle, Beschriftung. Bilder lassen sich vergroessern, je Bild waehlbar (nichts / vergroessern / Adresse), Galerien mit einem Schalter. Grundlage ist ein gewoehnlicher Verweis auf die grosse Fassung: ohne JavaScript oeffnet er das Bild, mit JavaScript einen dialog-Betrachter mit Blaettern, Escape und Pfeiltasten. Das Skript laedt nur, wo es etwas zu tun hat. Die Rechtszeile wird ein Baustein und steht damit im Fussbereich statt als heller Streifen darunter. Die eingebaute Leiste erscheint nur noch, wenn die Seite den Baustein nicht enthaelt. Dabei gefunden: zwei Stylesheet-Regeln griffen seit drei Veroeffentlichungen nicht mehr. Beim Entfernen alter Regeln waren Selektorreste stehen geblieben, und CSS nimmt dann die naechste Regel mit - betroffen waren der Einwilligungsdialog und die Rechtszeile. Ein Test prueft jetzt jede CSS-Datei auf abgebrochene Selektoren. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
74766f6684 |
Weiterlesen ist ein Link, Menues teilen sich eine Abfrage
In der wechselseitigen Beitragsliste stand "Weiterlesen" als reine Beschriftung da: sichtbar wie ein Knopf, aber nicht anklickbar. Jetzt ein Link, mit dem Beitragstitel im Linktext fuer Vorlesesoftware. Jedes Menue holte beim Aufloesen die vollstaendige Seitenliste selbst. Mit zwei Menuen fiel das nicht auf, mit vier - Kopf, zwei Listen im Fuss, Rechtszeile - waren es vier gleiche Abfragen je Seitenaufruf. Einmal je Anfrage gemerkt: 21 -> 18 Abfragen auf der Startseite. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
6c477a52be |
Vorschau zeigt nie eine Seite ohne ihre Gestaltung
Gemessen: die Farben in der Vorschau und auf der veroeffentlichten Seite waren immer identisch. Der Aufbau war das Problem - die erzeugten Stile wurden im load-Ereignis des Rahmens angewandt, und das feuert erst, wenn das letzte Bild geladen ist. Auf der nachgebauten Startseite stand die Vorschau dadurch 1440 ms lang ohne eine einzige Farbe da. Jetzt wird angewandt, sobald das Dokument geparst ist; der Rahmen bleibt bis dahin verdeckt; und gestaltet wird nur das neue Dokument - der erste Anlauf gestaltete das alte und schaltete zu frueh sichtbar. Die Editorkontrolle prueft dagegen das Verhalten statt der Zeit: der Rahmen muss beim Aufbau verdeckt werden und danach wieder sichtbar. Eine Zeitmessung haette auf der kleinen Testseite nichts gefunden. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
e0d06ac44c |
Cloudflare Turnstile optional, Formular-Fehlerseite repariert
Turnstile laesst sich in den Einstellungen einschalten: aus, bis beide Schluessel eingetragen sind; die Sicherheitsrichtlinie oeffnet sich nur auf Seiten mit Formular, und nur fuer challenges.cloudflare.com. Antwortet Cloudflare nicht, gilt die Absendung als bestanden - ein Ausfall dort darf keine Kundenanfrage kosten. Die drei eingebauten Pruefungen ohne Dritte bleiben davon unberuehrt. Dabei gefunden: wer ein Pflichtfeld vergass, bekam die Seite ohne Gestaltung zurueck. Der Formularcode baute sie selbst ein zweites Mal auf und liess Theme, Blockstile und Schriften weg. Jetzt geht auch dieser Weg durch den Seitencontroller, die Meldungen reisen als Anfrageattribut mit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
a2dfd0f796 |
Schriften ins Repository, Anleitung fuer neue Websites, Schutzkopfzeilen
Die Lato-Dateien liegen jetzt unter public/assets/fonts/ samt OFL-Text und einer Lizenznotiz: auf einem frischen Server fehlt nichts, und es wird nie versehentlich von Google geladen. docs/NEUE-WEBSITE.md beschreibt, wie eine neue Kundenwebsite entsteht - Reihenfolge, Dokumentformat, Bilder, SEO, Pruefungen - und nennt am Ende die fuenf Fehler, die hier immer wieder passiert sind. Permissions-Policy ergaenzt (Kamera, Mikrofon, Standort, Sensoren aus), X-Powered-By entfernt: der Server nannte in jeder Antwort seine genaue PHP-Fassung. Die Browserpruefung misst die Kopfzeilen jetzt. Behoben: der Editor kannte Schema v17, der Validator v18 - die Beitragsnavigation liess sich in keinem aktuellen Dokument einfuegen. Ein Test bindet die Zahl des Editors an die des Validators. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
7c6b2a9ec8 |
Livegang vorbereitet: Checkliste, Weiterleitungen, www-Regel
docs/LIVEGANG.md trennt, was geprueft ist, von dem, was nur auf dem echten Hosting geprueft werden kann - Mailversand, HTTPS, MySQL, Cronjobs, Rechtstexte - und nennt die Reihenfolge am Umzugstag. Fuer den Nachbau sind 14 Weiterleitungen von den alten WordPress-Adressen auf die neuen angelegt; ohne sie haette jede bei Google stehende Adresse nach dem Umzug mit 404 geantwortet. Die Datenschutzerklaerung nennt jetzt die Tatsachen: Schriften vom eigenen Server, kein Google Maps, kein reCAPTCHA. In der .htaccess steht die www-Umleitung vorbereitet und auskommentiert, mit dem Hinweis, dass sie zu SITE_ORIGIN passen muss. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
074ef0e7e5 |
Eigener Suchtitel, Schriften lokal, Bilder in Anzeigegroesse
Getrennter Titel fuer Suchergebnisse je Seite und Beitrag (Migration 20260913000100): auf der Seite steht "Leistungen", im Suchergebnis darf der lange Titel stehen. Leer heisst weiterhin: der Titel der Seite. Schriften kommen jetzt vom eigenen Server. Ein Knopf im Designbereich oder cms:fonts:fetch holt die gewaehlten Google-Schnitte als WOFF2 nach public/assets/fonts. Das spart zwei fremde Verbindungen nacheinander (gemessen 820 ms) und die IP-Weitergabe an Google. Ohne Dateien bleibt es beim bisherigen Verweis - eine Seite ohne Schrift waere schlimmer. Ein Stylesheet statt vier, mit Pruefsumme im Namen und ohne Kommentare, dazu eine .htaccess mit Kompression, Cache und Schutz interner Dateien. Der Entwicklungsserver sendet dieselben Kopfzeilen, sonst misst man lokal etwas, das es im Betrieb nicht gibt. Bilder in der Groesse, in der sie erscheinen: ein nur fuer Desktop gesetztes Hintergrundbild gilt auf dem Telefon in Telefongroesse (189 KB -> 40 KB), img nennt seine feste Breite oder sizes="auto", und fetchpriority liegt auf dem ersten Bild des Inhalts statt auf dem Logo. Neu: npm run test:links prueft jeden internen Verweis auf seine Antwort. Lighthouse gegen den Nachbau: Barrierefreiheit, Best Practices und SEO 100 auf allen vier geprueften Adressen, Performance 100 ausser auf der bilderreichen Startseite (98 mobil, 96 Desktop). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
35d8270afd |
Vorschaubild beim Teilen, robots.txt als Bot-Steuerung
Das Feld "Vorschaubild beim Teilen" gab es seit dem SEO-Paket, ausgegeben wurde es nie: keine mit KantSites gebaute Seite hatte ein og:image. Es wird jetzt aufgeloest - erst das gesetzte Vorschaubild, sonst das Beitragsbild - als absolute Adresse bis 1600 px, dazu og:site_name, og:locale, og:image:alt und twitter:card (klein ohne Bild, gross mit). Dasselbe Bild steht im strukturierten Datensatz eines Beitrags; Archive haben jetzt ebenfalls Open-Graph-Angaben. Eigene robots.txt-Zeilen: 200 statt 30, und Leerzeilen bleiben als Trenner erhalten - Regeln je Bot (welche KI-Crawler lesen duerfen) brauchen Bloecke, nicht einen Klumpen. Behoben: die Symbolerzeugung suchte feste Breiten statt der Varianten, die das Bild wirklich hat - ein 192 px grosses Zeichen, also der haeufigste Fall, scheiterte damit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
f2ef2a4901 |
Beitraege optional, Unterstriche nur im Text, eigenes Symbol
Eine Website ohne Beitraege redet nirgends von Beitraegen: Archiv und Feed antworten mit 404, der Feedverweis faellt aus dem Kopf, und der Hinweiskasten der Beitragsliste bleibt im Editor statt oeffentlich zu erscheinen. Das gilt auch je Kategorie, sobald deren letzter Beitrag weg ist. Dabei gefunden: die Liste fragte je Beitrag nach Bild und Begriffen - jetzt je eine Abfrage fuer die ganze Liste (22 -> 16 Abfragen auf der Startseite des Nachbaus). Unterstrichene Links gibt es nur noch im Fliesstext, dort mit einem Schalter im Designbereich; Karten, Menue, Kontaktzeilen und der Ansehen-Streifen haben keinen mehr. Die aktuelle Seite im Menue wird ueber das Schriftgewicht kenntlich - die Akzentfarbe fiel im dunklen Fussmenue durch die Kontrastpruefung. Neu: das Symbol der Website laesst sich festlegen. Aus einem Bild der Mediathek entstehen beim Speichern quadratische PNG-Dateien in 32 und 180 px; schlaegt das fehl, wird die Einstellung nicht gespeichert. Die Browserpruefung laeuft jetzt gegen jede Installation statt nur gegen die Demo: geprueft wird, was in der Sitemap steht, und das Ladebudget trennt Bilder vom Beiwerk. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
f0b634f0c1 |
Einblendungen laufen beim Scrollen, ohne Skript
Umut: "Effekte gibts keine, sind die aktiv?" Nachgemessen: die Zeigereffekte liefen alle. Die Einblendungen gab es seit Schema v3 - nur benutzt hatte sie niemand, weil eine Animation beim Laden unterhalb der Falz wertlos ist. Mit animation-timeline: view() laufen dieselben Keyframes, wenn der Abschnitt in den Blick kommt - hinter der Bewegungsschranke, hinter @supports (Firefox und Safari behalten das Einblenden beim Laden) und mit einem Bereich, der endet, bevor der Abschnitt in der Mitte steht. Dabei hat axe einen Fehler gefunden, den ich selbst gebaut hatte: eine Scroll-Zeitachse ist umkehrbar, also stand alles unterhalb der Falz dauerhaft am Anfang der Kurve - bei opacity .35 blass, bei .85 immer noch 3,86:1 statt 7,1:1. Auf dem Scrollweg wird deshalb nur Bewegung animiert, keine Deckkraft. Benutzt wird es jetzt auch: alle drei Beitragsvorlagen bringen die Einblendung je Abschnitt mit. Geprueft: 400 Tests unter PHP 8.2 und 8.4, Editortest, Browserpruefung, axe ohne Verstoss auf Startseite, Projekteseite und Beitrag - vor und nach dem Durchscrollen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
0d6c1a17af |
Vier Darstellungen fuer die Beitragsliste
Karten (Raster mit Bild oben), Liste (Bild links, Text rechts), Kompakt (nur Titel und Datum) und Wechselseitig (Bild mal links, mal rechts). Dieselben Daten, dasselbe Markup - nur eine Klasse wechselt. Die erste Fassung von "Wechselseitig" war ein umgedrehter Flexkasten und sah auch so aus. Jetzt sitzt das Bild in einer Karte mit Ecken, Schatten und festem Verhaeltnis, der Text hat eine Nummer aus einem CSS-Zaehler, eine begrenzte Zeilenlaenge und einen sichtbaren Verweis, und zwischen den Reihen liegt eine feine Linie. Zwei Details: die Karte ist das Listenelement, also zaehlt :nth-child auf ihr - die erste Fassung wechselte deshalb gar nicht. Und die Umkehrung laeuft ueber order statt row-reverse, damit auf dem Telefon sauber wieder Bild ueber Text steht. Geprueft: 399 Tests unter PHP 8.2 und 8.4, 18 JS-Tests, Editortest, Browserpruefung, axe ohne Verstoss auf allen vier Darstellungen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
84e88c6636 |
Drei Aufbauten fuer neue Beitraege
Umut wollte mehrere Designs zur Auswahl. Bei Seiten waere das falsch - dort weiss vorher niemand, was daraus wird. Bei Beitraegen ist die Form fast immer dieselbe, und wer jedes Mal von vorn anfaengt, baut jedes Mal etwas leicht anderes. Bildkopf (Bild ueber die volle Breite, Titel darauf), Klassisch (Titel und Vorspann schmal, Bild darunter) und Magazin (Titel neben den Eckdaten). Gewaehlt wird beim Anlegen; danach ist jeder Block aenderbar wie jeder andere. Kein Aufbau verlaesst sich auf ein Bild, das es noch nicht gibt. Dabei ist eine Regel gefallen: der erste Textblock eines Abschnitts wurde automatisch zur Kleinbeschriftung in Akzentfarbe. Das gestaltet nach Position statt nach Absicht - im Fussbereich wurde daraus roter Versalientext, in der Magazin-Vorlage aus dem Einstiegsabsatz eine Beschriftung. Wer eine Beschriftung will, stellt sie ein. Geprueft: 398 Tests unter PHP 8.2 und 8.4, Editortest, Browserpruefung, axe ohne Verstoss auf allen drei Aufbauten. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
1b22265a54 |
Beitragsnavigation als Baustein (Dokumentschema v18)
Umut: "Beitragsseite gefaellt mir nicht, sollte wie bei kant-it.de sein oder besser. Falls noetig Plugin bauen." Die Originalseite hat Galerie, Vor/Zurueck zwischen Projekten und einen Abschlussaufruf. Galerie und Aufruf gab es laengst - sie waren nur nicht benutzt. Die Navigation gab es nicht. Kein Plugin: ein Plugin ist hier ein Bausteintyp, dessen Eigenschaften der Kern aufbewahrt, aber nicht rendert - es koennte also nichts ausgeben, solange es keine Laufzeit dafuer gibt. Und die Nachbarn eines Beitrags stehen in derselben Tabelle wie die Beitragsliste, die der Kern schon fuellt. Also ein Baustein: postnav. Gespeichert sind zwei Beschriftungen, mehr nicht - welcher Beitrag vorher und nachher kommt, entscheidet der Renderer. Gesucht wird innerhalb derselben Kategorie, und am Rand wird nicht umgebrochen. Ausserdem: die uebernommenen Projekttexte begannen mit dem wiederholten Titel (20 Beitraege), und schmale Abschnitte standen links statt mittig - max-width ohne margin:auto ist eine halbe Einstellung. Geprueft: 396 Tests unter PHP 8.2 und 8.4, 18 JS-Tests, Editortest, Browserpruefung, axe ohne Verstoss auf der Beitragsseite. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
5a5933f8cd |
Slider mit Autorotation, Beitragsliste mit Blaettern
Zwei Wuensche, zwei Bausteine. Die Autorotation ist Sekunden, kein Haekchen: 0 heisst aus, ab 3 laeuft sie. Sie braucht ein Skript - das zweite auf einer oeffentlichen Seite nach den Tabs - und es kommt nur auf Seiten mit einem solchen Slider, sonst bleibt script-src 'none'. Es laeuft nicht bei "weniger Bewegung", hoert beim ersten Tippen, Klicken, Wischen oder Scrollen endgueltig auf und pausiert bei Zeiger, Fokus, Hintergrundtab und ausserhalb des Bildes. Ohne Skript bleibt der Slider vollstaendig bedienbar. Die Beitragsliste kann blaettern statt abzuschneiden. Eine Auswahl auf der Startseite zeigt die neuesten und hoert auf; eine Uebersichtsseite blaettert und sagt, wie viele es sind. Das war die eigene Regel aus Arbeitspaket M, die fuer diesen Baustein noch nicht galt. Beim Bauen zweimal dieselbe Falle wie vorgestern: eine Variable war in der Schliessung nicht gebunden. Einmal das Sprungziel des Sliders (-78 statt 666), einmal die Seitenzahl - die zweite fiel sofort auf, weil die Seite mit 500 antwortete. Geprueft: 395 Tests unter PHP 8.2 und 8.4, 18 JS-Tests, Editortest, Browserpruefung, axe ohne Verstoss. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
b2c4f45474 |
Eigener Durchgang vor dem Livegang: drei Fehler, zwei Feinheiten
Umut: "schau selbst drueber, wuerdest du so online gehen?" Nein, so nicht. Verborgener Text stand sichtbar auf der Seite: .visually-hidden gibt es in admin.css, aber nicht in site.css. "Bewertung: 5 von 5" neben den Sternen und "(Pflichtfeld)" hinter jedem Formularfeld waren zu lesen - seit dem ersten Formular. axe meldet so etwas nicht, es prueft das Ansagen, nicht das faelschliche Sichtbarsein. Jede Spalte war ein Kasten: Rahmen, Ecken, 30px Innenabstand von vornherein. Eine Spalte ist ein Layoutmittel; die Karte ist jetzt eine Einstellung. Die Demoseite wirkt dadurch ruhiger. Der Knopf im Aufruf-Band war Tinte auf Tinte, also auf dunklem Grund fast unsichtbar - ausgerechnet beim Handlungsaufruf. Aufruf-Band und Formular nehmen die Akzentfarbe. Dazu: gestapelte Karten klebten aneinander (18px), und die linke Spalte im Kontaktbereich war halb leer. Geprueft: 393 Tests unter PHP 8.2 und 8.4, Editortest, Browserpruefung, axe ohne Verstoss. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
2715d329ef |
Beitragskopf mit Bild, und die Metazeile laesst sich abschalten
Umut meinte den Kopf beim Oeffnen eines Beitrags. Im Original fuellt dort das Projektbild den Kopf, darueber ein Verlauf mit Badge, Titel und einer kurzen Akzentlinie - der Text mittig. Nachgebaut ohne neue Funktion, aus Hintergrundbild, Verlauf und Flexausrichtung. Dabei stand die Zeile mit Datum, Autor und Kategorie ueber dem Bild und wiederholte, was der Titel darin schon sagt. Neue Einstellung "Datum, Autor und Kategorie ueber einem Beitrag zeigen", Voreinstellung an. Geprueft: 391 Tests unter PHP 8.2 und 8.4, Editortest, Browserpruefung, axe ohne Verstoss auf dem Beitrag. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
1b164f4c86 |
Beitragskarten reagieren auf Zeiger und Tastatur
Umut: "es gibt keinen Mausover-Effekt, das fehlt". Am Original nachgemessen und uebernommen: die Karte hebt sich um 8px mit weichem Schatten, das Bild zieht auf 1,06 auf, darueber blendet ein Hinweis ein. Die Bewegung steht vollstaendig hinter der Bewegungsschranke - wer weniger Bewegung eingestellt hat, bekommt keine, sieht den Hinweis aber trotzdem. Alles haengt zusaetzlich an :focus-within, damit der Effekt nicht nur Mausbenutzern gehoert. Der Hinweis ist fuer Vorlesesoftware ausgeblendet, weil der Titel darunter zum selben Ziel fuehrt. Ausserdem: der Leuchteffekt trug noch das Gruen der Vorlage statt der Akzentfarbe der Website. Geprueft: 391 Tests unter PHP 8.2 und 8.4, Editortest, Browserpruefung, axe ohne Verstoss. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
5f23194760 |
Kennzahl und Kundenstimme folgen wieder ihrer Einstellung
Beim vollstaendigen Nachbau von kant-it.de aufgefallen: die Groesse der Kennzahl liess sich am Block einstellen und aenderte nichts, weil .block-stat strong 44px fest setzte. Dasselbe bei der Kundenstimme mit 18px. Beide erben jetzt vom Block - dieselbe Familie wie die Theme-Skala, die zuvor die Kartenueberschriften ueberschrieben hat. Der Nachbau umfasst jetzt alle 29 Projektbeitraege mit den echten Bildern und Texten sowie die vollstaendige Datenschutzerklaerung. Dabei ein Befund fuer den echten Umzug: 11 der 29 Projektbilder haette die Mediathek auf einem 128-MB-Hosting abgewiesen, zwei auch mit mehr Speicher - sie ueberschreiten die Pixelgrenze. Ein Umzug muss solche Bilder vorher verkleinern. Geprueft: 390 Tests unter PHP 8.2 und 8.4, Editortest, Browserpruefung, axe ohne Verstoss auf fuenf Ansichten des Nachbaus. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
e6dcc8e823 |
Offener Punkt notiert: Menueart je Geraet
Beim Nachbau aufgefallen: horizontal oder Burger gilt fuer alle Groessen. Heute loest man es mit zwei Menuebloecken und display:none je Geraet - das funktioniert, ist aber eine Umgehung. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
e21dff91fe |
Slider mit Punkten, Karten als Karten, hervorgehobenes Wort
Umut hat den Nachbau Detail fuer Detail mit kant-it.de verglichen. Vier Stellen, an denen das CMS etwas nicht konnte oder etwas Falsches tat. Der Slider zeigte eine Rollleiste statt Punkte. Punkte zeichnet jetzt der Browser selbst - scroll-marker-group und ::scroll-marker, ohne Skript, mit erkennbarem aktivem Punkt. Wo ein Browser das noch nicht kennt, bleibt das wischbare Schiebefeld. Pfeile gibt es bewusst nicht: Chrome legt ::scroll-button an den Seitenrand statt in den Slider. Und er rotiert nicht von selbst, weil eine oeffentliche Seite kein JavaScript laedt. Eine Beitragskarte war keine Karte, sondern eine lose Spalte. Jetzt weiss, 18px Ecken, Bild buendig oben im Verhaeltnis 16:10, Text darunter. Die Theme-Schriftskala ueberschrieb die Groessen der Bausteine: jede Kartenueberschrift war so gross wie eine Abschnittsueberschrift. Eine Ueberschrift darf ab v17 ein Wort hervorheben. Dabei waere beinahe eine Luecke entstanden: die Dokumentfassung war in der Schliessung des Filters nicht gebunden, der Filter lief nie, die Ausgabe war schon unescaped. Ein Test mit <script> in einer Ueberschrift hat es gezeigt. Geprueft: 390 PHP-Tests unter 8.2 und 8.4, 18 JS-Tests, Editortest, Browserpruefung, axe ohne Verstoss auf dem Nachbau. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
70283db20a |
Dokumentschema v17: Projektraster, verlinktes Bild, klebender Kopfbereich
Alles aus dem Nachbau von kant-it.de, den Umut durchgesehen hat. Eine Beitragsliste kann Datum, Autor, Auszug und Kategorie ausblenden und sieht damit aus wie ein Projektraster statt wie ein Blogarchiv. Beinahe lautlos danebengegangen: |default(true) macht in Twig aus einem gespeicherten false ein true - die Einstellung haette sich speichern lassen und nichts getan. Der Test prueft beide Richtungen. Ein Bild darf verlinken, damit ein Logo auf die Startseite zeigt; die Adresse geht durch dieselbe Pruefung wie jeder andere Link. Und der Kopfbereich kann beim Scrollen oben bleiben - als Einstellung der Website, weil nur das umschliessende Element kleben kann. Der groesste Fund steckt im Editor: die Liste bekannter Schemafassungen endete bei 12, waehrend Bausteine v13 bis v15 verlangen. In einem aktuellen Dokument liess sich damit kein Baustein mehr einfuegen, und Symbol, Fortschritt, Slider und externer Inhalt in gar keinem. Jetzt eine Zahl an einer Stelle, mit einem Test ueber jeden Typ und jede Fassung. Geprueft: 389 PHP-Tests unter 8.2 und 8.4, 18 JS-Tests, Editortest, Browserpruefung. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
efa285c0d0 |
Die Gestaltung faerbt jetzt auch die Bausteine
Gefunden beim Nachbau von kant-it.de: eine Website mit eigener Palette
behielt das Gruen der Vorlage. Symbole, Knoepfe, Rahmen, ruhiger Text,
Fokusring und der Einwilligungsdialog kamen aus festen Token in site.css,
die das Theme nie gesetzt hat - die Farben liessen sich einstellen und
taten nichts.
Das Theme setzt --ink, --paper, --accent, --muted, --line und --mint jetzt
selbst. Als Akzent dient die Linkfarbe, nicht ein Palettenname: das Token
faerbt auch kleine Beschriftungen, und eine helle Akzentfarbe waere dort
nicht lesbar. --muted und --line werden aus Textton und Hintergrund
gemischt; eine Palettenfarbe gleichen Namens gewinnt.
Der Einwilligungsdialog nimmt die Primaerfarbe und laesst sich eigens
faerben ueber eine Palettenfarbe mit dem Schluessel "consent".
Ausserdem aus demselben Nachbau: Ueberschriften werden nicht mehr getrennt
("di-gitale Exzellenz"), und Fliesstext auf dunkel gefaerbten Abschnitten
mischt seine Farbe aus der geerbten statt aus einem Token fuer helle
Hintergruende.
Geprueft: 381 Tests unter PHP 8.2 und 8.4, axe ohne Verstoss auf vier
Seiten des Nachbaus in Desktop- und Handybreite.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
e34b4dca67 |
Installer: sechs Bildschirme, und eine Datei davor
/install fuehrt von einer leeren Installation zu einer Website: Systempruefung, Datenbank (SQLite oder MySQL, Verbindung sofort geprueft), Migration im Prozess ohne Konsole, Website mit Startseite, Bereichen, Menue sowie Impressum und Datenschutzgeruest, erstes Konto, Abschlussliste. Jeder Schritt schreibt sein Ergebnis sofort, damit ein Neuladen nichts verliert. Gesperrt wird ueber den Zustand der Datenbank - gibt es ein Konto, antwortet /install mit 404. Eine Datei koennte jemand loeschen. Solange nichts installiert ist, fuehrt jede Adresse zum Installer statt zu einem 500 aus einer fehlenden Tabelle. Und weil ohne APP_SECRET nicht einmal die Seite bootet, die das erklaeren wuerde, erzeugt der erste Start das Geheimnis selbst. scripts/install.php ist die einzelne Datei davor: Adresse und SHA-256 stehen darin (vom Buildskript eingetragen), ohne passende Pruefsumme wird nicht entpackt, jeder Archiveintrag wird gegen das Zielverzeichnis geprueft, und danach loescht sie sich selbst. Geprueft: 379 Tests unter PHP 8.2 und 8.4, darunter der ganze Ablauf durch die HTTP-Schicht, neun ZIP-Slip-Varianten, axe ohne Verstoss auf allen Installationsbildschirmen, und das entpackte Releasearchiv startet in den Installer. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
c3bff7d936 |
Bilder in vier Breiten, Releasearchiv fuer Hosting ohne Composer
Uploads werden weiterhin nach WebP umgewandelt, jetzt in vier statt drei Breiten (480/960/1600/2400) und ohne Hochskalieren. Hintergrundbilder waehlen ihre Variante je Geraet, weil CSS kein srcset kennt. Dabei kam ein Fehler heraus, den erst der Browsertest zeigte: der Dokumentpruefer erlaubte drei sources je Bild, also war mit der vierten Variante jedes Dokument mit einem Bild ungueltig - ohne sichtbare Meldung. Die Grenze haengt jetzt an MediaLibrary::WIDTHS. Geteiltes Hosting hat meistens keinen Composer. scripts/build-release.php baut deshalb auf einem Build-Rechner ein Archiv mit fertigem vendor/ ohne Entwicklungspakete, samt SHA-256. Der Updater bricht ab, wenn ein Update composer.lock aendert und Composer auf dem Server nicht aufrufbar ist, statt mit einem unpassenden vendor/ weiterzulaufen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
c046681302 |
Fassung 1.2.0
Sicherung und Wiederherstellung, Ladeverhalten gemessen, Seitenbereiche je Seite, Menuearten, Designerausbau. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>v1.2.0 |
||
|
|
269fb223af |
Messen statt vermuten: 18 Abfragen auf 8, Ladebudget, Blaettern ueberall
Arbeitspaket M sagte "Abfragen je Seite zaehlen. Messen, dann zusammenfassen." Messen braucht ein Messgeraet, also gibt es jetzt eines: ein Zaehler als Doctrine-Middleware, dessen Zahl ausserhalb der Produktion im Kopf X-Kant-Queries steht. Keine Profiler-Maschinerie, eine Zahl. Die erste Messung: die Startseite brauchte 18 Abfragen. Nicht wegen einer komplizierten Seite, sondern weil SiteSettings::load() und Theme::load() je Aufrufer dieselbe Zeile erneut holten - Renderer, strukturierte Daten, Einwilligungsschalter, Vorlagen. Beide merken sich ihren Stand jetzt fuer die Dauer einer Anfrage: 18 auf 8. Dabei ist mir die klassische Falle des Merkens selbst passiert, und ein bestehender Test hat sie sofort gezeigt: ich leerte den Merker am Anfang des Speicherns. Das Speichern liest den Stand aber noch einmal und fuellte ihn damit erneut - der Rest der Anfrage bekam den alten Stand. Geleert wird jetzt nach dem Schreiben. Das Ladebudget wird gemessen statt behauptet: die Browserpruefung liest je Seite HTML-Groesse, CSS-Groesse, Anzahl Anfragen, Anzahl Skripte und Abfragezahl und prueft Obergrenzen. Startseite: 7,4 KB HTML, 22,7 KB CSS, 2 Anfragen, 8 Abfragen, 0 Skripte. Die Null ist die wichtigste Zahl - sie haelt als Test fest, was bisher nur Absicht war. Das erste Bild einer Seite ist nicht mehr lazy. Es ist meistens das groesste Ding ueber der Falz, und es zu verzoegern verzoegert genau das Pixel, auf das jemand wartet. Der Renderer bestimmt es in Renderreihenfolge, Kopfbereich zuerst. Eine feste Obergrenze ist kein Blaettern: der Fassungsverlauf hoerte bei dreissig auf, die Einsendungen bei fuenfzig, die Weiterleitungen zeigten bis zu zweitausend auf einmal. Das Erste sieht aus wie "es gibt dreissig" und ist das Einzige, was eine Historie nicht tun darf. Alle drei blaettern jetzt, mit derselben Rechnung und demselben Pager wie Beitragsarchiv und Mediathek. 347 PHP-Tests / 1422 Assertions unter PHP 8.2.12 und 8.4.22. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
8c49f6a67a |
Sicherung und Wiederherstellung - und die Wiederherstellung ist nachgewiesen
Arbeitspaket O. Der Teil, um den es geht, ist nicht das Sichern, sondern das Zurueckspielen: eine Sicherungsfunktion, deren Wiederherstellung nie gelaufen ist, ist eine Vermutung. Die Datenbank wird nicht kopiert, sondern von SQLite ausgeschrieben (VACUUM INTO). Ein copy() waehrend eines Schreibvorgangs ergibt eine Datei, die vorhanden aussieht und sich am Tag der Wiederherstellung nicht oeffnen laesst. Der Medienordner gehoert dazu - ohne die Dateien stellt die Sicherung eine Website voller kaputter Bilder her. .env gehoert nicht dazu: darin steht APP_SECRET, und eine Sicherung wird heruntergeladen und weitergereicht. Was nicht drin ist, steht im Manifest. Jede Sicherung traegt Zeitpunkt, Anlass, Fassung, Migrationsstand, Inhaltszahlen und die SHA-256 der Datenbank. Die Uebersicht zeigt "unversehrt" oder "Pruefsumme falsch" - eine Sicherung, von der man erst beim Zurueckspielen erfaehrt, dass sie kaputt ist, waere schlimmer als keine. Beim Zurueckspielen: neuere Fassung wird abgewiesen (mit --force geht es), zuerst wird der aktuelle Stand gesichert, Wartungszustand an, Medien werden ergaenzt statt ersetzt - eine Datei, die nach der Sicherung hochgeladen wurde, bleibt liegen. Die Massnahme gegen Datenverlust darf nicht selbst welchen verursachen. In der Verwaltung gibt es Liste und Anlegen-Knopf, aber kein Zurueckspielen: ein Knopf, der die ganze Datenbank ersetzt, gehoert nicht neben einen, der eine Seite speichert. Nachgewiesen, zweimal: acht Tests gegen eine wegwerfbare Installation (Sicherung, Seite und Bilddatei loeschen, zurueckspielen, beides wieder da) - und von Hand auf der Entwicklungsinstallation mit einer eigens angelegten Testseite: 5 Seiten, gesichert, geloescht (4), zurueckgespielt (5, Seite mit ihrer Adresse wieder da), Testseite entfernt (4). Damit ist der aelteste offene Punkt aus Paket I erledigt. Ein Fall, den erst der Test zeigte: zwei Sicherungen in derselben Sekunde - nicht akademisch, denn die Wiederherstellung legt selbst eine Sicherheitskopie an. Der Name bekommt jetzt eine Nummer, statt dass die zweite scheitert. Offen: MySQL (mysqldump fehlt) und ein Download ueber den Browser. 344 PHP-Tests / 1397 Assertions. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
af3589c95c |
Seitenbreite wirkt, vier Menueplaetze, Seiten ohne Kopfbereich
Drei Fragen, drei unterschiedliche Antworten. Die globale Seitenbreite war einstellbar und wirkte nur in eine Richtung: site.css schrieb width:min(1180px,...), also schluckte die 1180 jeden groesseren Wert aus dem Designbereich. Schmaler ging, breiter nicht, ohne jede Meldung. Die Zahl kommt jetzt aus dem Theme. Das ist der dritte Fehler dieser Art an einem Tag - nach der Rahmenstaerke und der Bildrundung -, und alle drei hatten dieselbe Ursache: CSS, das nie gegen eine Erwartung geprueft wurde. Menueplaetze und Menueart waren vermischt. Wo ein Menue steht, bestimmt der Block und war immer frei. Welche Eintraege es zeigt, bestimmt der Platz - davon gab es zwei, jetzt vier (Haupt, zweite, Fusszeile, Rechtliches). Wie es aussieht, war gar nicht einstellbar: jetzt waagerecht, untereinander oder aufklappbar als Burger. Der Burger ist ein details-Element, denn ein Menue, das ein Skript zum Oeffnen braucht, geht auf einer Seite ohne Skript nicht auf. "Seiten ohne Menue" war nicht moeglich - der Kopfbereich war ein Dokument fuer alle Seiten. Jetzt waehlt jede Seite: Standard, ein anderer Bereich, oder keiner. Dafuer musste die Regel "es gibt genau einen Kopf- und Fussbereich" fallen; sie war richtig, solange niemand waehlen konnte, und wurde falsch, sobald man waehlen kann. Ein bestehender Test, der diese Regel zusicherte, ist deshalb umgeschrieben und prueft jetzt die neue. Gespeichert wird die Wahl, nicht das Ergebnis: leer heisst Standard, none heisst keiner, sonst die Adresse. Ein Verweis auf einen geloeschten Bereich faellt auf den Standard zurueck, statt die Seite stillschweigend ohne Navigation auszuliefern. Neu im Ausbauplan: ein einzelnes install.php, das das Releasearchiv herunterlaedt und entpackt, damit niemand tausende Dateien per FTP hochladen muss. Mit den Regeln, die darueber entscheiden, ob das eine Hilfe oder eine Einladung ist: Adresse und SHA-256 stehen in der Datei und nicht im Formular, HTTPS mit Zertifikatspruefung, Schutz gegen ZIP-Slip, Selbstloeschung danach. 336 PHP-Tests / 1354 Assertions, 17 JS-Modelltests. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
67b85751cf |
Randlose Abschnitte, volle Bildschirmhoehe, Vollbild-Hero
Umuts Frage: "Haben wir bilder usw als volles bild startseite? 100% hoehe usw?" Die Teile gab es, die Kombination nicht - und zwei Sachen fehlten wirklich. Abschnittsbreiten: neu "randlos" (ohne Begrenzung, ohne Rand, von Kante zu Kante) und "breit" (1600 px) neben normal und schmal. Vorher war jeder Inhalt auf 1180 px begrenzt; ein Bild von Kante zu Kante war nicht moeglich. Hoeheneinheiten: neu dvh, svh, lvh. 100vh ist auf dem Handy hoeher als der Bildschirm - es meint die Ansicht ohne Adressleiste, und der untere Rand verschwindet darunter. 100dvh ist das, was jemand meint, der "volle Hoehe" sagt. Und eine Vorlage "Vollbild-Hero", die die ganze Kombination auf einen Klick setzt: randlos, 100dvh (mobil 80dvh), Inhalt senkrecht zentriert, Hintergrundbild formatfuellend, dunkle Ueberlagerung damit der Text lesbar bleibt, Ueberschrift, Text, Button. Die Teile waren alle da, aber diese Kombination zu finden war eine Recherche. 328 PHP-Tests / 1329 Assertions, 17 JS-Modelltests. Geprueft: vier Breiten angenommen und eine erfundene abgewiesen, sieben Hoehenangaben mit dvh/svh/lvh und zwei ungueltige, ein randloser Abschnitt mit formatfuellendem Bild, und die Hero-Vorlage Eigenschaft fuer Eigenschaft. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
464f52b147 |
Suchfeld im Designbereich, Sicherung als Arbeitspaket O
Neunzig Eigenschaften in acht zugeklappten Gruppen: "wo ist die Rahmenstaerke" ist eine berechtigte Frage. Jetzt filtert ein Suchfeld die Eigenschaften, oeffnet die passenden Gruppen und sagt, wie viele Treffer es gibt - und wenn keine, wo eigenes CSS zu finden ist. Getestet: "rahmen" laesst die Gruppen Rahmen und Bild stehen, 14 Treffer. Neu im Ausbauplan, Paket O: Sicherung und Wiederherstellung als Funktion statt als Disziplin. Heute entstehen Sicherungen nur als Nebenprodukt des Updaters und weil ich vor jeder Migration von Hand eine Kopie lege. Geplant sind Datenbank per VACUUM INTO statt copy (eine Kopie waehrend eines Schreibvorgangs kann unbrauchbar sein), Medienordner, ein Manifest mit Fassung, Migrationsstand und Pruefsummen - und ohne .env, weil darin APP_SECRET steht und eine Sicherung den Server verlaesst. Dazu Rotation, damit die Platte nicht vollaeuft und die naechste Sicherung nicht genau dann scheitert, wenn man sie braucht. Die Abnahme ist die Wiederherstellung, nicht die Sicherung: eine Seite loeschen, zurueckspielen, pruefen dass sie wieder da ist. Eine Sicherungsfunktion, deren Wiederherstellung nie gelaufen ist, ist eine Vermutung. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
806df4b5df |
Fassung 1.1.0
Designerausbau, Statistik, Updater, Einwilligung und Pflichtseiten seit 1.0.1. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>v1.1.0 |
||
|
|
7251b82f09 |
Designer: 93 Eigenschaften, neun Einblendungen, drei neue Bausteine
Umut fragte nach Zeilen, nach Rahmen und Rundungen - und ob der Designer so aufgestellt ist wie Flatsome. Der Vergleich steht in docs/DESIGNER-VERGLEICH.md, mit der Einschraenkung, dass Flatsome hier nicht installierbar war: das ist Wissen, keine Messung. Zwei echte Fehler kamen dabei heraus, beide vorher unbemerkt. Eine Rahmenstaerke je Seite wurde zu border-width-top. Das ist kein CSS, der Browser verwirft die Zeile stillschweigend - Rahmenstaerken je Seite hatten nie eine Wirkung, und es gab keine Meldung, die darauf hingewiesen haette. Die Schreibweise steht jetzt je Eigenschaft im Schema, weil padding-top dem Namen folgt und border-top-width nicht. Und eine Rundung auf einem Bildblock landete auf dem figure, waehrend das Bild darin eckig blieb. Eigenschaften koennen jetzt auf das Bild im Block zielen (target 'img' im Schema, eine zweite Regel im Compiler) - deshalb tut object-fit ueberhaupt etwas, denn auf einem figure tut es nichts. Von 50 auf 93 Eigenschaften: Bild (Ausschnitt, Bildmitte, Seitenverhaeltnis, Hoehe, Ecken, Rahmen), Positionierung mit z-index, getrennte Zeilen- und Spaltenabstaende, Flex je Element, Innen- und Textschatten, acht Bildfilter als eine filter-Deklaration in fester Reihenfolge, Mischmodus, Zusatzrahmen, Mauszeiger. Neun Einblendungen mit Verzoegerung, sieben Hover-Effekte, alle innerhalb von prefers-reduced-motion. Drei neue Bausteine (Dokumentschema v15): Symbol als eigenes Element, Fortschritt mit role=meter und dem Wert im Markup statt nur in der Balkenbreite, und ein Slider als Scrollbereich mit Einrasten - ohne JavaScript, ohne Autoplay, mit Finger, Trackpad, Mausrad und Tastatur. Zeilen waren nicht unauffindbar, sondern unbrauchbar leer: eine Zeile ohne Spalten sieht aus wie nichts. Jetzt legt "Zeile, 2/3/4 Spalten" beides auf einen Klick an, und im Werkzeugkasten steht, wie der Aufbau gemeint ist. 315 PHP-Tests / 1309 Assertions, 16 JS-Modelltests, axe auf dreizehn Bildschirmen ohne Verstoesse. 16 Datensaetze rechnen jede Eigenschaftsform gegen die erwartete Deklaration nach - die Pruefung, die die beiden Fehler oben gefunden haette, wenn es sie vorher gegeben haette. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
30d8d58bbf |
Updater am echten Repository durchgespielt
v1.0.0 gesetzt, die Installation darauf gestellt, v1.0.1 veröffentlicht und das Update ausgeführt: elf Schritte, alle ok, Sicherung mit cms.db und den Umgebungsdateien, Migration ohne Änderung, Rauchtest grün, danach VERSION 1.0.1 und die Website online. Der Wartungszustand ist einzeln geprüft - 503 mit Retry-After für die Website, 200 für die Verwaltung. Das steht so in QUALITY, mit den Zahlen und dem Pfad der Sicherung. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
5a8d67a638 |
Fassung 1.0.1: die laufende Fassung steht in der Verwaltung
Eine kleine, von außen sichtbare Änderung - sie ist der Prüfstein für das Update: nach dem Einspielen muss in der Seitenleiste 1.0.1 stehen, und der Weg dorthin muss die Schritte gegangen sein, die der Updater verspricht. Die Fassung kommt über eine Twig-Funktion in die Vorlage, nicht über einen globalen Dienst: die Vorlagen bekommen genau diese eine lesende Antwort und nicht einen Updater mit update() darauf. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>v1.0.1 |
||
|
|
52f0ab3807 |
Updater: neue Fassung über Git, mit Vorprüfung und Rückweg
Aus dem Plan in docs/UPDATE.md ist Code geworden: cms:update, cms:health, der Bildschirm "System" und der Wartungszustand. Die Vorprüfung ist die halbe Arbeit. Sie fragt nach proc_open, Git, sauberer Arbeitskopie, Herkunft, Schreibrechten und Platz - und danach, ob Datenbank und Medienordner wirklich von Git ausgenommen sind. Das ist der Punkt, an dem ein Update Inhalte zerstören könnte, also wird er geprüft und nicht angenommen. Jede Prüfung sagt, was zu tun ist, nicht bloß "fehlgeschlagen". Der Rückweg ist Teil des Wegs: scheitert ein Schritt, wird auf den vorherigen Commit zurückgesetzt. Die Datenbank nur dann zurückgeschrieben, wenn die Migration schon begonnen hatte - sonst verlöre der Rückweg Inhalte, die während des Updates entstanden sind. Antwortet der alte Stand im Rauchtest, geht die Website wieder online; antwortet er nicht, bleibt der Wartungszustand, weil eine kaputte Seite schlechter ist als eine ehrliche Meldung. Der Rauchtest läuft als eigener Prozess, denn nur ein frischer Prozess führt den neuen Code aus. Ein Test im laufenden Prozess hätte den alten geprüft und "alles in Ordnung" gemeldet. Kein symfony/process: der Runner sind dreißig Zeilen über proc_open mit dem Befehl als Array - kein Shell, nichts zu maskieren, und "proc_open ist abgeschaltet" wird die erste Antwort statt der Überraschung im dritten Schritt. 285 PHP-Tests / 1244 Assertions. Sechs davon fahren den Updater gegen echte Git-Repositorys in einem Temp-Verzeichnis, mit Platzhalterskripten für die zwei Befehle - inklusive des Fehlschlags, nach dem Code und Datenbank zurückgesetzt sein müssen. Nicht gegen dieses Projekt: ein Test, der die Arbeitskopie auscheckt, in der er läuft, ist ein Weg, Arbeit zu verlieren. Offen bleibt die Sicherung einer MySQL-Datenbank per mysqldump - dafür fehlt die Installation; der Updater sagt das im Schritt "Sicherung". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>v1.0.0 |