Sechs Erkenntnisse aus einem Ticketdurchlauf einarbeiten
Upgrade-Skill 1.3 - neuer Step 9b: die uebrig gebliebenen sys_template- Datensaetze loeschen. "Via site sets, not sys_template" liest sich wie "die Tabelle ist erledigt", aber v14 wertet sie weiter aus (TCA in cms-frontend, PageInformationFactory ruft getSysTemplateRowsByRootline). Ein Alt-Template mit clear=3 OBERHALB des Site-Roots loescht Constants und Setup, also auch das Set-TypoScript - und zwar nur fuer Code, der das FE-TypoScript im Backend mit eigener Rootline neu aufbaut, weil der Core die Rootline am Site abschneidet. Symptome sehen unverwandt aus (fehlende FormEngine-Platzhalter, leere Template-Layout-Listen, nicht erscheinende FlexForm-Sheets), Kennzeichen ist: Frontend richtig, Backend falsch. Mit den drei Pruefungen, die das Loeschen vorher absichern, und Soft-Delete statt DELETE. Design-Parity 1.9 - drei Punkte: - Vergleichsschleife: um zu belegen, dass ein Eingriff das Frontend NICHT veraendert, muss vor dem Diff das Render-Rauschen weggefiltert werden (picture-/img-Hashes, CSS-mtime), sonst weicht jede Seite ab und der Beweis faellt aus. - Neuer Abschnitt zum Backend-Formular mit Playwright: es steckt in einem iframe (und der naheliegende Frame-Filter erwischt den Hauptframe mit), innerText ist in inaktiven Tabs LEER, auf den eigenen field-item eingrenzen, Tab-Aktivierung ist unzuverlaessig, den SAVE testen - und die UI-Reichweite einer Aenderung an einer FormEngine-Renderbedingung vorher/nachher zaehlen (aus 9 Schaltern wurden unbemerkt 83). - Settings: Booleans in settings.yaml gehoeren in Anfuehrungszeichen. YAML true wird zum Constant "1", YAML false zu einem LEEREN Constant; das Frontend ueberlebt es, der Backend-Platzhalter nicht. Deploy-Skill 1.3 - die dort empfohlene Form MYSQL_PWD="$(cat …)" wird fuer Schreibzugriffe regelmaessig blockiert. Durchgegangen ist ein Skript, das das Passwort selbst aus DBPASSFILE liest, sodass nur ein Pfad in der Kommandozeile steht. Dazu: solche Skripte gezielt und idempotent auf dem aktuell gespeicherten Stand arbeiten lassen statt ein vorbereitetes Blob zurueckzuschreiben, sonst ueberfaehrt man den parallelen Save eines Redakteurs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
---
|
||||
name: typo3-t3bootstrap-live-design-parity
|
||||
description: "Match a TYPO3 v14 t3bootstrap-based build (local DDEV) to a reference LIVE site page by page — the frontend/design phase after a v11->v14 upgrade. Use when making an upgraded TYPO3 site look like its old/live counterpart, when doing per-page visual parity against a reference URL, when content that exists in the DB isn't rendering after a v11->v14 migration, or when customizing a t3bootstrap sitepackage's templates/SCSS/settings. Covers: the Playwright compare loop (computed style + CSS rule), the settings-vs-SCSS decision, the t3b_core spacing system (spacing.yaml / tx_t3b_spacing) and why spacing must never be fixed in SCSS, recurring structural fixes (stranded colPos, missing templateLayout partials, template partialRootPaths precedence/shadowing, on-demand component CSS, unregistered CTypes), a full visual-parity checklist (layout/width, typography, colors, links/buttons, equal-sizing, icons, borders, footer, header/nav, hero carousel incl. why Bootstrap autoplay cannot be switched off via the interval), diagnosing regressions caused by an editor's SAVE (CKEditor dropping undeclared classes, FlexForm selects with no empty item flipping to "yes"), and cache-safe techniques (full-bleed bands, image-border restyle, responsive crop variants, client-side randomisation, FAL-via-DataHandler). Assumes the site already boots on v14 (see the v11->v14 upgrade skill)."
|
||||
description: "Match a TYPO3 v14 t3bootstrap-based build (local DDEV) to a reference LIVE site page by page — the frontend/design phase after a v11->v14 upgrade. Use when making an upgraded TYPO3 site look like its old/live counterpart, when doing per-page visual parity against a reference URL, when content that exists in the DB isn't rendering after a v11->v14 migration, or when customizing a t3bootstrap sitepackage's templates/SCSS/settings. Covers: the Playwright compare loop (computed style + CSS rule, and how to prove a change did NOT alter the frontend), driving the BACKEND record form/FormEngine with Playwright (it lives in an iframe; innerText is empty in inactive tabs), the settings-vs-SCSS decision incl. why settings.yaml booleans must be quoted strings, the t3b_core spacing system (spacing.yaml / tx_t3b_spacing) and why spacing must never be fixed in SCSS, recurring structural fixes (stranded colPos, missing templateLayout partials, template partialRootPaths precedence/shadowing, on-demand component CSS, unregistered CTypes), a full visual-parity checklist (layout/width, typography, colors, links/buttons, equal-sizing, icons, borders, footer, header/nav, hero carousel incl. why Bootstrap autoplay cannot be switched off via the interval), diagnosing regressions caused by an editor's SAVE (CKEditor dropping undeclared classes, FlexForm selects with no empty item flipping to "yes"), and cache-safe techniques (full-bleed bands, image-border restyle, responsive crop variants, client-side randomisation, FAL-via-DataHandler). Assumes the site already boots on v14 (see the v11->v14 upgrade skill)."
|
||||
metadata:
|
||||
author: Wappler
|
||||
version: "1.8"
|
||||
version: "1.9"
|
||||
---
|
||||
|
||||
# TYPO3 v14 t3bootstrap — live-design parity
|
||||
@@ -77,10 +77,50 @@ placeholders below from the site you're matching; keep a per-project log of what
|
||||
it decides whether anything you measure afterwards means something. `curl` is NOT a substitute
|
||||
behind HTTP basic auth (staging) — it returns 401 while the browser holds the credentials.
|
||||
Test behaviour only after that fetch and the DOM agree.
|
||||
- **To prove a change did NOT alter the frontend, diff the HTML — but normalise the per-render noise
|
||||
first.** TYPO3 emits values that differ on every render, so a raw `diff` reports every page as
|
||||
changed and the proof evaporates: `id="picture-<hash>"` / `id="img-<hash>"` on responsive images
|
||||
(regenerated per render), and the `?<mtime>` on `main.css`/`fonts.css` after any `cache:flush`
|
||||
recompile. Filter those, then diff:
|
||||
```
|
||||
norm() { sed 's|/typo3temp/assets/css/[^"]*|CSS|g; s|picture-[0-9a-f]*|P|g; s|img-[0-9a-f]*|I|g'; }
|
||||
diff <(norm < before.html) <(norm < after.html) && echo "identisch"
|
||||
```
|
||||
Capture the "before" over **several** pages (a content page, the home page, one with news teasers)
|
||||
before touching anything — after the change it is too late. This is the evidence that turns "I
|
||||
think nothing broke" into "4 pages byte-identical".
|
||||
2. With `browser_evaluate`, capture the real element's **computed style AND its explicit CSS rule**
|
||||
(getComputedStyle + walk `document.styleSheets` for the selector). Don't assume inheritance.
|
||||
3. Diff vs DDEV → decide **setting vs SCSS** (below) → apply → flush → re-screenshot → verify.
|
||||
|
||||
## Driving the BACKEND with Playwright (FormEngine)
|
||||
Sooner or later the question is "what does the editor actually see in this field?" — the record form is
|
||||
a different beast from the frontend, and four things silently produce wrong measurements. Each of these
|
||||
cost a wasted measurement round:
|
||||
- **⚠ The record form lives in an `iframe`.** `document.querySelectorAll(...)` on the main document
|
||||
returns **0 fields** and looks like an empty form. Use `page.frames()`. And beware the obvious
|
||||
selector: `page.frames().find(f => f.url().includes('record/edit'))` matches the **main** frame too,
|
||||
because the outer URL contains that path — pick `f => f !== page.mainFrame()` instead.
|
||||
- **⚠ `innerText` returns EMPTY for anything in an inactive FormEngine tab.** FlexForm sheets are tabs,
|
||||
so every field outside the active one reads as blank — which looks exactly like "no label / no hint
|
||||
rendered". Use **`textContent`**, which ignores visibility. (`offsetParent === null` likewise only
|
||||
means "its tab isn't open", not "hidden".)
|
||||
- **Scope to the field's own `.t3js-formengine-field-item`.** Walking up to a parent to find some text
|
||||
pulls in the neighbouring fields' hints and produces confident nonsense (a hint from the field *above*
|
||||
attributed to this one).
|
||||
- **Activating a tab is unreliable.** `getByRole('tab', {name})` timed out and a JS `.click()` on
|
||||
`[role="tab"]` did nothing on v14. Don't fight it: read via `textContent` regardless of the active
|
||||
tab. Buttons work normally — `button[name="_savedok"]` is Save.
|
||||
- **Test the SAVE, not just the render**, whenever the concern is "does the stored configuration
|
||||
survive?" Press Save in the real form, then check the DB and the frontend. That is the only test that
|
||||
reproduces what an editor does, and it is where FlexForm bugs actually surface.
|
||||
- **⚠ Count the affected widgets BEFORE and AFTER changing a FormEngine element's render condition.**
|
||||
These blocks often render more than they appear to — a placeholder block can also carry the nullable
|
||||
"Set element specific value" toggle, so a change to *when* it renders silently adds or removes that
|
||||
control. A one-line fix of mine turned 9 toggles into **83** (and the naive variant would have removed
|
||||
all 9); only counting `.t3js-form-field-eval-null-placeholder-checkbox` in the real form before and
|
||||
after revealed it. Then choose the variant that keeps the previous footprint.
|
||||
|
||||
## When the report is a rendering artefact, not a defect
|
||||
Some "it looks broken" reports are sub-pixel rasterisation: a hairline that washes out, a circle whose
|
||||
cap renders as a straight edge, an outline that vanishes. They are **display-dependent**, which is why
|
||||
@@ -106,6 +146,15 @@ one person sees them and another does not, and why they come and go with the zoo
|
||||
a bug fix. Do not ship a change that your own numbers say is not an improvement.
|
||||
|
||||
## Settings vs SCSS decision
|
||||
- **⚠ Write booleans in `settings.yaml` as QUOTED STRINGS, not YAML booleans.** Site settings arrive in
|
||||
TypoScript as constants, and the conversion is lossy: YAML `true` becomes the constant **`"1"`** and
|
||||
YAML `false` becomes an **EMPTY** constant. The frontend usually survives that (a falsy check, or an
|
||||
extension mapping `'true'`/`'false'` to real booleans), so it looks fine and the bug hides in the
|
||||
backend: an option field whose items are the strings `true`/`false` can no longer match the constant,
|
||||
so its "Default: …" hint shows `Default: "1"` — or, for the empty case, matches the FIRST item and
|
||||
claims `Default: "Default"`. With `'true'` / `'false'` the mapping works and the hint reads
|
||||
`(Default: "Yes"/"No")`, with identical frontend output. Applies to any `plugin.tx_*` value you set
|
||||
through `settings.yaml`, not just declared theme settings.
|
||||
- **Setting** (`config/sites/<SITE_ID>/settings.yaml`) for anything mapped in the theme's
|
||||
`Configuration/TypoScript/Plugin/Setup/tx_wsscss.typoscript`: `design.color.{primary,secondary,
|
||||
body-color,headings-color,header-bg,page-bg,footer-bg,footer-color,footer-headline-color,…}`,
|
||||
|
||||
Reference in New Issue
Block a user