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

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 +45 -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,188 @@
1
+ /**
2
+ * Theme customization system
3
+ * Generates CSS variables from theme configuration
4
+ */
5
+ /**
6
+ * Generate CSS custom properties (variables) from theme config
7
+ * These can be injected into the document or stylesheet
8
+ */
9
+ export function generateCSSVariables(theme) {
10
+ const vars = {};
11
+ // Color variables
12
+ if (theme.primary)
13
+ vars['--color-primary'] = theme.primary;
14
+ if (theme.secondary)
15
+ vars['--color-secondary'] = theme.secondary;
16
+ if (theme.textLight)
17
+ vars['--color-text-light'] = theme.textLight;
18
+ if (theme.textDark)
19
+ vars['--color-text-dark'] = theme.textDark;
20
+ if (theme.bgLight)
21
+ vars['--color-bg-light'] = theme.bgLight;
22
+ if (theme.bgDark)
23
+ vars['--color-bg-dark'] = theme.bgDark;
24
+ if (theme.sidebarBg)
25
+ vars['--color-sidebar-bg'] = theme.sidebarBg;
26
+ if (theme.navbarBg)
27
+ vars['--color-navbar-bg'] = theme.navbarBg;
28
+ if (theme.codeBg)
29
+ vars['--color-code-bg'] = theme.codeBg;
30
+ // Font variables
31
+ if (theme.fontFamily)
32
+ vars['--font-family-body'] = theme.fontFamily;
33
+ if (theme.headingFont)
34
+ vars['--font-family-heading'] = theme.headingFont;
35
+ return vars;
36
+ }
37
+ /**
38
+ * Apply CSS variables to the document root
39
+ */
40
+ export function applyCSSVariables(vars) {
41
+ if (typeof window === 'undefined') {
42
+ return; // Skip in SSR
43
+ }
44
+ const root = document.documentElement;
45
+ Object.entries(vars).forEach(([key, value]) => {
46
+ root.style.setProperty(key, value);
47
+ });
48
+ }
49
+ /**
50
+ * Create a stylesheet string from CSS variables
51
+ * Useful for injecting into <style> tags
52
+ */
53
+ export function createCSSVariablesStylesheet(vars) {
54
+ const entries = Object.entries(vars)
55
+ .map(([key, value]) => ` ${key}: ${value};`)
56
+ .join('\n');
57
+ return `:root {\n${entries}\n}`;
58
+ }
59
+ /**
60
+ * Parse a color value and validate it
61
+ */
62
+ export function parseColor(color) {
63
+ if (!color || typeof color !== 'string') {
64
+ return { valid: false, error: 'Color must be a non-empty string' };
65
+ }
66
+ const trimmed = color.trim();
67
+ // Hex colors
68
+ if (/^#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?([0-9a-fA-F]{2})?$/.test(trimmed)) {
69
+ return { valid: true, value: trimmed };
70
+ }
71
+ // RGB/RGBA
72
+ if (/^rgba?\s*\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}(\s*,\s*[\d.]+)?\s*\)$/.test(trimmed)) {
73
+ return { valid: true, value: trimmed };
74
+ }
75
+ // Named colors (basic list)
76
+ const namedColors = [
77
+ 'red',
78
+ 'blue',
79
+ 'green',
80
+ 'white',
81
+ 'black',
82
+ 'gray',
83
+ 'grey',
84
+ 'transparent',
85
+ 'currentColor',
86
+ ];
87
+ if (namedColors.includes(trimmed.toLowerCase())) {
88
+ return { valid: true, value: trimmed };
89
+ }
90
+ // CSS custom property
91
+ if (/^var\s*\(\s*--[a-zA-Z0-9-]+\s*\)$/.test(trimmed)) {
92
+ return { valid: true, value: trimmed };
93
+ }
94
+ return { valid: false, error: `Invalid color format: ${color}` };
95
+ }
96
+ /**
97
+ * Validate theme configuration
98
+ */
99
+ export function validateTheme(theme) {
100
+ const errors = [];
101
+ if (!theme || typeof theme !== 'object') {
102
+ return { valid: false, errors: ['Theme must be an object'] };
103
+ }
104
+ // Validate colors
105
+ const colorFields = ['primary', 'secondary', 'textLight', 'textDark', 'bgLight', 'bgDark', 'sidebarBg', 'navbarBg', 'codeBg'];
106
+ colorFields.forEach((field) => {
107
+ if (theme[field] !== undefined) {
108
+ const validation = parseColor(theme[field]);
109
+ if (!validation.valid) {
110
+ errors.push(`${field}: ${validation.error}`);
111
+ }
112
+ }
113
+ });
114
+ // Validate fonts
115
+ if (theme.fontFamily !== undefined && typeof theme.fontFamily !== 'string') {
116
+ errors.push('fontFamily must be a string');
117
+ }
118
+ if (theme.headingFont !== undefined && typeof theme.headingFont !== 'string') {
119
+ errors.push('headingFont must be a string');
120
+ }
121
+ return { valid: errors.length === 0, errors };
122
+ }
123
+ /**
124
+ * Merge theme configs, with priority to the first argument
125
+ */
126
+ export function mergeThemes(primary, secondary) {
127
+ return {
128
+ ...secondary,
129
+ ...primary,
130
+ };
131
+ }
132
+ export function getThemeTemplate(template = 'default') {
133
+ const templates = {
134
+ default: {
135
+ primary: '#0066cc',
136
+ secondary: '#ff6b6b',
137
+ textLight: '#333333',
138
+ textDark: '#f0f0f0',
139
+ bgLight: '#ffffff',
140
+ bgDark: '#1a1a1a',
141
+ sidebarBg: '#f5f5f5',
142
+ navbarBg: '#ffffff',
143
+ codeBg: '#f4f4f4',
144
+ fontFamily: 'system-ui, -apple-system, sans-serif',
145
+ headingFont: 'system-ui, -apple-system, sans-serif',
146
+ },
147
+ dark: {
148
+ primary: '#4da6ff',
149
+ secondary: '#ff9999',
150
+ textLight: '#e0e0e0',
151
+ textDark: '#1a1a1a',
152
+ bgLight: '#1a1a1a',
153
+ bgDark: '#0d0d0d',
154
+ sidebarBg: '#262626',
155
+ navbarBg: '#1a1a1a',
156
+ codeBg: '#2d2d2d',
157
+ fontFamily: 'system-ui, -apple-system, sans-serif',
158
+ headingFont: 'system-ui, -apple-system, sans-serif',
159
+ },
160
+ minimal: {
161
+ primary: '#000000',
162
+ secondary: '#666666',
163
+ textLight: '#333333',
164
+ textDark: '#cccccc',
165
+ bgLight: '#ffffff',
166
+ bgDark: '#181818',
167
+ sidebarBg: '#fafafa',
168
+ navbarBg: '#ffffff',
169
+ codeBg: '#eeeeee',
170
+ fontFamily: 'Georgia, serif',
171
+ headingFont: 'Georgia, serif',
172
+ },
173
+ colorful: {
174
+ primary: '#ff006e',
175
+ secondary: '#00d9ff',
176
+ textLight: '#2d3142',
177
+ textDark: '#e0e0e0',
178
+ bgLight: '#fafafa',
179
+ bgDark: '#0d1b2a',
180
+ sidebarBg: '#f0f3ff',
181
+ navbarBg: '#ffffff',
182
+ codeBg: '#f5f5f5',
183
+ fontFamily: 'system-ui, -apple-system, sans-serif',
184
+ headingFont: '"Segoe UI", Tahoma, sans-serif',
185
+ },
186
+ };
187
+ return templates[template] || templates.default;
188
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Highlight search terms in text
3
+ * Returns HTML with highlighted terms wrapped in <mark> tags
4
+ */
5
+ export declare function highlightSearchTerms(text: string, searchQuery: string): string;
6
+ /**
7
+ * Truncate text to a maximum length and ensure it ends at a word boundary
8
+ */
9
+ export declare function truncateText(text: string, maxLength?: number): string;
10
+ /**
11
+ * Extract excerpt around search terms
12
+ */
13
+ export declare function extractExcerpt(text: string, searchQuery: string, maxLength?: number): string;
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Highlight search terms in text
3
+ * Returns HTML with highlighted terms wrapped in <mark> tags
4
+ */
5
+ export function highlightSearchTerms(text, searchQuery) {
6
+ if (!text || !searchQuery.trim()) {
7
+ return text;
8
+ }
9
+ // Split search query into individual terms and escape special regex characters
10
+ const terms = searchQuery
11
+ .trim()
12
+ .split(/\s+/)
13
+ .filter((term) => term.length > 0)
14
+ .map((term) => term.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'));
15
+ if (terms.length === 0) {
16
+ return text;
17
+ }
18
+ // Create a regex that matches any of the terms (case-insensitive)
19
+ const regex = new RegExp(`\\b(${terms.join('|')})\\b`, 'gi');
20
+ // Replace matches with highlighted version
21
+ return text.replace(regex, '<span class="search-highlight">$1</span>');
22
+ }
23
+ /**
24
+ * Truncate text to a maximum length and ensure it ends at a word boundary
25
+ */
26
+ export function truncateText(text, maxLength = 150) {
27
+ if (text.length <= maxLength) {
28
+ return text;
29
+ }
30
+ // Truncate and find the last space
31
+ const truncated = text.substring(0, maxLength);
32
+ const lastSpace = truncated.lastIndexOf(' ');
33
+ if (lastSpace > maxLength * 0.7) {
34
+ // If the last space is relatively close to the end, use it
35
+ return truncated.substring(0, lastSpace) + '...';
36
+ }
37
+ // Otherwise just truncate and add ellipsis
38
+ return truncated + '...';
39
+ }
40
+ /**
41
+ * Extract excerpt around search terms
42
+ */
43
+ export function extractExcerpt(text, searchQuery, maxLength = 200) {
44
+ if (!text || !searchQuery.trim()) {
45
+ return truncateText(text, maxLength);
46
+ }
47
+ const searchTerms = searchQuery
48
+ .trim()
49
+ .split(/\s+/)
50
+ .filter((term) => term.length > 0)
51
+ .map((term) => term.toLowerCase());
52
+ // Find the position of the first search term in the text
53
+ let earliestIndex = text.length;
54
+ for (const term of searchTerms) {
55
+ const index = text.toLowerCase().indexOf(term);
56
+ if (index !== -1 && index < earliestIndex) {
57
+ earliestIndex = index;
58
+ }
59
+ }
60
+ // Extract context around the search term
61
+ let startIndex = Math.max(0, earliestIndex - 50);
62
+ let endIndex = Math.min(text.length, startIndex + maxLength);
63
+ // Adjust if we're too close to the end
64
+ if (endIndex === text.length && startIndex > 0) {
65
+ startIndex = Math.max(0, endIndex - maxLength);
66
+ }
67
+ let excerpt = text.substring(startIndex, endIndex);
68
+ // Remove partial words at the beginning
69
+ if (startIndex > 0) {
70
+ const firstSpace = excerpt.indexOf(' ');
71
+ if (firstSpace !== -1 && firstSpace < 20) {
72
+ excerpt = excerpt.substring(firstSpace + 1);
73
+ }
74
+ }
75
+ // Add ellipsis if needed
76
+ if (startIndex > 0) {
77
+ excerpt = '...' + excerpt;
78
+ }
79
+ if (endIndex < text.length) {
80
+ excerpt = excerpt + '...';
81
+ }
82
+ return excerpt;
83
+ }
@@ -0,0 +1 @@
1
+ export { renderMarkdown, renderMarkdownSync, renderMarkdownWithState, createLoadingResult, extractMetadata, getExcerpt, type MarkdownMetadata, type MarkdownResult, type MarkdownLoadingResult } from './markdown.js';
@@ -0,0 +1 @@
1
+ export { renderMarkdown, renderMarkdownSync, renderMarkdownWithState, createLoadingResult, extractMetadata, getExcerpt } from './markdown.js';
@@ -0,0 +1,40 @@
1
+ export interface MarkdownMetadata {
2
+ title?: string;
3
+ description?: string;
4
+ author?: string;
5
+ date?: string;
6
+ order?: number;
7
+ [key: string]: any;
8
+ }
9
+ export interface MarkdownResult {
10
+ html: string;
11
+ metadata: MarkdownMetadata;
12
+ }
13
+ export interface MarkdownLoadingResult extends MarkdownResult {
14
+ loading: boolean;
15
+ error?: string;
16
+ }
17
+ /**
18
+ * Create a loading result
19
+ */
20
+ export declare function createLoadingResult(): MarkdownLoadingResult;
21
+ /**
22
+ * Render markdown synchronously (browser-safe)
23
+ */
24
+ export declare function renderMarkdownSync(content: unknown): MarkdownResult;
25
+ /**
26
+ * Render markdown (async version, browser-safe)
27
+ */
28
+ export declare function renderMarkdown(content: unknown): MarkdownResult;
29
+ /**
30
+ * Render markdown with loading state
31
+ */
32
+ export declare function renderMarkdownWithState(content: unknown): MarkdownLoadingResult;
33
+ /**
34
+ * Extract metadata from markdown content
35
+ */
36
+ export declare function extractMetadata(content: string): MarkdownMetadata;
37
+ /**
38
+ * Get excerpt from markdown content
39
+ */
40
+ export declare function getExcerpt(content: string, wordLimit?: number): string;
@@ -0,0 +1,165 @@
1
+ import { marked } from 'marked';
2
+ /**
3
+ * Browser-safe frontmatter parser (no Buffer dependency)
4
+ */
5
+ function parseFrontmatter(content) {
6
+ const frontmatterRegex = /^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/;
7
+ const match = content.match(frontmatterRegex);
8
+ if (!match) {
9
+ return { data: {}, content };
10
+ }
11
+ const frontmatterStr = match[1];
12
+ const markdownContent = match[2];
13
+ // Parse YAML-like frontmatter (simple key: value pairs)
14
+ const data = {};
15
+ const lines = frontmatterStr.split('\n');
16
+ for (const line of lines) {
17
+ const colonIndex = line.indexOf(':');
18
+ if (colonIndex > 0) {
19
+ const key = line.slice(0, colonIndex).trim();
20
+ let value = line.slice(colonIndex + 1).trim();
21
+ // Remove quotes if present
22
+ if ((value.startsWith('"') && value.endsWith('"')) ||
23
+ (value.startsWith("'") && value.endsWith("'"))) {
24
+ value = value.slice(1, -1);
25
+ }
26
+ // Parse numbers
27
+ if (/^\d+$/.test(value)) {
28
+ value = parseInt(value, 10);
29
+ }
30
+ else if (/^\d+\.\d+$/.test(value)) {
31
+ value = parseFloat(value);
32
+ }
33
+ // Parse booleans
34
+ if (value === 'true')
35
+ value = true;
36
+ if (value === 'false')
37
+ value = false;
38
+ data[key] = value;
39
+ }
40
+ }
41
+ return { data, content: markdownContent };
42
+ }
43
+ /**
44
+ * Create a custom renderer that escapes raw HTML
45
+ */
46
+ function createSafeRenderer() {
47
+ const renderer = new marked.Renderer();
48
+ renderer.html = function (token) {
49
+ const html = token.text;
50
+ const escaped = html
51
+ .replace(/&/g, '&amp;')
52
+ .replace(/</g, '&lt;')
53
+ .replace(/>/g, '&gt;')
54
+ .replace(/"/g, '&quot;')
55
+ .replace(/'/g, '&#39;');
56
+ return `<p>${escaped}</p>\n`;
57
+ };
58
+ return renderer;
59
+ }
60
+ const markedOptions = {
61
+ breaks: true,
62
+ gfm: true,
63
+ async: false,
64
+ renderer: createSafeRenderer()
65
+ };
66
+ /**
67
+ * Validate content input
68
+ */
69
+ function validateContent(content) {
70
+ if (content === undefined || content === null) {
71
+ throw new Error('Content is undefined or null');
72
+ }
73
+ if (typeof content !== 'string') {
74
+ throw new Error(`Content must be a string, received ${typeof content}`);
75
+ }
76
+ return content;
77
+ }
78
+ /**
79
+ * Create a loading result
80
+ */
81
+ export function createLoadingResult() {
82
+ return {
83
+ html: '',
84
+ metadata: {},
85
+ loading: true
86
+ };
87
+ }
88
+ /**
89
+ * Render markdown synchronously (browser-safe)
90
+ */
91
+ export function renderMarkdownSync(content) {
92
+ try {
93
+ const validContent = validateContent(content);
94
+ if (validContent.trim().length === 0) {
95
+ return { html: '', metadata: {} };
96
+ }
97
+ const { data, content: markdownContent } = parseFrontmatter(validContent);
98
+ const html = marked.parse(markdownContent, markedOptions);
99
+ return {
100
+ html: html || '',
101
+ metadata: data
102
+ };
103
+ }
104
+ catch (error) {
105
+ console.error('Error rendering markdown:', error);
106
+ return {
107
+ html: `<p class="markdown-error">Error: ${error instanceof Error ? error.message : 'Unknown error'}</p>`,
108
+ metadata: {}
109
+ };
110
+ }
111
+ }
112
+ /**
113
+ * Render markdown (async version, browser-safe)
114
+ */
115
+ export function renderMarkdown(content) {
116
+ return renderMarkdownSync(content);
117
+ }
118
+ /**
119
+ * Render markdown with loading state
120
+ */
121
+ export function renderMarkdownWithState(content) {
122
+ const result = renderMarkdownSync(content);
123
+ return { ...result, loading: false };
124
+ }
125
+ /**
126
+ * Extract metadata from markdown content
127
+ */
128
+ export function extractMetadata(content) {
129
+ try {
130
+ const { data } = parseFrontmatter(content);
131
+ return data;
132
+ }
133
+ catch (error) {
134
+ console.error('Error extracting metadata:', error);
135
+ return {};
136
+ }
137
+ }
138
+ /**
139
+ * Get excerpt from markdown content
140
+ */
141
+ export function getExcerpt(content, wordLimit = 150) {
142
+ try {
143
+ if (!content || content.trim().length === 0) {
144
+ return '';
145
+ }
146
+ const { content: markdownContent } = parseFrontmatter(content);
147
+ const text = markdownContent
148
+ .replace(/#{1,6}\s/g, '')
149
+ .replace(/[*_]{1,2}(.*?)[*_]{1,2}/g, '$1')
150
+ .replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
151
+ .replace(/`([^`]+)`/g, '$1')
152
+ .replace(/^>\s/gm, '')
153
+ .trim();
154
+ const words = text.split(/\s+/).filter(word => word.length > 0);
155
+ if (words.length === 0) {
156
+ return '';
157
+ }
158
+ const excerpt = words.slice(0, wordLimit).join(' ');
159
+ return excerpt.length < text.length ? excerpt + '...' : excerpt;
160
+ }
161
+ catch (error) {
162
+ console.error('Error extracting excerpt:', error);
163
+ return '';
164
+ }
165
+ }
package/package.json CHANGED
@@ -1,44 +1,66 @@
1
1
  {
2
2
  "name": "@alliance-droid/svelte-docs-system",
3
- "version": "0.0.2",
3
+ "version": "0.1.1",
4
4
  "type": "module",
5
- "bin": {
6
- "svelte-docs-init": "./bin/init.js"
5
+ "description": "Drop-in documentation system for SvelteKit - just add markdown files",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "svelte": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ },
14
+ "./plugin": {
15
+ "types": "./dist/plugin.d.ts",
16
+ "default": "./dist/plugin.js"
17
+ }
7
18
  },
19
+ "svelte": "./dist/index.js",
20
+ "files": [
21
+ "dist",
22
+ "!dist/**/*.test.*"
23
+ ],
8
24
  "scripts": {
9
25
  "dev": "vite dev",
10
- "build": "vite build && pagefind",
26
+ "build": "vite build && npm run package",
27
+ "package": "svelte-kit sync && svelte-package -o dist",
11
28
  "preview": "vite preview",
12
29
  "prepare": "svelte-kit sync || echo ''",
30
+ "prepublishOnly": "npm run package",
13
31
  "test": "vitest",
14
- "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
15
- "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
32
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json"
33
+ },
34
+ "peerDependencies": {
35
+ "svelte": "^5.0.0",
36
+ "@sveltejs/kit": "^2.0.0"
37
+ },
38
+ "dependencies": {
39
+ "gray-matter": "^4.0.3",
40
+ "marked": "^17.0.1"
16
41
  },
17
42
  "devDependencies": {
18
43
  "@sveltejs/adapter-auto": "^7.0.0",
19
- "@sveltejs/adapter-static": "^3.0.10",
20
- "@sveltejs/adapter-vercel": "^6.3.1",
21
44
  "@sveltejs/kit": "^2.50.1",
45
+ "@sveltejs/package": "^2.3.10",
22
46
  "@sveltejs/vite-plugin-svelte": "^6.2.4",
23
- "@testing-library/svelte": "^5.3.1",
24
- "@testing-library/user-event": "^14.6.1",
25
- "autoprefixer": "^10.4.24",
26
- "happy-dom": "^20.5.0",
27
- "jsdom": "^28.0.0",
28
- "pagefind": "^1.4.0",
29
- "postcss": "^8.5.6",
47
+ "@types/node": "^22.15.29",
30
48
  "svelte": "^5.48.2",
31
49
  "svelte-check": "^4.3.5",
32
- "tailwindcss": "^4.1.18",
33
50
  "typescript": "^5.9.3",
34
51
  "vite": "^7.3.1",
35
52
  "vitest": "^4.0.18"
36
53
  },
37
- "dependencies": {
38
- "@fortawesome/fontawesome-free": "^7.1.0",
39
- "gray-matter": "^4.0.3",
40
- "marked": "^17.0.1",
41
- "resize-observer-polyfill": "^1.5.1",
42
- "svelte-component-library": "^0.2.1"
43
- }
54
+ "keywords": [
55
+ "svelte",
56
+ "sveltekit",
57
+ "documentation",
58
+ "markdown",
59
+ "docs"
60
+ ],
61
+ "repository": {
62
+ "type": "git",
63
+ "url": "https://github.com/alliance-droid/svelte-docs-system"
64
+ },
65
+ "license": "MIT"
44
66
  }