# Newsletter rendering

WUK newsletters are authored as normal TYPO3 pages (under the newsletter /
presse roots, where `config.isWukNewsletter = 1` is set in TypoScript). The
Fluid templates emit **Foundation-for-Emails "Inky"** component tags
(`<container>`, `<row>`, `<columns>`, `<button>`, `<spacer>`, `<callout>`,
`<wrapper>`). Those tags are turned into inlined, email-safe table markup at
request time.

## Pipeline (pure PHP, no Node)

`ContentPostProcessMiddleware` intercepts the rendered response of a newsletter
page and hands it to `NewsletterRenderer`, which:

1. **Normalises links** — `cleanUpHashLinks()` (strip domain from in-page
   anchors) and `prefixLinks()` (root-relative → `https://www.wuk.at`).
2. **Transforms Inky tags → tables** — `Newsletter\Inky\InkyTransformer`, a
   faithful native-`ext-dom` port of ZURB Inky 1.3.x (no third-party parser).
3. **Inlines CSS** — [`pelago/emogrifier`](https://github.com/MyIntervals/emogrifier)
   inlines the compiled stylesheet and keeps `@media` rules in a `<style>`
   block.

The result is cached on disk under `public/newsletter-tpl/dist/`, keyed by page
uid + `SYS_LASTCHANGED`. The cache is busted for `?no_cache=1` and for logged-in
backend users. Rendering failures are logged and re-thrown — a broken newsletter
fails loudly rather than being served as raw Inky markup.

This replaced the previous per-request `npm run build` (Gulp + Babel + node-sass
+ inky + inline-css + siphon + htmlmin), which required Node on the server, a
temp-file round-trip, a `chdir()`, and did not run on Apple Silicon.

## The stylesheet is a committed build artefact

The renderer inlines `public/newsletter-tpl/css/app.css`. **That file is
compiled from `public/newsletter-tpl/src/assets/scss/` with Dart Sass and is
committed to git** — the production server has no Node and cannot compile it.

> **If you change the newsletter SCSS, run `npm run build` in
> `public/newsletter-tpl` (Node 22) and commit the regenerated `css/app.css` in
> the same commit.** Otherwise the SCSS change has no effect in production and
> you silently ship stale styles.

See `public/newsletter-tpl/README.md` for the build.

## Dependencies

Only `pelago/emogrifier` (declared in this extension's `composer.json`), which
needs `ext-dom`, `ext-mbstring`, `ext-libxml` — all already required by TYPO3.
No PHP extension beyond TYPO3's baseline, and no runtime Node.

## Email size / Gmail clipping

Gmail clips messages over ~102 KB. About half of the existing newsletters
already exceed this (the weight is inline-style duplication across hundreds of
table cells, not the stylesheet). This pre-dates the pure-PHP rework — which is
in fact ~5 % smaller than the old output — and genuinely fixing it would require
reducing per-element inline-style duplication in the templates. Tracked
separately.
