@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
@@ -0,0 +1,9 @@
1
+ import type { NavSection } from '../stores/nav';
2
+ type $$ComponentProps = {
3
+ sections?: NavSection[];
4
+ currentPath?: string;
5
+ onNavigate?: (path: string) => void;
6
+ };
7
+ declare const Sidebar: import("svelte").Component<$$ComponentProps, {}, "">;
8
+ type Sidebar = ReturnType<typeof Sidebar>;
9
+ export default Sidebar;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Tabs component for switching between content panels
3
+ * Usage:
4
+ * <Tabs items={[{label: 'Tab 1', content: 'Content 1'}]} />
5
+ */
6
+ interface TabItem {
7
+ label: string;
8
+ content?: string;
9
+ }
10
+ interface Props {
11
+ items: TabItem[];
12
+ defaultIndex?: number;
13
+ }
14
+ declare const Tabs: import("svelte").Component<Props, {}, "">;
15
+ type Tabs = ReturnType<typeof Tabs>;
16
+ export default Tabs;
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Configuration schema and types for the documentation system
3
+ */
4
+ export interface ThemeConfig {
5
+ /** Primary color (hex, rgb, or CSS color name) */
6
+ primary?: string;
7
+ /** Secondary color */
8
+ secondary?: string;
9
+ /** Text color for light mode */
10
+ textLight?: string;
11
+ /** Text color for dark mode */
12
+ textDark?: string;
13
+ /** Background color for light mode */
14
+ bgLight?: string;
15
+ /** Background color for dark mode */
16
+ bgDark?: string;
17
+ /** Font family for body text */
18
+ fontFamily?: string;
19
+ /** Font family for headings */
20
+ headingFont?: string;
21
+ /** Sidebar background color */
22
+ sidebarBg?: string;
23
+ /** Navbar background color */
24
+ navbarBg?: string;
25
+ /** Code block background color */
26
+ codeBg?: string;
27
+ }
28
+ export interface NavItem {
29
+ label: string;
30
+ href?: string;
31
+ children?: NavItem[];
32
+ icon?: string;
33
+ }
34
+ export interface NavSection {
35
+ title: string;
36
+ items: NavItem[];
37
+ }
38
+ export interface NavigationConfig {
39
+ title?: string;
40
+ logo?: string;
41
+ sections?: NavSection[];
42
+ /** Auto-generate navigation from folder structure */
43
+ autoGenerate?: boolean;
44
+ /** Exclude paths from auto-generation */
45
+ excludePaths?: string[];
46
+ }
47
+ export interface ConfigOptions {
48
+ /** Name of the documentation project */
49
+ name?: string;
50
+ /** Mount point for docs (e.g., /docs, /help, /guides) */
51
+ docsRoute?: string;
52
+ /** Path to docs folder relative to project root */
53
+ docsFolderPath?: string;
54
+ /** Base URL path for links */
55
+ basePath?: string;
56
+ /** Theme configuration */
57
+ theme?: ThemeConfig;
58
+ /** Navigation configuration */
59
+ navigation?: NavigationConfig;
60
+ /** Enable search functionality */
61
+ enableSearch?: boolean;
62
+ /** Custom CSS file path */
63
+ customCss?: string;
64
+ /** Layout template name (default, minimal, full-width) */
65
+ layout?: 'default' | 'minimal' | 'full-width';
66
+ /** Enable dark mode toggle */
67
+ darkMode?: boolean;
68
+ /** Default theme (light or dark) */
69
+ defaultTheme?: 'light' | 'dark';
70
+ /** Enable breadcrumbs */
71
+ breadcrumbs?: boolean;
72
+ /** Enable prev/next navigation */
73
+ prevNext?: boolean;
74
+ /** Site title for header */
75
+ siteTitle?: string;
76
+ /** Site description for meta tags */
77
+ siteDescription?: string;
78
+ }
79
+ /**
80
+ * Default configuration values
81
+ */
82
+ export declare const DEFAULT_CONFIG: ConfigOptions;
83
+ /**
84
+ * Validates a configuration object
85
+ */
86
+ export declare function validateConfig(config: unknown): {
87
+ valid: boolean;
88
+ errors: string[];
89
+ };
90
+ /**
91
+ * Merges user config with defaults
92
+ */
93
+ export declare function mergeConfig(userConfig: ConfigOptions, defaults?: ConfigOptions): ConfigOptions;
package/dist/config.js ADDED
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Configuration schema and types for the documentation system
3
+ */
4
+ /**
5
+ * Default configuration values
6
+ */
7
+ export const DEFAULT_CONFIG = {
8
+ name: 'Documentation',
9
+ docsRoute: '/docs',
10
+ docsFolderPath: './docs',
11
+ basePath: '/docs',
12
+ enableSearch: true,
13
+ layout: 'default',
14
+ darkMode: true,
15
+ defaultTheme: 'light',
16
+ breadcrumbs: true,
17
+ prevNext: true,
18
+ theme: {
19
+ primary: '#0066cc',
20
+ secondary: '#ff6b6b',
21
+ fontFamily: 'system-ui, -apple-system, sans-serif',
22
+ headingFont: 'system-ui, -apple-system, sans-serif',
23
+ },
24
+ navigation: {
25
+ autoGenerate: true,
26
+ },
27
+ };
28
+ /**
29
+ * Validates a configuration object
30
+ */
31
+ export function validateConfig(config) {
32
+ const errors = [];
33
+ if (typeof config !== 'object' || config === null) {
34
+ errors.push('Configuration must be an object');
35
+ return { valid: false, errors };
36
+ }
37
+ const cfg = config;
38
+ // Validate docsRoute
39
+ if (cfg.docsRoute !== undefined) {
40
+ if (typeof cfg.docsRoute !== 'string') {
41
+ errors.push('docsRoute must be a string');
42
+ }
43
+ else if (!cfg.docsRoute.startsWith('/')) {
44
+ errors.push('docsRoute must start with /');
45
+ }
46
+ }
47
+ // Validate layout
48
+ if (cfg.layout !== undefined) {
49
+ if (!['default', 'minimal', 'full-width'].includes(cfg.layout)) {
50
+ errors.push('layout must be one of: default, minimal, full-width');
51
+ }
52
+ }
53
+ // Validate defaultTheme
54
+ if (cfg.defaultTheme !== undefined) {
55
+ if (!['light', 'dark'].includes(cfg.defaultTheme)) {
56
+ errors.push('defaultTheme must be either light or dark');
57
+ }
58
+ }
59
+ // Validate theme config
60
+ if (cfg.theme !== undefined) {
61
+ if (typeof cfg.theme !== 'object' || cfg.theme === null) {
62
+ errors.push('theme must be an object');
63
+ }
64
+ }
65
+ // Validate navigation config
66
+ if (cfg.navigation !== undefined) {
67
+ if (typeof cfg.navigation !== 'object' || cfg.navigation === null) {
68
+ errors.push('navigation must be an object');
69
+ }
70
+ }
71
+ return { valid: errors.length === 0, errors };
72
+ }
73
+ /**
74
+ * Merges user config with defaults
75
+ */
76
+ export function mergeConfig(userConfig, defaults = DEFAULT_CONFIG) {
77
+ return {
78
+ ...defaults,
79
+ ...userConfig,
80
+ theme: {
81
+ ...defaults.theme,
82
+ ...(userConfig.theme || {}),
83
+ },
84
+ navigation: {
85
+ ...defaults.navigation,
86
+ ...(userConfig.navigation || {}),
87
+ },
88
+ };
89
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Configuration loader and manager
3
+ * Loads, validates, and manages the docs system configuration
4
+ */
5
+ import type { ConfigOptions } from './config';
6
+ export interface ConfigLoadResult {
7
+ success: boolean;
8
+ config: ConfigOptions;
9
+ errors: string[];
10
+ warnings: string[];
11
+ source: 'default' | 'loaded' | 'merged';
12
+ }
13
+ /**
14
+ * Load configuration from a file
15
+ */
16
+ export declare function loadConfiguration(configPath?: string): Promise<ConfigLoadResult>;
17
+ export declare function getConfiguration(configPath?: string): Promise<ConfigOptions>;
18
+ /**
19
+ * Clear configuration cache (useful for testing or reloading)
20
+ */
21
+ export declare function clearConfigCache(): void;
22
+ /**
23
+ * Parse frontmatter from markdown content and merge with config
24
+ */
25
+ export declare function parseMarkdownFrontmatter(content: string): {
26
+ frontmatter: Record<string, unknown>;
27
+ body: string;
28
+ errors: string[];
29
+ };
30
+ /**
31
+ * Validate a custom config object
32
+ */
33
+ export declare function validateCustomConfig(config: unknown): {
34
+ valid: boolean;
35
+ errors: string[];
36
+ };
37
+ /**
38
+ * Create a configuration from minimal user input
39
+ */
40
+ export declare function createMinimalConfig(options?: Partial<ConfigOptions>): ConfigOptions;
41
+ /**
42
+ * Export configuration as JSON
43
+ */
44
+ export declare function exportConfigAsJSON(config: ConfigOptions): string;
45
+ /**
46
+ * Export configuration as YAML
47
+ */
48
+ export declare function exportConfigAsYAML(config: ConfigOptions): string;
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Configuration loader and manager
3
+ * Loads, validates, and manages the docs system configuration
4
+ */
5
+ import { DEFAULT_CONFIG, mergeConfig, validateConfig } from './config';
6
+ import { parseConfigFile, loadConfigFile, parseFrontmatter } from './configParser';
7
+ import { createRouteConfig, validateRoute } from './routing';
8
+ import { validateTheme } from './themeCustomization';
9
+ import { validateNavigation } from './navigationBuilder';
10
+ /**
11
+ * Load configuration from a file
12
+ */
13
+ export async function loadConfiguration(configPath = '/docs/_config.json') {
14
+ const errors = [];
15
+ const warnings = [];
16
+ let userConfig = {};
17
+ // Try to load the config file
18
+ const result = await loadConfigFile(configPath);
19
+ if (result.errors.length > 0 && !configPath.includes('_config')) {
20
+ // If it's not a standard config file, it might not exist - that's ok
21
+ errors.push(...result.errors);
22
+ }
23
+ else if (result.errors.length > 0) {
24
+ // For standard config file, log errors but continue with defaults
25
+ warnings.push(...result.errors);
26
+ }
27
+ else {
28
+ userConfig = result.config;
29
+ }
30
+ // Validate the loaded config
31
+ const validation = validateConfig(userConfig);
32
+ if (!validation.valid) {
33
+ warnings.push(...validation.errors);
34
+ }
35
+ // Validate sub-configs
36
+ if (userConfig.theme) {
37
+ const themeValidation = validateTheme(userConfig.theme);
38
+ if (!themeValidation.valid) {
39
+ warnings.push(`Theme validation errors: ${themeValidation.errors.join(', ')}`);
40
+ }
41
+ }
42
+ if (userConfig.navigation) {
43
+ const navValidation = validateNavigation(userConfig.navigation);
44
+ if (!navValidation.valid) {
45
+ warnings.push(`Navigation validation errors: ${navValidation.errors.join(', ')}`);
46
+ }
47
+ }
48
+ // Validate route
49
+ if (userConfig.docsRoute && !validateRoute(userConfig.docsRoute)) {
50
+ errors.push(`Invalid docsRoute: ${userConfig.docsRoute}`);
51
+ }
52
+ // Merge with defaults
53
+ const finalConfig = mergeConfig(userConfig, DEFAULT_CONFIG);
54
+ // Validate final config
55
+ const finalValidation = validateConfig(finalConfig);
56
+ if (!finalValidation.valid) {
57
+ errors.push(...finalValidation.errors);
58
+ }
59
+ const success = errors.length === 0;
60
+ return {
61
+ success,
62
+ config: finalConfig,
63
+ errors,
64
+ warnings,
65
+ source: success ? 'loaded' : warnings.length > 0 ? 'merged' : 'default',
66
+ };
67
+ }
68
+ /**
69
+ * Load and cache configuration (for browser environment)
70
+ */
71
+ let cachedConfig = null;
72
+ let configLoadPromise = null;
73
+ export async function getConfiguration(configPath = '/docs/_config.json') {
74
+ if (cachedConfig) {
75
+ return cachedConfig;
76
+ }
77
+ if (!configLoadPromise) {
78
+ configLoadPromise = loadConfiguration(configPath);
79
+ }
80
+ const result = await configLoadPromise;
81
+ cachedConfig = result.config;
82
+ return result.config;
83
+ }
84
+ /**
85
+ * Clear configuration cache (useful for testing or reloading)
86
+ */
87
+ export function clearConfigCache() {
88
+ cachedConfig = null;
89
+ configLoadPromise = null;
90
+ }
91
+ /**
92
+ * Parse frontmatter from markdown content and merge with config
93
+ */
94
+ export function parseMarkdownFrontmatter(content) {
95
+ const result = parseFrontmatter(content);
96
+ if (result.error) {
97
+ return {
98
+ frontmatter: {},
99
+ body: result.body,
100
+ errors: [result.error],
101
+ };
102
+ }
103
+ return {
104
+ frontmatter: result.frontmatter || {},
105
+ body: result.body,
106
+ errors: [],
107
+ };
108
+ }
109
+ /**
110
+ * Validate a custom config object
111
+ */
112
+ export function validateCustomConfig(config) {
113
+ const validation = validateConfig(config);
114
+ if (!validation.valid) {
115
+ return validation;
116
+ }
117
+ const cfg = config;
118
+ const errors = [];
119
+ // Additional validations
120
+ if (cfg.theme) {
121
+ const themeValidation = validateTheme(cfg.theme);
122
+ if (!themeValidation.valid) {
123
+ errors.push(`Theme: ${themeValidation.errors.join(', ')}`);
124
+ }
125
+ }
126
+ if (cfg.navigation) {
127
+ const navValidation = validateNavigation(cfg.navigation);
128
+ if (!navValidation.valid) {
129
+ errors.push(`Navigation: ${navValidation.errors.join(', ')}`);
130
+ }
131
+ }
132
+ if (cfg.docsRoute && !validateRoute(cfg.docsRoute)) {
133
+ errors.push(`Invalid docsRoute: ${cfg.docsRoute}`);
134
+ }
135
+ return { valid: errors.length === 0, errors };
136
+ }
137
+ /**
138
+ * Create a configuration from minimal user input
139
+ */
140
+ export function createMinimalConfig(options = {}) {
141
+ return mergeConfig(options, DEFAULT_CONFIG);
142
+ }
143
+ /**
144
+ * Export configuration as JSON
145
+ */
146
+ export function exportConfigAsJSON(config) {
147
+ return JSON.stringify(config, null, 2);
148
+ }
149
+ /**
150
+ * Export configuration as YAML
151
+ */
152
+ export function exportConfigAsYAML(config) {
153
+ const lines = [];
154
+ function addValue(key, value, indent = 0) {
155
+ const indentStr = ' '.repeat(indent);
156
+ if (value === null || value === undefined) {
157
+ return;
158
+ }
159
+ if (typeof value === 'string') {
160
+ lines.push(`${indentStr}${key}: ${value}`);
161
+ }
162
+ else if (typeof value === 'boolean' || typeof value === 'number') {
163
+ lines.push(`${indentStr}${key}: ${value}`);
164
+ }
165
+ else if (Array.isArray(value)) {
166
+ lines.push(`${indentStr}${key}:`);
167
+ value.forEach((item, idx) => {
168
+ if (typeof item === 'object') {
169
+ addValue(`- `, item, indent + 1);
170
+ }
171
+ else {
172
+ lines.push(`${indentStr} - ${item}`);
173
+ }
174
+ });
175
+ }
176
+ else if (typeof value === 'object') {
177
+ lines.push(`${indentStr}${key}:`);
178
+ Object.entries(value).forEach(([k, v]) => {
179
+ addValue(k, v, indent + 1);
180
+ });
181
+ }
182
+ }
183
+ Object.entries(config).forEach(([key, value]) => {
184
+ addValue(key, value);
185
+ });
186
+ return lines.join('\n');
187
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Config file parser supporting JSON and YAML formats
3
+ */
4
+ import type { ConfigOptions } from './config';
5
+ export interface ParseResult {
6
+ config: ConfigOptions;
7
+ errors: string[];
8
+ source: 'json' | 'yaml' | 'unknown';
9
+ }
10
+ /**
11
+ * Parse frontmatter from markdown content
12
+ * Supports both JSON and YAML frontmatter
13
+ */
14
+ export declare function parseFrontmatter(content: string): {
15
+ frontmatter: Record<string, unknown> | null;
16
+ body: string;
17
+ error?: string;
18
+ };
19
+ /**
20
+ * Parse config file content (JSON or YAML)
21
+ */
22
+ export declare function parseConfigFile(content: string, filename?: string): ParseResult;
23
+ /**
24
+ * Load and parse a config file from a file path (browser-safe)
25
+ * In a browser environment, use fetch; in Node, use fs
26
+ */
27
+ export declare function loadConfigFile(filePath: string): Promise<ParseResult>;
@@ -0,0 +1,208 @@
1
+ /**
2
+ * Config file parser supporting JSON and YAML formats
3
+ */
4
+ import { validateConfig } from './config';
5
+ /**
6
+ * Parse JSON config file
7
+ */
8
+ function parseJSON(content) {
9
+ try {
10
+ return { data: JSON.parse(content) };
11
+ }
12
+ catch (err) {
13
+ return {
14
+ data: null,
15
+ error: `Invalid JSON: ${err instanceof Error ? err.message : 'Unknown error'}`,
16
+ };
17
+ }
18
+ }
19
+ /**
20
+ * Parse YAML config file (simplified parser)
21
+ * Handles basic YAML key-value pairs and nested objects
22
+ */
23
+ function parseYAML(content) {
24
+ try {
25
+ const result = {};
26
+ const lines = content.split('\n');
27
+ let currentObject = null;
28
+ let currentKey = null;
29
+ let indentStack = [];
30
+ for (let i = 0; i < lines.length; i++) {
31
+ const line = lines[i];
32
+ // Skip empty lines and comments
33
+ if (!line.trim() || line.trim().startsWith('#')) {
34
+ continue;
35
+ }
36
+ // Calculate indentation
37
+ const indent = line.length - line.trimLeft().length;
38
+ const trimmedLine = line.trim();
39
+ // Pop stack if we've decreased indentation
40
+ while (indentStack.length > 0 && indentStack[indentStack.length - 1].indent >= indent) {
41
+ indentStack.pop();
42
+ }
43
+ // Parse key: value
44
+ if (trimmedLine.includes(':')) {
45
+ const [key, ...valueParts] = trimmedLine.split(':');
46
+ const trimmedKey = key.trim();
47
+ const value = valueParts.join(':').trim();
48
+ // Determine parent object
49
+ const parent = indentStack.length > 0 ? indentStack[indentStack.length - 1].obj : result;
50
+ // Parse value
51
+ let parsedValue = value;
52
+ if (value === '') {
53
+ // Empty value - next items might be children
54
+ parsedValue = {};
55
+ indentStack.push({ indent, key: trimmedKey, obj: parsedValue });
56
+ }
57
+ else if (value === 'true') {
58
+ parsedValue = true;
59
+ }
60
+ else if (value === 'false') {
61
+ parsedValue = false;
62
+ }
63
+ else if (/^\d+$/.test(value)) {
64
+ parsedValue = parseInt(value, 10);
65
+ }
66
+ else if (/^\d+\.\d+$/.test(value)) {
67
+ parsedValue = parseFloat(value);
68
+ }
69
+ else if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
70
+ parsedValue = value.slice(1, -1);
71
+ }
72
+ else if (value.startsWith('[') && value.endsWith(']')) {
73
+ try {
74
+ parsedValue = JSON.parse(value);
75
+ }
76
+ catch {
77
+ parsedValue = value;
78
+ }
79
+ }
80
+ else if (value.startsWith('{') && value.endsWith('}')) {
81
+ try {
82
+ parsedValue = JSON.parse(value);
83
+ }
84
+ catch {
85
+ parsedValue = value;
86
+ }
87
+ }
88
+ parent[trimmedKey] = parsedValue;
89
+ currentKey = trimmedKey;
90
+ }
91
+ }
92
+ return { data: result };
93
+ }
94
+ catch (err) {
95
+ return {
96
+ data: null,
97
+ error: `Invalid YAML: ${err instanceof Error ? err.message : 'Unknown error'}`,
98
+ };
99
+ }
100
+ }
101
+ /**
102
+ * Parse frontmatter from markdown content
103
+ * Supports both JSON and YAML frontmatter
104
+ */
105
+ export function parseFrontmatter(content) {
106
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
107
+ if (!frontmatterMatch) {
108
+ return { frontmatter: null, body: content };
109
+ }
110
+ const frontmatterContent = frontmatterMatch[1];
111
+ const body = frontmatterMatch[2];
112
+ // Try JSON first
113
+ let parsed = parseJSON(frontmatterContent);
114
+ // If JSON fails, try YAML
115
+ if (parsed.error) {
116
+ parsed = parseYAML(frontmatterContent);
117
+ }
118
+ if (parsed.error) {
119
+ return {
120
+ frontmatter: null,
121
+ body: content,
122
+ error: `Failed to parse frontmatter: ${parsed.error}`,
123
+ };
124
+ }
125
+ return {
126
+ frontmatter: parsed.data,
127
+ body,
128
+ };
129
+ }
130
+ /**
131
+ * Detect file format from content or filename
132
+ */
133
+ function detectFormat(content, filename) {
134
+ // Check filename extension
135
+ if (filename.endsWith('.json'))
136
+ return 'json';
137
+ if (filename.endsWith('.yaml') || filename.endsWith('.yml'))
138
+ return 'yaml';
139
+ // Try to detect by content
140
+ const trimmed = content.trim();
141
+ if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
142
+ return 'json';
143
+ }
144
+ return 'yaml';
145
+ }
146
+ /**
147
+ * Parse config file content (JSON or YAML)
148
+ */
149
+ export function parseConfigFile(content, filename = 'config.json') {
150
+ const format = detectFormat(content, filename);
151
+ let parsed;
152
+ if (format === 'json') {
153
+ parsed = parseJSON(content);
154
+ }
155
+ else {
156
+ parsed = parseYAML(content);
157
+ }
158
+ if (parsed.error) {
159
+ return {
160
+ config: {},
161
+ errors: [parsed.error],
162
+ source: format,
163
+ };
164
+ }
165
+ const validation = validateConfig(parsed.data);
166
+ return {
167
+ config: parsed.data || {},
168
+ errors: validation.errors,
169
+ source: format,
170
+ };
171
+ }
172
+ /**
173
+ * Load and parse a config file from a file path (browser-safe)
174
+ * In a browser environment, use fetch; in Node, use fs
175
+ */
176
+ export async function loadConfigFile(filePath) {
177
+ try {
178
+ let content;
179
+ if (typeof window !== 'undefined') {
180
+ // Browser environment - use fetch
181
+ const response = await fetch(filePath);
182
+ if (!response.ok) {
183
+ return {
184
+ config: {},
185
+ errors: [`Failed to load config file: ${response.statusText}`],
186
+ source: 'unknown',
187
+ };
188
+ }
189
+ content = await response.text();
190
+ }
191
+ else {
192
+ // Node environment - would need fs module
193
+ return {
194
+ config: {},
195
+ errors: ['Cannot load config file in this environment'],
196
+ source: 'unknown',
197
+ };
198
+ }
199
+ return parseConfigFile(content, filePath);
200
+ }
201
+ catch (err) {
202
+ return {
203
+ config: {},
204
+ errors: [`Error loading config file: ${err instanceof Error ? err.message : 'Unknown error'}`],
205
+ source: 'unknown',
206
+ };
207
+ }
208
+ }