@alliance-droid/svelte-docs-system 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/README.md +155 -23
  2. package/dist/components/APITable.svelte.d.ts +21 -0
  3. package/dist/components/Breadcrumbs.svelte.d.ts +14 -0
  4. package/dist/components/Callout.svelte.d.ts +15 -0
  5. package/dist/components/CodeBlock.svelte.d.ts +12 -0
  6. package/{src/lib → dist}/components/DocLayout.svelte +18 -6
  7. package/dist/components/DocLayout.svelte.d.ts +18 -0
  8. package/dist/components/DocsPage.svelte +39 -0
  9. package/dist/components/DocsPage.svelte.d.ts +8 -0
  10. package/dist/components/Documentation.svelte +639 -0
  11. package/dist/components/Footer.svelte.d.ts +10 -0
  12. package/dist/components/Image.svelte.d.ts +15 -0
  13. package/{src/lib → dist}/components/Navbar.svelte +4 -4
  14. package/dist/components/Navbar.svelte.d.ts +10 -0
  15. package/{src/lib → dist}/components/Search.svelte +2 -2
  16. package/dist/components/Search.svelte.d.ts +6 -0
  17. package/{template-starter/src/lib → dist}/components/Sidebar.svelte +2 -2
  18. package/dist/components/Sidebar.svelte.d.ts +9 -0
  19. package/dist/components/Tabs.svelte.d.ts +16 -0
  20. package/dist/config.d.ts +93 -0
  21. package/dist/config.js +89 -0
  22. package/dist/configLoader.d.ts +48 -0
  23. package/dist/configLoader.js +187 -0
  24. package/dist/configParser.d.ts +27 -0
  25. package/dist/configParser.js +208 -0
  26. package/{template-starter/src/lib/index.ts → dist/index.d.ts} +6 -7
  27. package/dist/index.js +18 -0
  28. package/dist/navigationBuilder.d.ts +64 -0
  29. package/dist/navigationBuilder.js +225 -0
  30. package/dist/plugin.d.ts +30 -0
  31. package/dist/plugin.js +172 -0
  32. package/dist/routing.d.ts +48 -0
  33. package/dist/routing.js +92 -0
  34. package/dist/stores/i18n.d.ts +20 -0
  35. package/dist/stores/i18n.js +119 -0
  36. package/dist/stores/nav.d.ts +20 -0
  37. package/dist/stores/nav.js +15 -0
  38. package/dist/stores/search.d.ts +49 -0
  39. package/dist/stores/search.js +127 -0
  40. package/dist/stores/theme.d.ts +7 -0
  41. package/dist/stores/theme.js +152 -0
  42. package/dist/stores/version.d.ts +18 -0
  43. package/dist/stores/version.js +93 -0
  44. package/dist/themeCustomization.d.ts +46 -0
  45. package/dist/themeCustomization.js +188 -0
  46. package/dist/utils/highlight.d.ts +13 -0
  47. package/dist/utils/highlight.js +83 -0
  48. package/dist/utils/index.d.ts +1 -0
  49. package/dist/utils/index.js +1 -0
  50. package/dist/utils/markdown.d.ts +40 -0
  51. package/dist/utils/markdown.js +165 -0
  52. package/package.json +44 -23
  53. package/COMPONENTS.md +0 -365
  54. package/COVERAGE_REPORT.md +0 -663
  55. package/SEARCH_VERIFICATION.md +0 -229
  56. package/TEST_SUMMARY.md +0 -344
  57. package/bin/init.js +0 -821
  58. package/docs/COMPONENT_LIBRARY_INTEGRATION_REPORT.md +0 -153
  59. package/docs/DARK_MODE_AUDIT_REPORT.md +0 -403
  60. package/docs/E2E_TESTS.md +0 -354
  61. package/docs/TESTING.md +0 -754
  62. package/docs/THEME_INHERITANCE.md +0 -192
  63. package/docs/de/index.md +0 -41
  64. package/docs/en/COMPONENTS.md +0 -443
  65. package/docs/en/api/examples.md +0 -100
  66. package/docs/en/api/overview.md +0 -69
  67. package/docs/en/components/index.md +0 -622
  68. package/docs/en/config/navigation.md +0 -505
  69. package/docs/en/config/theme-and-colors.md +0 -395
  70. package/docs/en/getting-started/integration.md +0 -406
  71. package/docs/en/guides/common-setups.md +0 -651
  72. package/docs/en/index.md +0 -243
  73. package/docs/en/markdown.md +0 -102
  74. package/docs/en/routing.md +0 -64
  75. package/docs/en/setup.md +0 -52
  76. package/docs/en/troubleshooting.md +0 -704
  77. package/docs/es/index.md +0 -41
  78. package/docs/fr/index.md +0 -41
  79. package/docs/ja/index.md +0 -41
  80. package/pagefind.toml +0 -8
  81. package/postcss.config.js +0 -5
  82. package/src/app.css +0 -119
  83. package/src/app.d.ts +0 -13
  84. package/src/app.html +0 -11
  85. package/src/lib/components/APITable.test.ts +0 -153
  86. package/src/lib/components/Breadcrumbs.test.ts +0 -148
  87. package/src/lib/components/Callout.test.ts +0 -100
  88. package/src/lib/components/CodeBlock.test.ts +0 -133
  89. package/src/lib/components/Image.test.ts +0 -163
  90. package/src/lib/components/Sidebar.svelte +0 -110
  91. package/src/lib/components/Tabs.test.ts +0 -102
  92. package/src/lib/config.test.ts +0 -140
  93. package/src/lib/config.ts +0 -179
  94. package/src/lib/configIntegration.test.ts +0 -272
  95. package/src/lib/configLoader.ts +0 -231
  96. package/src/lib/configParser.test.ts +0 -217
  97. package/src/lib/configParser.ts +0 -234
  98. package/src/lib/index.ts +0 -37
  99. package/src/lib/integration.test.ts +0 -426
  100. package/src/lib/navigationBuilder.test.ts +0 -338
  101. package/src/lib/navigationBuilder.ts +0 -268
  102. package/src/lib/performance.test.ts +0 -369
  103. package/src/lib/routing.test.ts +0 -202
  104. package/src/lib/routing.ts +0 -127
  105. package/src/lib/search-functionality.test.ts +0 -493
  106. package/src/lib/stores/i18n.test.ts +0 -180
  107. package/src/lib/stores/i18n.ts +0 -143
  108. package/src/lib/stores/nav.ts +0 -36
  109. package/src/lib/stores/search.test.ts +0 -140
  110. package/src/lib/stores/search.ts +0 -162
  111. package/src/lib/stores/theme.test.ts +0 -117
  112. package/src/lib/stores/theme.ts +0 -167
  113. package/src/lib/stores/version.test.ts +0 -139
  114. package/src/lib/stores/version.ts +0 -111
  115. package/src/lib/themeCustomization.test.ts +0 -223
  116. package/src/lib/themeCustomization.ts +0 -212
  117. package/src/lib/utils/highlight.test.ts +0 -136
  118. package/src/lib/utils/highlight.ts +0 -100
  119. package/src/lib/utils/index.ts +0 -7
  120. package/src/lib/utils/markdown.test.ts +0 -357
  121. package/src/lib/utils/markdown.ts +0 -77
  122. package/src/routes/+layout.server.ts +0 -1
  123. package/src/routes/+layout.svelte +0 -29
  124. package/src/routes/+page.svelte +0 -165
  125. package/src/routes/quote-demo/+page.svelte +0 -141
  126. package/static/robots.txt +0 -3
  127. package/svelte.config.js +0 -15
  128. package/tailwind.config.ts +0 -55
  129. package/template-starter/.github/workflows/build.yml +0 -40
  130. package/template-starter/.github/workflows/deploy-github-pages.yml +0 -47
  131. package/template-starter/.github/workflows/deploy-netlify.yml +0 -41
  132. package/template-starter/.github/workflows/deploy-vercel.yml +0 -64
  133. package/template-starter/NPM-PACKAGE-SETUP.md +0 -233
  134. package/template-starter/README.md +0 -320
  135. package/template-starter/docs/_config.json +0 -39
  136. package/template-starter/docs/api/components.md +0 -257
  137. package/template-starter/docs/api/overview.md +0 -169
  138. package/template-starter/docs/guides/configuration.md +0 -145
  139. package/template-starter/docs/guides/github-pages-deployment.md +0 -254
  140. package/template-starter/docs/guides/netlify-deployment.md +0 -159
  141. package/template-starter/docs/guides/vercel-deployment.md +0 -131
  142. package/template-starter/docs/index.md +0 -49
  143. package/template-starter/docs/setup.md +0 -149
  144. package/template-starter/package.json +0 -31
  145. package/template-starter/pagefind.toml +0 -3
  146. package/template-starter/postcss.config.js +0 -5
  147. package/template-starter/src/app.css +0 -34
  148. package/template-starter/src/app.d.ts +0 -13
  149. package/template-starter/src/app.html +0 -11
  150. package/template-starter/src/lib/components/APITable.svelte +0 -120
  151. package/template-starter/src/lib/components/APITable.test.ts +0 -96
  152. package/template-starter/src/lib/components/Breadcrumbs.svelte +0 -85
  153. package/template-starter/src/lib/components/Breadcrumbs.test.ts +0 -82
  154. package/template-starter/src/lib/components/Callout.svelte +0 -60
  155. package/template-starter/src/lib/components/Callout.test.ts +0 -91
  156. package/template-starter/src/lib/components/CodeBlock.svelte +0 -68
  157. package/template-starter/src/lib/components/CodeBlock.test.ts +0 -62
  158. package/template-starter/src/lib/components/DocLayout.svelte +0 -84
  159. package/template-starter/src/lib/components/Footer.svelte +0 -78
  160. package/template-starter/src/lib/components/Image.svelte +0 -100
  161. package/template-starter/src/lib/components/Image.test.ts +0 -81
  162. package/template-starter/src/lib/components/Navbar.svelte +0 -141
  163. package/template-starter/src/lib/components/Search.svelte +0 -248
  164. package/template-starter/src/lib/components/Tabs.svelte +0 -48
  165. package/template-starter/src/lib/components/Tabs.test.ts +0 -89
  166. package/template-starter/src/routes/+layout.svelte +0 -28
  167. package/template-starter/src/routes/+page.svelte +0 -92
  168. package/template-starter/svelte.config.js +0 -17
  169. package/template-starter/tailwind.config.ts +0 -17
  170. package/template-starter/tsconfig.json +0 -13
  171. package/template-starter/vite.config.ts +0 -6
  172. package/tests/e2e/example.spec.ts +0 -345
  173. package/tsconfig.json +0 -20
  174. package/vite.config.ts +0 -6
  175. package/vitest.config.ts +0 -33
  176. package/vitest.setup.ts +0 -21
  177. /package/{src/lib → dist}/assets/favicon.svg +0 -0
  178. /package/{src/lib → dist}/components/APITable.svelte +0 -0
  179. /package/{src/lib → dist}/components/Breadcrumbs.svelte +0 -0
  180. /package/{src/lib → dist}/components/Callout.svelte +0 -0
  181. /package/{src/lib → dist}/components/CodeBlock.svelte +0 -0
  182. /package/{src/lib → dist}/components/Footer.svelte +0 -0
  183. /package/{src/lib → dist}/components/Image.svelte +0 -0
  184. /package/{src/lib → dist}/components/Tabs.svelte +0 -0
  185. /package/{src/lib → dist}/svelte-component-library.d.ts +0 -0
