Commit Graph

9 Commits

Author SHA1 Message Date
Matt Kane 1c4d4f04b2 feat(core): expose outer user middleware hook (#2499)
* feat(core): wrap EmDash with user middleware

* fix(core): validate outer middleware config
2026-08-16 17:39:47 +01:00
Daniel 2b3741e3e0 test(e2e): give fixture post pages a head so component styles ship (#2415)
* test(e2e): give fixture post pages a head so component styles ship

The fixture's post page opens `<html>` and goes straight to `<body>`. Astro
has no head to inject into, so the page ships no styles at all: every scoped
style of the components it renders — `Comments`, `CommentForm` and the whole
Portable Text component tree — is dropped. Measured on the rendered page:
zero `<style>` tags and zero stylesheet links, while the elements still carry
their classes and Astro's scoping attribute.

That leaves public rendering untestable end to end. Components ship as source
and are compiled by the consuming site, so "the styles reach the page" is a
guarantee worth a test; the specs that already load this page assert text and
attributes only, and pass either way.

Add the head, and a spec that reads a component's applied style from the
browser so a regression in style delivery fails here instead of shipping.

* test(e2e): retry the cold public route before asserting styles

The spec navigated straight to the post page and asserted a computed style.
The workerd dev runner's Vite dep optimizer can transiently 500 a cold route
even after the global setup's warm-up, which covers the admin and content API
routes but not this public page. Playwright's assertion retry does not help
there: once the navigation lands on an error page the element never appears,
so the page has to be reloaded.

Wrap the navigation in the same reload loop the sibling specs use.

---------

Co-authored-by: Matt Kane <mkane@cloudflare.com>
2026-08-13 10:15:12 +01:00
Daniel 5a5adb79d2 fix(core): make editor text alignment render on public pages (#2410)
* fix(core): make editor text alignment render on public pages

* test(core): prove alignment CSS reaches a rendered page

The repro test asserted Astro's `data-astro-cid-*` scoping attribute as a
stand-in for "the alignment rules ship and apply". That proxy cannot fail on
the regression it guards: the attribute is stamped whenever the component
carries any scoped style, so deleting or mistyping the rules keeps it green.
The container API cannot do better — `renderToString` emits markup only, and
the compiled style module resolves to an empty string under the repro config.

Move the CSS claim to the level that can see it. A fixture page renders a
Portable Text value through the public component tree, and an e2e spec reads
the computed alignment from the browser. The repro test keeps the part it can
prove on its own: the class the Block override emits per `textAlign`.

The fixture page carries its own markup instead of a seeded entry so the
suite's shared content stays untouched, which also keeps the admin
visual-regression baselines unchanged.

Drop the comments flagged in review and lower the changeset to the effect a
reader upgrading the package can observe.
2026-08-12 10:44:21 +01:00
Scott Buscemi 534f23884f fix(ui): move Comments/CommentForm to emdash/ui/comments subpath (#2039) (#2044)
* fix(ui): move Comments/CommentForm to emdash/ui/comments subpath (#2039)

Their <style> blocks were pulled into a shared, render-blocking CSS chunk
on every page that imported anything from the emdash/ui barrel (e.g.
PortableText), because Astro scans the whole barrel module graph. Splitting
them into a dedicated entry point keeps comment CSS off pages that don't
render comments, mirroring the existing emdash/ui/search entry point.

* fix(ui): keep barrel Comments exports as deprecated (#2039)

Address ascorbic review: add emdash/ui/comments without breaking existing
emdash/ui imports. Mark barrel re-exports @deprecated (remove in 1.0),
allowlist the subpath in the public-source guard, and sync template skills.
2026-08-08 11:39:42 +01:00
Matt Kane a623c6b7db fix(media): optimize storage-backed images behind Cloudflare Access (#1549)
Wrap Astro's image endpoint so EmDash media bytes are read straight from
the storage adapter instead of being fetched over HTTP. The stock endpoint
fetches the (absolute) media URL to load the source; on Cloudflare that is a
self-subrequest that fails behind Access / global_fetch_strictly_public,
404ing from /_image. The wrapped endpoint matches the internal media route by
pathname, reads bytes from storage (no fetch), and transforms them with sharp
(Node) or the IMAGES binding (Cloudflare); everything else delegates to the
stock endpoint unchanged.

On by default where the image service is local; opt out with images: false.
2026-06-22 07:49:33 +01:00
Matt Kane 85f2d9fbfd test(e2e): Cloudflare/workerd e2e harness — fixture + target parametrization (#1320)
* test(e2e): add minimal Cloudflare adapter fixture

Mirrors e2e/fixture but swaps the Node adapter + SQLite for the Cloudflare
adapter + D1/R2, so astro dev runs the workerd SSR module runner. Foundation
for a Cloudflare e2e lane that catches workerd-only regressions (#1292 class).

* test(e2e): parametrize harness for the Cloudflare target

EMDASH_E2E_TARGET=cloudflare boots e2e/fixture-cloudflare under astro dev
(workerd) instead of the Node fixture. Gate setup on dev-bypass actually
returning 200 rather than the server merely responding -- the Cloudflare dev
runner's Vite dep optimizer 500s on cold start until it finishes pre-bundling.
Clear miniflare D1/R2 state per run for isolation. Existing specs run
unmodified against both targets.

* test(e2e): address review — track CF seed, fix teardown/markers, seed content server-side

Review findings on #1320:
- Commit the CF fixture's .emdash/seed.json (it was gitignored, so the fixture
  silently fell back to the default seed in a fresh checkout). Un-ignore the dir.
- global-teardown cleaned only the Node fixture path; use info.workDir so the CF
  fixture's .astro/.wrangler/.emdash artifacts are cleaned too.
- ensureFixtureDepsBuilt gated on a single marker; check all required artifacts
  per target (cloudflare + plugin-color), else a half-built tree boots a broken
  fixture.

Root-cause fix for cold-start seeding: content seeding hand-rolled per-item API
POSTs, each the first hit to a route the workerd dev runner hadn't compiled —
racing the Vite optimizer and 500ing on a cold cache. Move the plain posts/pages
into the seed file's content block (applied server-side during dev-bypass) and
resolve their ids by slug (the list GET warms the content route before the one
remaining dynamic flow, the media upload + image post). Drop the CF fixture's
astro build script (it polluted the dev run) and give the slower workerd target
a 90s test timeout.

CF: content-types 11/11 warm and green cold; node: content-types 11/11, search
20/20.

* ci: add Cloudflare/workerd e2e smoke job

Runs the content-types spec against EMDASH_E2E_TARGET=cloudflare so the foundation
is actually exercised on every PR, not dormant. Single job (no sharding) scoped to
one spec that drives the admin SPA, schema CRUD, and seeded content end-to-end on
the workerd runtime. Broad sharded coverage + paths-gating is a follow-up.

* test(e2e): warm the admin's data routes before specs run

CI's slower 2-core runner exposed a cold-start gap: the content-types page's
client-side fetch to /_emdash/api/schema/collections hit that route cold, the
workerd optimizer served a 500, and the admin rendered an empty table — failing
the first specs (even on retry, since the route was still compiling). idsBySlug
warmed the content routes but not the schema/media routes. Warm those (authed)
to a 200 before tests start, so the browser's first fetches don't race the
optimizer.
2026-06-03 23:14:12 +01:00
seslly d2114523a5 fix: passkeys behind TLS reverse proxy (#225)
* fix: passkeys behind TLS reverse proxy

Add passkeyPublicOrigin and wire it through passkey routes so origin/rpId match
the browser when dev runs behind nginx. Expose dev-only /_emdash/api/dev/passkey-url,
add admin messaging for insecure WebAuthn contexts, nginx repro under demos/simple,
and direct kysely dependency for the simple demo Node adapter bundle.

Made-with: Cursor

* docs: add passkeyPublicOrigin to configuration reference

Adds the new passkeyPublicOrigin option and reverse proxy guidance
to the public-facing configuration docs as requested in PR review.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* update tests and more docs

* fix: add missing refresh-server-pat fixture and restore docs heading

---------

Co-authored-by: Joseph Eftekhari <jdeftekhari@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 07:41:07 +01:00
Matt Kane 2e863566b3 Fix scope 2026-04-01 10:58:32 +01:00
Matt Kane 43fcb9a131 first commit 2026-04-01 10:44:22 +01:00