From c04d163a27daee43ba42d2778b7f11240329a18a Mon Sep 17 00:00:00 2001 From: Teffen Ellis Date: Tue, 28 Oct 2025 06:35:39 +0100 Subject: [PATCH 1/2] web: Render Markdown in Blueprints. --- web/src/admin/blueprints/BlueprintListPage.ts | 26 ++++++++++++------- web/src/elements/ak-mdx/ak-mdx.tsx | 4 +-- .../elements/ak-mdx/components/MDXWrapper.tsx | 12 +++++++-- web/src/elements/table/Table.css | 8 ++++++ 4 files changed, 36 insertions(+), 14 deletions(-) diff --git a/web/src/admin/blueprints/BlueprintListPage.ts b/web/src/admin/blueprints/BlueprintListPage.ts index d7341351738a..00f7a5903751 100644 --- a/web/src/admin/blueprints/BlueprintListPage.ts +++ b/web/src/admin/blueprints/BlueprintListPage.ts @@ -7,6 +7,7 @@ import "#elements/forms/DeleteBulkForm"; import "#elements/forms/ModalForm"; import "#elements/tasks/TaskList"; import "@patternfly/elements/pf-tooltip/pf-tooltip.js"; +import "#elements/ak-mdx/ak-mdx"; import { DEFAULT_CONFIG } from "#common/api/config"; import { EVENT_REFRESH } from "#common/constants"; @@ -44,6 +45,16 @@ export function BlueprintStatus(blueprint?: BlueprintInstance): string { return msg("Unknown"); } +const BlueprintDescriptionProperty = "blueprints.goauthentik.io/description"; + +export function formatBlueprintDescription(item: BlueprintInstance): string | null { + const { labels = {} } = (item.metadata || {}) as { + labels?: Record; + }; + + return labels[BlueprintDescriptionProperty] || null; +} + @customElement("ak-blueprint-list") export class BlueprintListPage extends TablePage { protected override searchEnabled = true; @@ -133,18 +144,13 @@ export class BlueprintListPage extends TablePage { } row(item: BlueprintInstance): SlottedTemplateResult[] { - let description = undefined; - const descKey = "blueprints.goauthentik.io/description"; - if ( - item.metadata && - item.metadata.labels && - Object.hasOwn(item.metadata?.labels, descKey) - ) { - description = item.metadata?.labels[descKey]; - } + const description = formatBlueprintDescription(item); + return [ html`
${item.name}
- ${description ? html`${description}` : nothing}`, + ${description + ? html`` + : nothing}`, html`${BlueprintStatus(item)}`, Timestamp(item.lastApplied), html``, diff --git a/web/src/elements/ak-mdx/ak-mdx.tsx b/web/src/elements/ak-mdx/ak-mdx.tsx index 76eb96534094..6905797a3f41 100644 --- a/web/src/elements/ak-mdx/ak-mdx.tsx +++ b/web/src/elements/ak-mdx/ak-mdx.tsx @@ -1,6 +1,7 @@ import "#elements/Alert"; import { globalAK } from "#common/global"; +import { BrandedHTMLPolicy } from "#common/purify"; import OneDark from "#common/styles/one-dark.css"; import { MDXAnchor } from "#elements/ak-mdx/components/MDXAnchor"; @@ -98,7 +99,7 @@ export class AKMDX extends AKElement { nextMDXModule = await fetchMDXModule(pathname); } else { nextMDXModule = { - content: this.content || "", + content: `${BrandedHTMLPolicy.createHTML(this.content || "")}`, }; } @@ -144,7 +145,6 @@ export class AKMDX extends AKElement { }); const { frontmatter = {} } = mdxExports; - this.#reactRoot.render( { const nextChildren = React.Children.toArray(children); if (title) { - nextChildren.unshift(

{title}

); + nextChildren.unshift( +

+ {title} +

, + ); } - return
{nextChildren}
; + return ( +
+ {nextChildren} +
+ ); }; diff --git a/web/src/elements/table/Table.css b/web/src/elements/table/Table.css index e96a3a9e1297..7844eec5c59d 100644 --- a/web/src/elements/table/Table.css +++ b/web/src/elements/table/Table.css @@ -10,6 +10,14 @@ } } +td.pf-c-table__toggle:first-child > .pf-c-button { + --pf-c-button--PaddingLeft: 0; +} + +td ak-mdx::part(content) { + --pf-c-content--FontSize: 1em; +} + /** * TODO: Row actions need a better approach to alignment, * but this will at least get the buttons in a grid-like layout. From 3947052ad83618a11ed92ceffb17360034a3a0e6 Mon Sep 17 00:00:00 2001 From: Teffen Ellis Date: Thu, 30 Oct 2025 15:50:32 +0100 Subject: [PATCH 2/2] web: Add MDX rendering to user notes. --- web/src/admin/groups/GroupViewPage.ts | 7 +++++-- web/src/admin/users/UserViewPage.ts | 5 +++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/web/src/admin/groups/GroupViewPage.ts b/web/src/admin/groups/GroupViewPage.ts index ecf572b6b058..65064c47b530 100644 --- a/web/src/admin/groups/GroupViewPage.ts +++ b/web/src/admin/groups/GroupViewPage.ts @@ -8,6 +8,7 @@ import "#elements/Tabs"; import "#elements/buttons/ActionButton/index"; import "#elements/buttons/SpinnerButton/index"; import "#elements/forms/ModalForm"; +import "#elements/ak-mdx/ak-mdx"; import { DEFAULT_CONFIG } from "#common/api/config"; import { EVENT_REFRESH } from "#common/constants"; @@ -159,8 +160,10 @@ export class GroupViewPage extends AKElement { >
${msg("Notes")}
- ${Object.hasOwn(this.group?.attributes || {}, "notes") - ? html`${this.group.attributes?.notes}` + ${this.group?.attributes?.notes + ? html`` : html`

${msg( diff --git a/web/src/admin/users/UserViewPage.ts b/web/src/admin/users/UserViewPage.ts index 3abebeef7fef..bb665eb1df8c 100644 --- a/web/src/admin/users/UserViewPage.ts +++ b/web/src/admin/users/UserViewPage.ts @@ -23,6 +23,7 @@ import "#elements/user/UserConsentList"; import "#elements/user/UserReputationList"; import "#elements/user/sources/SourceSettings"; import "./UserDevicesTable.js"; +import "#elements/ak-mdx/ak-mdx"; import { DEFAULT_CONFIG } from "#common/api/config"; import { EVENT_REFRESH } from "#common/constants"; @@ -420,8 +421,8 @@ export class UserViewPage extends WithCapabilitiesConfig(AKElement) { >

${msg("Notes")}
- ${Object.hasOwn(this.user?.attributes || {}, "notes") - ? html`${this.user.attributes?.notes}` + ${this.user?.attributes?.notes + ? html`` : html`

${msg(