Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,22 @@ jobs:
working-directory: frontend
run: npm run build

- name: Install browser for production README smoke test
working-directory: frontend
run: npx playwright install --with-deps chromium

- name: Verify production README in Chromium
working-directory: frontend
run: |
npm run preview -- --host 127.0.0.1 --port 4184 --strictPort &
preview_pid=$!
trap 'kill "$preview_pid"' EXIT
for attempt in $(seq 1 30); do
if curl --fail --silent http://127.0.0.1:4184/ > /dev/null; then break; fi
sleep 1
done
npm run check:browser-runtime

# ============================================================================
# Docker Tests (matches test_docker.sh)
# ============================================================================
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ All notable changes to PrintOps will be documented in this file.
## Unreleased

### Fixed
- **Safari 16.0–16.3 File Manager loading (#144)** — Removed the GFM autolink-literal import that could prevent the lazy File Manager chunk from parsing. Tables, task lists, strikethrough, footnotes and explicit links remain available; bare URLs/emails now stay text. Production builds target Safari 16 and check emitted JavaScript, including the transformed PDF worker, for known incompatible syntax. PDF preview runtime support still requires a current browser; see [browser compatibility](docs/browser-compatibility.md).
- **AMS material names, colours and RFID tare weights stay consistent (#137)** — AMS writes now keep product and subtype labels for display while sending printer-supported material types, preserve preset filament types, normalize tray colours at the MQTT boundary, and retain assignments when normalized telemetry returns. Newly detected Bambu RFID spools use the named low-temperature core with its catalog link; a conservative one-time repair corrects only untouched auto-detected legacy rows and preserves manual edits.
- **FTPS retries and downloads remain bounded without wasting healthy work (#136)** — Explicit print and firmware uploads now make their own bounded connection attempts instead of spending every retry on a background handshake cooldown, while background cover and archive scans retain the cooldown guard. Slow downloads receive a capped size-based total budget in addition to the socket inactivity timeout, heavy 3MF transfers take turns per printer, timed-out path searches cooperatively stop their worker, and cover retries re-check the shared 3MF cache. Upload failures now distinguish TLS, authentication, network, path and SD-card/storage causes instead of blaming storage for every failure.
- **Open print batches keep their final reusable reprint template (#135)** — Deleting one queue item or clearing history now retains the last per-plate source an active batch needs to recreate outstanding runs, while fulfilled and cancelled batches remain cleanable. Already stranded batches identify affected plates, only offer dispatchable quantities, keep cancellation permission-aware, and no longer let one stranded plate block healthy plates in the same batch. Retained responses name the batch and reason; printer, AMS, plate and variant settings continue to be cloned from the preserved run.
Expand Down
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Screenshots gehören nicht in das Repository.
| Upstream | [H2C- und Home-Assistant-Funktionen 2026-08-27](upstream-h2c-home-assistant-evaluation-2026-08-27.md) | Gerätebestand, Sensorzustände, Interlock-Fallbacks und Folgeissues |
| Betrieb | [H2C-Nozzle-Mapping-Audit](h2c-nozzle-mapping-dispatch-audit.md) | Software-Sicherheitsgrenze und Hardware-Freigabenachweis für physische H2C-Düsen-IDs |
| Entwicklung | [README Editorial Guide](readme-editorial-guide.md) | Zielgruppen, Positionierung und Regeln für die zentrale Projekt-README |
| Browser | [Browser-Kompatibilität](browser-compatibility.md) | Safari-16-Syntaxbaseline, README-Markdown und Grenzen der PDF-Vorschau |

Die allgemeine Projektübersicht, Installation und erste Schritte stehen in der
[README im Projektstamm](../README.md).
Expand Down
86 changes: 86 additions & 0 deletions docs/browser-compatibility.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Browser-Kompatibilität

Aktuelle Browser bleiben für den vollständigen Funktionsumfang empfohlen.
Der JavaScript-Produktionsbuild hat eine explizite **Safari-/iOS-16.0-Syntaxbaseline**
(neben Chrome/Edge 111 und Firefox 114). Insbesondere darf der Dateimanager
unter Safari/iOS 16.0–16.3 nicht wegen des README-Markdown-Imports leer bleiben.
Das ist keine Zusage, dass sämtliche Browser-APIs, CSS-Effekte, Offline-Funktionen
oder gerätespezifischen Abläufe auf diesen alten Versionen unterstützt werden.

## Markdown im Dateimanager

Tabellen, Aufgabenlisten, Durchstreichung, Fußnoten und normales Markdown bleiben
erhalten. Unmarkierte URLs und E-Mail-Adressen erscheinen als Text. Für klickbare
Links `[Beschreibung](https://example.com)`, `<https://example.com>` oder
`<name@example.com>` verwenden. Raw-HTML wird nicht ausgeführt; die URL-Filterung
von ReactMarkdown und `noopener noreferrer` für Links bleiben erhalten.

Der Parser kombiniert die vier benötigten GFM-Erweiterungen direkt. Der
Autolink-Literal-Import aus `remark-gfm` entfällt: Er enthielt einen bereits beim
Laden ungültigen Lookbehind-Ausdruck. In PrintOps war davon der lazy geladene
Dateimanager betroffen, nicht der bereits funktionierende Login-Einstieg.

## PDF-Vorschau ist eine separate Laufzeitgrenze

Auch der PDF-Worker wird durch Vite übersetzt und auf Syntax geprüft, statt als
unveränderte `.mjs`-Datei kopiert zu werden. Das ergänzt **keine** fehlenden
Browser-APIs für PDF.js. Die Dokumentlayout-PDF-Vorschau benötigt weiterhin einen
aktuellen, von PDF.js unterstützten Browser; Safari 16 wird dafür nicht zugesagt.
Der bestehende Fehlerbereich der Vorschau schützt den übrigen Layouteditor.
Keine Änderungen an Belegberechnung, Berechtigungen oder PDF-Erzeugung im Backend.

## Reproduzierbare Prüfungen

Im Verzeichnis `frontend`:

```sh
npm ci
npm run build -- --outDir ./dist/browser-baseline
npm run preview -- --outDir ./dist/browser-baseline --host 127.0.0.1 --port 4184 --strictPort
```

Jeder Vite-Produktionsbuild prüft automatisch alle tatsächlich geschriebenen
`.js`- und `.mjs`-Dateien im gewählten Ausgabeverzeichnis, einschließlich Worker
und öffentlicher Assets. Die AST-Prüfung erkennt Lookbehind-Literale, statische
Klassenblöcke und RegExp-Unicode-Sets; Text/Kommentare werden nicht als Code
fehlinterpretiert. Fehlendes/leeres Ausgabe-JavaScript führt zum Fehler.
Dies ist ein gezielter Regressionswächter, kein vollständiger Safari-Parser oder
eine Prüfung dynamisch erzeugter regulärer Ausdrücke.

In einem zweiten Terminal, während die Vorschau läuft:

```sh
npx playwright install chromium
npm run check:browser-runtime
```

Der Check lädt den **gebauten** Dateimanager mit deterministischen lokalen
API-Testdaten bei 1440×1000 und 390×844, prüft Markdown und Link-/HTML-Schutz und
klappt die README zu und wieder auf. Relevante Konsolen-/HTTP-Fehler schlagen
fehl. Service Worker sind für die API-Fixtures ausgeschaltet; die erwarteten
WebSocket-Verbindungsfehler ohne Backend sind explizit ausgenommen. Der Check
läuft auch im CI-Job „Frontend Build“.

Für einen historischen Engine-Gegencheck kann eine **separat installierte**
Playwright-Version verwendet werden, ohne App-Abhängigkeiten zu downgraden:

```sh
BASELINE_ENGINE=webkit BASELINE_PLAYWRIGHT=/absolute/path/to/playwright-core npm run check:browser-runtime
```

Unter PowerShell die beiden Variablen mit `$env:BASELINE_ENGINE='webkit'` und
`$env:BASELINE_PLAYWRIGHT='C:/.../playwright-core'` setzen und danach denselben
npm-Befehl ausführen. `BASELINE_URL` überschreibt die lokale Vorschauadresse;
`BASELINE_SCREENSHOTS` speichert Bilder in einem vorhandenen Verzeichnis.

Validiert am 08.09.2026: WebKit 16.0 (Playwright 1.27.1, Build 1724, Windows) und
Chromium 149.0.7827.55. Derselbe alte Produktions-Dateimanager schlug in WebKit
mit `Invalid regular expression: invalid group specifier name` fehl; der
korrigierte Build besteht den README-Ablauf in beiden Engines und Viewports.
Das ersetzt keinen Test auf einem physischen iOS-Gerät. Bestehende mobile
Toolbar-Überbreite und Schrift-Rasterung der historischen Windows-Engine sind
nicht Teil dieser Parsefehler-Korrektur.

Referenzen: [Safari 16.4 / neue JavaScript-Syntax](https://webkit.org/blog/13966/webkit-features-in-safari-16-4/),
[Vite Build-Ziel](https://vite.dev/config/build-options.html#build-target),
[PDF.js Browser-Anforderungen](https://github.com/mozilla/pdf.js/wiki/Frequently-Asked-Questions).
23 changes: 22 additions & 1 deletion frontend/e2e/document-layout.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ async function installDocumentLayoutApi(page: Page, evidenceKind: EvidenceKind |
if (pathname === '/api/v1/auth/status') {
return respond(route, { auth_enabled: false, requires_setup: false });
}
if (pathname === '/api/v1/auth/encryption-status') {
return respond(route, {
key_configured: true, key_source: 'generated', decryption_broken: false, migration_error_count: 0,
legacy_plaintext_rows: { oidc_providers: 0, user_totp: 0 },
encrypted_rows: { oidc_providers: 0, user_totp: 0 },
});
}
if (pathname === '/api/v1/business-profiles/options') {
return respond(route, [{
id: 2,
Expand Down Expand Up @@ -238,7 +245,7 @@ async function installDocumentLayoutApi(page: Page, evidenceKind: EvidenceKind |
async function openWorkspace(page: Page) {
await page.goto('/settings?tab=orders-calculation&sub=format-preview');
await expect(page.locator('#document-layout-workspace')).toBeVisible();
await expect(page.locator('#document-layout-workspace').getByRole('heading', { name: /Format & Preview/i })).toBeVisible();
await expect(page.getByRole('heading', { name: /Format & Preview/i })).toBeVisible();
await expect(page.getByRole('img', { name: 'PDF page 1' })).toBeVisible();
}

Expand Down Expand Up @@ -293,6 +300,20 @@ test.describe('document layout desktop workflow', () => {
});
});

test('PDF preview survives native worker rejection using its module fallback', async ({ page }) => {
await page.addInitScript(() => {
window.Worker = class extends Worker {
constructor(...args: ConstructorParameters<typeof Worker>) {
super(...args);
this.terminate();
throw new Error('Native workers blocked by baseline test');
}
};
});
await installDocumentLayoutApi(page);
await openWorkspace(page);
});

test.describe('document layout mobile workflow', () => {
test.use({ viewport: { width: 390, height: 844 } });

Expand Down
148 changes: 10 additions & 138 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading