Files
Teffen Ellis 220eb26e5f web: MDX without React (#21949)
* packages/theme: add the @goauthentik/theme design-system package (#23341)

* packages/fonts: add @goauthentik/fonts package

Extract the bundled web fonts out of web/ into a dedicated
@goauthentik/fonts workspace package: the RedHat variable faces, the
PatternFly pficon icon face, and the FontAwesome Free solid face, each
with its upstream license recorded under licenses/.

web/ now pulls the faces and icons from the package's
@goauthentik/fonts/faces.css and @goauthentik/fonts/icons.css entry
points instead of the old #fonts/* import and the inlined pficon.scss
vendor sheet.

Anchor esbuild's [dir] at the monorepo root via outbase so assets pulled
from the out-of-web package no longer resolve to a "_.._" segment, which
Go's //go:embed silently drops from the embedded outpost build.

Co-Authored-By: Ken Sternberg <ken@goauthentik.io>

* packages/theme: add @goauthentik/theme design-system package

Add @goauthentik/theme, which defines authentik's design tokens (color,
typography, fonts, spacing, shape, shadow, motion, z-index) in TypeScript
and builds them into CSS via styleframe.

Token names carry a distinct separator per category so the token type is
recoverable from the name alone. That is worth the verbosity: it keeps
the DX legible and leaves room for automatic theme management and future
tooling built on top of the token set.

Co-Authored-By: Ken Sternberg <ken@goauthentik.io>

* web/theme: add a demo page for the theme tokens

Add a self-contained demo page, built by build-demo.mjs, that renders
every theme token — colors, typography, spacing, shape, shadow, motion —
so the design system can be eyeballed in isolation while it evolves.

Co-Authored-By: Ken Sternberg <ken@goauthentik.io>

* Heal lockfile.

* Fix spelling.

* Fix grouping.

---------

Co-authored-by: Ken Sternberg <ken@goauthentik.io>

* web/elements/ak-mdx: drop React + runtime MDX eval, use unified pipeline

Replace `@mdx-js/mdx`'s `evaluate`/`run` (which depends on `'unsafe-eval'`
in the page CSP) with a pure `unified`/remark/rehype pipeline. URL-mode
content now arrives from the build-time `mdx-plugin` as pre-rendered HTML
and is stamped through a Trusted Types passthrough policy
(`CompiledMarkdownTrustPolicy`) so admin-side custom elements like
`<ak-alert>` and `<ak-md-a>` survive. Content-mode (admin-supplied
markdown) is compiled in-browser via `compileRuntimeMarkdown` and routed
through the existing `BrandedHTMLPolicy` (DOMPurify).

`<ak-md-a>` replaces the React `MDXAnchor`/`MDXWrapper` pair: a tiny Lit
custom element with `display: contents` that intercepts in-doc fragment
clicks for shadow-root scrolling. The remark plugins gain `caution` and
`tip` admonition types and promote `:::name[Title]` directive labels to
`<strong>`. `one-dark.css` learns `:host` so syntax-highlighted code
blocks inherit the palette inside `<ak-mdx>`'s shadow tree.

Removes `@mdx-js/mdx`, `react`, `react-dom`, `rehype-mermaid`, and
`remark-mdx-frontmatter`. Adds `unified`, `remark-parse`, `remark-rehype`,
and `mdast-util-to-string`.

Co-Authored-By: Agent <279763771+playpen-agent@users.noreply.github.com>

* web/bundler/mdx-plugin: pre-render markdown to HTML at build time

Compile each `.md` / `.mdx` file through a build-time `unified` pipeline
(remark-parse, GFM, frontmatter, directives, custom admonition/headings/
lists transforms; rehype-rehype, anchor wrapping, syntax highlighting,
mermaid extraction) and emit a JSON envelope of
`{ content: HTML, frontmatter, publicPath, publicDirectory }`. The
on-load result still ships via the `file` loader so the runtime side
keeps its existing fetch path. The compiled HTML uses `<ak-md-a>` and
`<ak-alert>` custom elements so `<ak-mdx>` can stamp it directly into
shadow DOM with no client-side JavaScript evaluation.

Plugin is split across four sibling files (`node.js`, `compile.js`,
`remark.js`, `rehype.js`) so each concern lives in its own module. The
title/wrapper HTML is built as a hast tree and serialized through
`hast-util-to-html` rather than string-concatenated, dropping the
hand-rolled `escapeHTML` helper and unifying escape semantics with the
rest of the document.

Co-Authored-By: Agent <279763771+playpen-agent@users.noreply.github.com>

* web/test: e2e ak-mdx pipeline via OAuth2 provider docs

The OAuth2 provider docs page exercises the full pipeline in one place:
frontmatter title, multiple H2 slugs, `:::caution`/`:::info` admonitions
(with and without titles), relative-doc links, external links, and an
embedded mermaid sequence diagram. Tests boot the admin UI, provision a
fresh OAuth2 provider, navigate to its view page, and assert against the
compiled DOM inside `<ak-mdx>`'s shadow root.

Co-Authored-By: Agent <279763771+playpen-agent@users.noreply.github.com>

* web/elements/ak-mdx: sanitize replacer output, note pipeline drift

Address PR review feedback on the URL-mode trust boundary. `<ak-mdx>`'s
`replacers` hook runs over pre-rendered build-time HTML before it is
stamped into the DOM, and consumers (e.g. `ProxyProviderViewPage`) splice
admin-controlled values such as `provider.externalHost` into it. The old
React pipeline ran replacers on raw markdown that was then compiled, so
those values were HTML-escaped on serialization; the new URL mode passed
the post-replacer HTML straight through, dropping that guarantee.

Replace the passthrough `CompiledMarkdownTrustPolicy` with
`CompiledMarkdownSanitizePolicy`: a DOMPurify policy that whitelists the
custom elements (`<ak-alert>`, `<ak-md-a>`, `<ak-diagram>`) and the
`part`/`level` attributes our pipeline emits, and strips anything else a
replacer could inject.

Also add a reciprocal drift note to the runtime `markdown.ts` pointing at
`bundler/mdx-plugin/`, mirroring the existing note on the bundler side.

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

* Fix anchor slugification.

* Spellcheck.

---------

Co-authored-by: Ken Sternberg <ken@goauthentik.io>
Co-authored-by: Agent <279763771+playpen-agent@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-24 22:55:37 +01:00
..
2026-08-24 22:55:37 +01:00