From 0b86ece1d5970a26a7eb5129d8ff07b998876e90 Mon Sep 17 00:00:00 2001 From: Lucas Smith Date: Mon, 11 May 2026 13:03:02 +1000 Subject: [PATCH] feat: add custom branding for signing pages (#2785) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Platform-plan organisations and teams can now customise non-embed signing pages with six brand colour tokens, a border-radius, and a free-text custom CSS block (up to 256 KB). - Stored on OrganisationGlobalSettings / TeamGlobalSettings; teams inherit from the org via brandingEnabled === null. - CSS is sanitised on save (PostCSS) so we can inline it at SSR with no per-render parsing. - Rendered via a nonce'd ; +}; diff --git a/apps/remix/app/root.tsx b/apps/remix/app/root.tsx index 0c6341cad..096b1504e 100644 --- a/apps/remix/app/root.tsx +++ b/apps/remix/app/root.tsx @@ -17,6 +17,7 @@ import { Scripts, ScrollRestoration, useLoaderData, + useMatches, } from 'react-router'; import { PreventFlashOnWrongTheme, ThemeProvider, useTheme } from 'remix-themes'; @@ -110,6 +111,13 @@ export function LayoutContent({ children }: { children: React.ReactNode }) { const [theme] = useTheme(); + // Recipient routes (signing pages) put `documenso-branded` on so the + // inside a string value', () => { + const result = sanitizeBrandingCss('.x { font-family: ""; }'); + + expect(result.css.toLowerCase()).not.toContain(' inside a CSS comment', () => { + const result = sanitizeBrandingCss('.x { color: red; /* */ }'); + + expect(result.css.toLowerCase()).not.toContain(' inside an at-rule params block', () => { + const result = sanitizeBrandingCss( + '@media screen and (foo: bar) { .x { color: red; } }', + ); + + expect(result.css.toLowerCase()).not.toContain(' in a value', () => { + const result = sanitizeBrandingCss('.x { font-family: "foo"; }'); + + expect(result.css.toLowerCase()).not.toContain(' in an attribute selector value', () => { + const result = sanitizeBrandingCss('[data-x=""] { color: red; }'); + + expect(result.css.toLowerCase()).not.toContain(' { + // `"; }'); + + // The output keeps the literal `` end tag's `<` for the same reason it'd escape ``. + expect(result.css).toContain('