From 9b45db3c1de623e8d57abb4b9d778e2f0fc1f96e Mon Sep 17 00:00:00 2001 From: Caio Pizzol Date: Thu, 19 Mar 2026 14:12:03 -0300 Subject: [PATCH 1/2] test: add consumer type checks for theme exports and preset theme validation - Add createTheme/buildTheme imports to consumer-types smoke test so broken .d.ts exports are caught during CI - Add preset theme structural validation to compat.test.ts: verifies all three presets exist and every variable they declare is defined in variables.css --- .../src/assets/styles/helpers/compat.test.ts | 36 +++++++++++++++++++ .../superdoc/tests/consumer-types/test.ts | 5 +++ 2 files changed, 41 insertions(+) diff --git a/packages/superdoc/src/assets/styles/helpers/compat.test.ts b/packages/superdoc/src/assets/styles/helpers/compat.test.ts index 46238e5163..ff8efe1144 100644 --- a/packages/superdoc/src/assets/styles/helpers/compat.test.ts +++ b/packages/superdoc/src/assets/styles/helpers/compat.test.ts @@ -6,6 +6,7 @@ import { fileURLToPath } from 'node:url'; const __dirname = dirname(fileURLToPath(import.meta.url)); const variablesCss = readFileSync(resolve(__dirname, 'variables.css'), 'utf-8'); const compatCss = readFileSync(resolve(__dirname, 'compat.css'), 'utf-8'); +const themesCss = readFileSync(resolve(__dirname, 'themes.css'), 'utf-8'); /** Extract all --sd-* variable declarations from a CSS string. */ const extractDeclaredVars = (css: string): Set => { @@ -130,4 +131,39 @@ describe('backward compatibility', () => { } }); }); + + describe('preset themes', () => { + /** Extract variables declared inside each .sd-theme-* block. */ + const extractThemeBlocks = (css: string): Map> => { + const themes = new Map>(); + const blockRegex = /\.(sd-theme-[\w-]+)\s*\{([^}]+)\}/g; + for (const match of css.matchAll(blockRegex)) { + const vars = new Set(); + for (const decl of match[2].matchAll(/(--sd-[\w-]+)\s*:/g)) { + vars.add(decl[1]); + } + themes.set(match[1], vars); + } + return themes; + }; + + const themeBlocks = extractThemeBlocks(themesCss); + + it('contains all expected preset themes', () => { + expect([...themeBlocks.keys()].sort()).toEqual(['sd-theme-blueprint', 'sd-theme-docs', 'sd-theme-word']); + }); + + it('every theme variable is declared in variables.css', () => { + const declaredInVariables = extractDeclaredVars(variablesCss); + const broken: string[] = []; + for (const [theme, vars] of themeBlocks) { + for (const v of vars) { + if (!declaredInVariables.has(v)) { + broken.push(`${theme}: ${v}`); + } + } + } + expect(broken, `Theme variables not in variables.css: ${broken.join(', ')}`).toEqual([]); + }); + }); }); diff --git a/packages/superdoc/tests/consumer-types/test.ts b/packages/superdoc/tests/consumer-types/test.ts index bbf568afda..51148db802 100644 --- a/packages/superdoc/tests/consumer-types/test.ts +++ b/packages/superdoc/tests/consumer-types/test.ts @@ -10,6 +10,7 @@ // Main entry point import type { SuperDoc } from 'superdoc'; +import { createTheme, buildTheme } from 'superdoc'; // Super-editor entry point import type { EditorView, EditorState, Transaction, Schema } from 'superdoc/super-editor'; @@ -21,3 +22,7 @@ import type { ProseMirrorJSON, NodeConfig, MarkConfig } from 'superdoc/types'; type _AssertSuperDoc = SuperDoc extends object ? true : never; type _AssertEditorView = EditorView extends object ? true : never; type _AssertJSON = ProseMirrorJSON extends object ? true : never; +type _AssertCreateTheme = typeof createTheme extends (...args: any[]) => string ? true : never; +type _AssertBuildTheme = typeof buildTheme extends (...args: any[]) => { className: string; css: string } + ? true + : never; From f1aaebe177234c55527903ffa518490bed970d70 Mon Sep 17 00:00:00 2001 From: Caio Pizzol Date: Thu, 19 Mar 2026 14:28:14 -0300 Subject: [PATCH 2/2] fix(test): use constrained generic so type assertions actually fail on mismatch `type X = never` compiles without error, so the previous assertions were no-ops. `AssertExtends` violates the `extends true` constraint and produces a real compile error. --- packages/superdoc/tests/consumer-types/test.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/superdoc/tests/consumer-types/test.ts b/packages/superdoc/tests/consumer-types/test.ts index 51148db802..75f4706be0 100644 --- a/packages/superdoc/tests/consumer-types/test.ts +++ b/packages/superdoc/tests/consumer-types/test.ts @@ -18,11 +18,13 @@ import type { EditorView, EditorState, Transaction, Schema } from 'superdoc/supe // Types entry point import type { ProseMirrorJSON, NodeConfig, MarkConfig } from 'superdoc/types'; -// Verify the types are usable (not just importable) -type _AssertSuperDoc = SuperDoc extends object ? true : never; -type _AssertEditorView = EditorView extends object ? true : never; -type _AssertJSON = ProseMirrorJSON extends object ? true : never; -type _AssertCreateTheme = typeof createTheme extends (...args: any[]) => string ? true : never; -type _AssertBuildTheme = typeof buildTheme extends (...args: any[]) => { className: string; css: string } - ? true - : never; +// Verify the types are usable (not just importable). +// AssertExtends is a compile error, so signature mismatches fail the build. +type AssertExtends = T; +type _AssertSuperDoc = AssertExtends; +type _AssertEditorView = AssertExtends; +type _AssertJSON = AssertExtends; +type _AssertCreateTheme = AssertExtends string ? true : false>; +type _AssertBuildTheme = AssertExtends< + typeof buildTheme extends (...args: any[]) => { className: string; css: string } ? true : false +>;