@@ -1,167 +0,0 @@
1
- import { writable } from 'svelte/store';
2
-
3
- type Theme = 'light' | 'dark';
4
-
5
- /**
6
- * Detects if this app is embedded in a parent app by checking if window.parent exists
7
- * and is different from the current window.
8
- */
9
- function isEmbedded(): boolean {
10
- if (typeof window === 'undefined') return false;
11
- try {
12
- return window.parent !== window && window.parent !== null;
13
- } catch {
14
- return false;
15
- }
16
- }
17
-
18
- /**
19
- * Attempts to detect the parent app's theme by checking the parent window's
20
- * document.documentElement classList for the 'dark' class.
21
- */
22
- function getParentTheme(): Theme | null {
23
- if (!isEmbedded()) return null;
24
-
25
- try {
26
- // Try to access parent's document to check for dark class
27
- if (
28
- window.parent &&
29
- window.parent.document &&
30
- window.parent.document.documentElement
31
- ) {
32
- const hasDarkClass =
33
- window.parent.document.documentElement.classList.contains('dark');
34
- return hasDarkClass ? 'dark' : 'light';
35
- }
36
- } catch (e) {
37
- // Cross-origin or other access errors - fall back to other methods
38
- console.debug('Unable to detect parent theme via document inspection:', e);
39
- }
40
-
41
- return null;
42
- }
43
-
44
- function createThemeStore() {
45
- /**
46
- * Initializes theme by:
47
- * 1. Checking if embedded in parent app and inheriting parent's theme
48
- * 2. Falling back to localStorage preference
49
- * 3. Falling back to system preference
50
- * 4. Defaulting to 'light'
51
- */
52
- const getInitialTheme = (): Theme => {
53
- if (typeof window === 'undefined') {
54
- return 'light'; // SSR default
55
- }
56
-
57
- // Priority 1: Check parent app theme if embedded
58
- const parentTheme = getParentTheme();
59
- if (parentTheme) {
60
- return parentTheme;
61
- }
62
-
63
- // Priority 2: Check localStorage (user preference in standalone mode)
64
- try {
65
- const stored = localStorage?.getItem?.('theme') as Theme | null;
66
- if (stored) {
67
- return stored;
68
- }
69
- } catch (e) {
70
- // localStorage may not be available in some environments
71
- }
72
-
73
- // Priority 3: Check system preference
74
- if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
75
- return 'dark';
76
- }
77
-
78
- return 'light';
79
- };
80
-
81
- const { subscribe, set, update } = writable<Theme>(getInitialTheme());
82
-
83
- // Set up listener for parent theme changes when embedded
84
- if (typeof window !== 'undefined' && isEmbedded()) {
85
- try {
86
- const observer = new MutationObserver((mutations) => {
87
- mutations.forEach((mutation) => {
88
- if (
89
- mutation.type === 'attributes' &&
90
- mutation.attributeName === 'class' &&
91
- mutation.target === window.parent?.document?.documentElement
92
- ) {
93
- // Parent's dark class changed, update our theme
94
- const parentTheme = getParentTheme();
95
- if (parentTheme) {
96
- const currentTheme: Theme = parentTheme;
97
- applyTheme(currentTheme);
98
- set(currentTheme);
99
- }
100
- }
101
- });
102
- });
103
-
104
- // Watch for class changes on parent's documentElement
105
- if (window.parent?.document?.documentElement) {
106
- observer.observe(window.parent.document.documentElement, {
107
- attributes: true,
108
- attributeFilter: ['class'],
109
- });
110
- }
111
- } catch (e) {
112
- console.debug(
113
- 'Could not set up parent theme listener (may be cross-origin):',
114
- e
115
- );
116
- }
117
- }
118
-
119
- /**
120
- * Applies theme to the document by adding/removing the 'dark' class
121
- */
122
- const applyTheme = (theme: Theme) => {
123
- if (typeof window === 'undefined') return;
124
- if (theme === 'dark') {
125
- document.documentElement.classList.add('dark');
126
- } else {
127
- document.documentElement.classList.remove('dark');
128
- }
129
- };
130
-
131
- return {
132
- subscribe,
133
- set: (theme: Theme) => {
134
- if (typeof window !== 'undefined') {
135
- // Only save to localStorage if not embedded (standalone mode)
136
- if (!isEmbedded()) {
137
- try {
138
- localStorage?.setItem?.('theme', theme);
139
- } catch (e) {
140
- // localStorage may not be available
141
- }
142
- }
143
- applyTheme(theme);
144
- }
145
- set(theme);
146
- },
147
- toggle: () => {
148
- update((theme) => {
149
- const newTheme = theme === 'dark' ? 'light' : 'dark';
150
- if (typeof window !== 'undefined') {
151
- // Only save to localStorage if not embedded (standalone mode)
152
- if (!isEmbedded()) {
153
- try {
154
- localStorage?.setItem?.('theme', newTheme);
155
- } catch (e) {
156
- // localStorage may not be available
157
- }
158
- }
159
- applyTheme(newTheme);
160
- }
161
- return newTheme;
162
- });
163
- },
164
- };
165
- }
166
-
167
- export const theme = createThemeStore();
@@ -1,139 +0,0 @@
1
- import { describe, it, expect, beforeEach, vi } from 'vitest';
2
- import { version } from './version';
3
-
4
- // Mock localStorage
5
- const localStorageMock = (() => {
6
- let store: Record<string, string> = {};
7
-
8
- return {
9
- getItem: (key: string) => store[key] || null,
10
- setItem: (key: string, value: string) => {
11
- store[key] = value.toString();
12
- },
13
- removeItem: (key: string) => {
14
- delete store[key];
15
- },
16
- clear: () => {
17
- store = {};
18
- },
19
- };
20
- })();
21
-
22
- Object.defineProperty(window, 'localStorage', {
23
- value: localStorageMock,
24
- });
25
-
26
- describe('version store', () => {
27
- beforeEach(() => {
28
- localStorage.clear();
29
- });
30
-
31
- it('should initialize with default version', () => {
32
- let currentVersion = '';
33
- const unsubscribe = version.subscribe((config) => {
34
- currentVersion = config.current;
35
- });
36
-
37
- expect(currentVersion).toBe('2.0');
38
- unsubscribe();
39
- });
40
-
41
- it('should have multiple versions available', () => {
42
- let versions = [];
43
- const unsubscribe = version.subscribe((config) => {
44
- versions = config.availableVersions.map((v) => v.version);
45
- });
46
-
47
- expect(versions).toContain('2.0');
48
- expect(versions).toContain('1.5');
49
- expect(versions).toContain('1.0');
50
- expect(versions.length).toBe(3);
51
- unsubscribe();
52
- });
53
-
54
- it('should mark v2.0 as latest', () => {
55
- let latestVersion = null;
56
- const unsubscribe = version.subscribe((config) => {
57
- const latest = config.availableVersions.find((v) => v.isLatest);
58
- latestVersion = latest?.version;
59
- });
60
-
61
- expect(latestVersion).toBe('2.0');
62
- unsubscribe();
63
- });
64
-
65
- it('should allow changing version', () => {
66
- let currentVersion = '';
67
- const unsubscribe = version.subscribe((config) => {
68
- currentVersion = config.current;
69
- });
70
-
71
- version.setVersion('1.5');
72
- expect(currentVersion).toBe('1.5');
73
-
74
- version.setVersion('1.0');
75
- expect(currentVersion).toBe('1.0');
76
-
77
- unsubscribe();
78
- });
79
-
80
- it('should persist version preference to localStorage', () => {
81
- version.setVersion('1.5');
82
- expect(localStorage.getItem('docs-version')).toBe('1.5');
83
-
84
- version.setVersion('1.0');
85
- expect(localStorage.getItem('docs-version')).toBe('1.0');
86
- });
87
-
88
- it('should ignore setting invalid version', () => {
89
- let currentVersion = '';
90
- const unsubscribe = version.subscribe((config) => {
91
- currentVersion = config.current;
92
- });
93
-
94
- const initialVersion = currentVersion;
95
- version.setVersion('99.0');
96
- expect(currentVersion).toBe(initialVersion);
97
-
98
- unsubscribe();
99
- });
100
-
101
- it('should allow adding new versions', () => {
102
- let versions = [];
103
- const unsubscribe = version.subscribe((config) => {
104
- versions = config.availableVersions.map((v) => v.version);
105
- });
106
-
107
- version.addVersion({
108
- version: '3.0',
109
- label: 'v3.0',
110
- isLatest: false,
111
- status: 'beta',
112
- });
113
-
114
- expect(versions).toContain('3.0');
115
- unsubscribe();
116
- });
117
-
118
- it('should allow removing versions', () => {
119
- let versions = [];
120
- const unsubscribe = version.subscribe((config) => {
121
- versions = config.availableVersions.map((v) => v.version);
122
- });
123
-
124
- const initialCount = versions.length;
125
- version.removeVersion('1.0');
126
-
127
- expect(versions.length).toBe(initialCount - 1);
128
- expect(versions).not.toContain('1.0');
129
- unsubscribe();
130
- });
131
-
132
- it('should retrieve version metadata', () => {
133
- const metadata = version.getVersionMetadata('2.0');
134
- expect(metadata).toBeDefined();
135
- expect(metadata?.version).toBe('2.0');
136
- expect(metadata?.isLatest).toBe(true);
137
- expect(metadata?.status).toBe('stable');
138
- });
139
- });
@@ -1,111 +0,0 @@
1
- import { writable } from 'svelte/store';
2
-
3
- export interface VersionMetadata {
4
- version: string;
5
- label: string;
6
- isLatest: boolean;
7
- releaseDate?: string;
8
- status?: 'stable' | 'beta' | 'deprecated';
9
- }
10
-
11
- export interface VersionConfig {
12
- current: string;
13
- availableVersions: VersionMetadata[];
14
- }
15
-
16
- function createVersionStore() {
17
- // Default version configuration
18
- const defaultConfig: VersionConfig = {
19
- current: '2.0',
20
- availableVersions: [
21
- {
22
- version: '2.0',
23
- label: 'v2.0 (Latest)',
24
- isLatest: true,
25
- releaseDate: '2026-02-04',
26
- status: 'stable',
27
- },
28
- {
29
- version: '1.5',
30
- label: 'v1.5',
31
- isLatest: false,
32
- releaseDate: '2025-12-01',
33
- status: 'stable',
34
- },
35
- {
36
- version: '1.0',
37
- label: 'v1.0 (Archive)',
38
- isLatest: false,
39
- releaseDate: '2025-10-01',
40
- status: 'deprecated',
41
- },
42
- ],
43
- };
44
-
45
- const getInitialVersion = (): string => {
46
- if (typeof window === 'undefined') {
47
- return defaultConfig.current;
48
- }
49
-
50
- try {
51
- // Check localStorage for stored version preference
52
- const stored = localStorage?.getItem?.('docs-version');
53
- if (stored) {
54
- return stored;
55
- }
56
- } catch (e) {
57
- // localStorage may not be available in some environments
58
- }
59
-
60
- return defaultConfig.current;
61
- };
62
-
63
- const { subscribe, set, update } = writable<VersionConfig>({
64
- ...defaultConfig,
65
- current: getInitialVersion(),
66
- });
67
-
68
- return {
69
- subscribe,
70
- setVersion: (version: string) => {
71
- update((config) => {
72
- if (config.availableVersions.some((v) => v.version === version)) {
73
- if (typeof window !== 'undefined') {
74
- try {
75
- localStorage?.setItem?.('docs-version', version);
76
- } catch (e) {
77
- // localStorage may not be available
78
- }
79
- }
80
- return { ...config, current: version };
81
- }
82
- return config;
83
- });
84
- },
85
- addVersion: (metadata: VersionMetadata) => {
86
- update((config) => ({
87
- ...config,
88
- availableVersions: [
89
- ...config.availableVersions.filter((v) => v.version !== metadata.version),
90
- metadata,
91
- ],
92
- }));
93
- },
94
- removeVersion: (version: string) => {
95
- update((config) => ({
96
- ...config,
97
- availableVersions: config.availableVersions.filter((v) => v.version !== version),
98
- }));
99
- },
100
- getVersionMetadata: (version: string): VersionMetadata | undefined => {
101
- let metadata: VersionMetadata | undefined;
102
- const unsubscribe = subscribe((config) => {
103
- metadata = config.availableVersions.find((v) => v.version === version);
104
- });
105
- unsubscribe();
106
- return metadata;
107
- },
108
- };
109
- }
110
-
111
- export const version = createVersionStore();
@@ -1,223 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import {
3
- generateCSSVariables,
4
- createCSSVariablesStylesheet,
5
- parseColor,
6
- validateTheme,
7
- mergeThemes,
8
- getThemeTemplate,
9
- } from './themeCustomization';
10
-
11
- describe('Theme Customization', () => {
12
- describe('generateCSSVariables', () => {
13
- it('should generate CSS variables from theme config', () => {
14
- const theme = {
15
- primary: '#ff0000',
16
- secondary: '#00ff00',
17
- fontFamily: 'Arial',
18
- };
19
-
20
- const vars = generateCSSVariables(theme);
21
- expect(vars['--color-primary']).toBe('#ff0000');
22
- expect(vars['--color-secondary']).toBe('#00ff00');
23
- expect(vars['--font-family-body']).toBe('Arial');
24
- });
25
-
26
- it('should skip undefined values', () => {
27
- const theme = { primary: '#ff0000' };
28
- const vars = generateCSSVariables(theme);
29
-
30
- expect(Object.keys(vars)).toContain('--color-primary');
31
- expect(Object.keys(vars)).not.toContain('--color-secondary');
32
- });
33
-
34
- it('should handle all color properties', () => {
35
- const theme = {
36
- primary: '#1',
37
- secondary: '#2',
38
- textLight: '#3',
39
- textDark: '#4',
40
- bgLight: '#5',
41
- bgDark: '#6',
42
- sidebarBg: '#7',
43
- navbarBg: '#8',
44
- codeBg: '#9',
45
- };
46
-
47
- const vars = generateCSSVariables(theme);
48
- expect(Object.keys(vars)).toHaveLength(9);
49
- });
50
-
51
- it('should handle all font properties', () => {
52
- const theme = {
53
- fontFamily: 'sans-serif',
54
- headingFont: 'serif',
55
- };
56
-
57
- const vars = generateCSSVariables(theme);
58
- expect(vars['--font-family-body']).toBe('sans-serif');
59
- expect(vars['--font-family-heading']).toBe('serif');
60
- });
61
- });
62
-
63
- describe('createCSSVariablesStylesheet', () => {
64
- it('should create valid CSS string', () => {
65
- const vars = { '--color-primary': '#ff0000' };
66
- const css = createCSSVariablesStylesheet(vars);
67
-
68
- expect(css).toContain(':root');
69
- expect(css).toContain('--color-primary: #ff0000');
70
- });
71
-
72
- it('should include multiple variables', () => {
73
- const vars = {
74
- '--color-primary': '#ff0000',
75
- '--color-secondary': '#00ff00',
76
- };
77
-
78
- const css = createCSSVariablesStylesheet(vars);
79
- expect(css).toContain('--color-primary');
80
- expect(css).toContain('--color-secondary');
81
- });
82
- });
83
-
84
- describe('parseColor', () => {
85
- it('should parse hex colors', () => {
86
- expect(parseColor('#ff0000').valid).toBe(true);
87
- expect(parseColor('#f00').valid).toBe(true);
88
- expect(parseColor('#ff0000aa').valid).toBe(true);
89
- });
90
-
91
- it('should parse RGB colors', () => {
92
- expect(parseColor('rgb(255, 0, 0)').valid).toBe(true);
93
- expect(parseColor('rgba(255, 0, 0, 0.5)').valid).toBe(true);
94
- });
95
-
96
- it('should parse named colors', () => {
97
- expect(parseColor('red').valid).toBe(true);
98
- expect(parseColor('blue').valid).toBe(true);
99
- expect(parseColor('transparent').valid).toBe(true);
100
- });
101
-
102
- it('should parse CSS variables', () => {
103
- expect(parseColor('var(--color-primary)').valid).toBe(true);
104
- });
105
-
106
- it('should reject invalid colors', () => {
107
- expect(parseColor('invalid').valid).toBe(false);
108
- expect(parseColor('#').valid).toBe(false);
109
- expect(parseColor('').valid).toBe(false);
110
- });
111
-
112
- it('should return error message for invalid colors', () => {
113
- const result = parseColor('not-a-color');
114
- expect(result.valid).toBe(false);
115
- expect(result.error).toBeDefined();
116
- });
117
- });
118
-
119
- describe('validateTheme', () => {
120
- it('should validate valid theme', () => {
121
- const theme = {
122
- primary: '#ff0000',
123
- secondary: 'blue',
124
- fontFamily: 'Arial',
125
- };
126
-
127
- const result = validateTheme(theme);
128
- expect(result.valid).toBe(true);
129
- expect(result.errors).toHaveLength(0);
130
- });
131
-
132
- it('should reject non-object theme', () => {
133
- const result = validateTheme('not-object' as any);
134
- expect(result.valid).toBe(false);
135
- expect(result.errors.length).toBeGreaterThan(0);
136
- });
137
-
138
- it('should validate all color fields', () => {
139
- const theme = {
140
- primary: 'invalid-color',
141
- };
142
-
143
- const result = validateTheme(theme);
144
- expect(result.valid).toBe(false);
145
- expect(result.errors.some((e) => e.includes('primary'))).toBe(true);
146
- });
147
-
148
- it('should validate font fields are strings', () => {
149
- const theme = {
150
- fontFamily: 123 as any,
151
- };
152
-
153
- const result = validateTheme(theme);
154
- expect(result.valid).toBe(false);
155
- expect(result.errors.some((e) => e.includes('fontFamily'))).toBe(true);
156
- });
157
- });
158
-
159
- describe('mergeThemes', () => {
160
- it('should merge two themes with priority to first', () => {
161
- const primary = { primary: '#ff0000' };
162
- const secondary = { primary: '#00ff00', secondary: '#0000ff' };
163
-
164
- const merged = mergeThemes(primary, secondary);
165
- expect(merged.primary).toBe('#ff0000');
166
- expect(merged.secondary).toBe('#0000ff');
167
- });
168
-
169
- it('should handle undefined values', () => {
170
- const primary = { primary: '#ff0000' };
171
- const secondary = { secondary: '#00ff00' };
172
-
173
- const merged = mergeThemes(primary, secondary);
174
- expect(merged.primary).toBe('#ff0000');
175
- expect(merged.secondary).toBe('#00ff00');
176
- });
177
- });
178
-
179
- describe('getThemeTemplate', () => {
180
- it('should return default theme', () => {
181
- const theme = getThemeTemplate('default');
182
- expect(theme.primary).toBeDefined();
183
- expect(theme.fontFamily).toBeDefined();
184
- });
185
-
186
- it('should return dark theme', () => {
187
- const theme = getThemeTemplate('dark');
188
- expect(theme.primary).toBeDefined();
189
- // Dark theme might have different colors
190
- expect(theme.bgDark).toBeDefined();
191
- });
192
-
193
- it('should return minimal theme', () => {
194
- const theme = getThemeTemplate('minimal');
195
- expect(theme.primary).toBe('#000000');
196
- });
197
-
198
- it('should return colorful theme', () => {
199
- const theme = getThemeTemplate('colorful');
200
- expect(theme.primary).toBe('#ff006e');
201
- });
202
-
203
- it('should default to default theme if invalid', () => {
204
- const theme = getThemeTemplate('invalid' as any);
205
- expect(theme).toEqual(getThemeTemplate('default'));
206
- });
207
-
208
- it('should return default if not specified', () => {
209
- const theme = getThemeTemplate();
210
- expect(theme).toEqual(getThemeTemplate('default'));
211
- });
212
-
213
- it('all theme templates should be valid', () => {
214
- const templates = ['default', 'dark', 'minimal', 'colorful'] as const;
215
-
216
- templates.forEach((templateName) => {
217
- const theme = getThemeTemplate(templateName);
218
- const result = validateTheme(theme);
219
- expect(result.valid).toBe(true);
220
- });
221
- });
222
- });
223
- });