@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.
- package/README.md +155 -23
- package/dist/components/APITable.svelte.d.ts +21 -0
- package/dist/components/Breadcrumbs.svelte.d.ts +14 -0
- package/dist/components/Callout.svelte.d.ts +15 -0
- package/dist/components/CodeBlock.svelte.d.ts +12 -0
- package/{src/lib → dist}/components/DocLayout.svelte +18 -6
- package/dist/components/DocLayout.svelte.d.ts +18 -0
- package/dist/components/DocsPage.svelte +39 -0
- package/dist/components/DocsPage.svelte.d.ts +8 -0
- package/dist/components/Documentation.svelte +639 -0
- package/dist/components/Footer.svelte.d.ts +10 -0
- package/dist/components/Image.svelte.d.ts +15 -0
- package/{src/lib → dist}/components/Navbar.svelte +4 -4
- package/dist/components/Navbar.svelte.d.ts +10 -0
- package/{src/lib → dist}/components/Search.svelte +2 -2
- package/dist/components/Search.svelte.d.ts +6 -0
- package/{template-starter/src/lib → dist}/components/Sidebar.svelte +2 -2
- package/dist/components/Sidebar.svelte.d.ts +9 -0
- package/dist/components/Tabs.svelte.d.ts +16 -0
- package/dist/config.d.ts +93 -0
- package/dist/config.js +89 -0
- package/dist/configLoader.d.ts +48 -0
- package/dist/configLoader.js +187 -0
- package/dist/configParser.d.ts +27 -0
- package/dist/configParser.js +208 -0
- package/{template-starter/src/lib/index.ts → dist/index.d.ts} +6 -7
- package/dist/index.js +18 -0
- package/dist/navigationBuilder.d.ts +64 -0
- package/dist/navigationBuilder.js +225 -0
- package/dist/plugin.d.ts +30 -0
- package/dist/plugin.js +172 -0
- package/dist/routing.d.ts +48 -0
- package/dist/routing.js +92 -0
- package/dist/stores/i18n.d.ts +20 -0
- package/dist/stores/i18n.js +119 -0
- package/dist/stores/nav.d.ts +20 -0
- package/dist/stores/nav.js +15 -0
- package/dist/stores/search.d.ts +49 -0
- package/dist/stores/search.js +127 -0
- package/dist/stores/theme.d.ts +7 -0
- package/dist/stores/theme.js +152 -0
- package/dist/stores/version.d.ts +18 -0
- package/dist/stores/version.js +93 -0
- package/dist/themeCustomization.d.ts +46 -0
- package/dist/themeCustomization.js +188 -0
- package/dist/utils/highlight.d.ts +13 -0
- package/dist/utils/highlight.js +83 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/markdown.d.ts +40 -0
- package/dist/utils/markdown.js +165 -0
- package/package.json +44 -23
- package/COMPONENTS.md +0 -365
- package/COVERAGE_REPORT.md +0 -663
- package/SEARCH_VERIFICATION.md +0 -229
- package/TEST_SUMMARY.md +0 -344
- package/bin/init.js +0 -821
- package/docs/COMPONENT_LIBRARY_INTEGRATION_REPORT.md +0 -153
- package/docs/DARK_MODE_AUDIT_REPORT.md +0 -403
- package/docs/E2E_TESTS.md +0 -354
- package/docs/TESTING.md +0 -754
- package/docs/THEME_INHERITANCE.md +0 -192
- package/docs/de/index.md +0 -41
- package/docs/en/COMPONENTS.md +0 -443
- package/docs/en/api/examples.md +0 -100
- package/docs/en/api/overview.md +0 -69
- package/docs/en/components/index.md +0 -622
- package/docs/en/config/navigation.md +0 -505
- package/docs/en/config/theme-and-colors.md +0 -395
- package/docs/en/getting-started/integration.md +0 -406
- package/docs/en/guides/common-setups.md +0 -651
- package/docs/en/index.md +0 -243
- package/docs/en/markdown.md +0 -102
- package/docs/en/routing.md +0 -64
- package/docs/en/setup.md +0 -52
- package/docs/en/troubleshooting.md +0 -704
- package/docs/es/index.md +0 -41
- package/docs/fr/index.md +0 -41
- package/docs/ja/index.md +0 -41
- package/pagefind.toml +0 -8
- package/postcss.config.js +0 -5
- package/src/app.css +0 -119
- package/src/app.d.ts +0 -13
- package/src/app.html +0 -11
- package/src/lib/components/APITable.test.ts +0 -153
- package/src/lib/components/Breadcrumbs.test.ts +0 -148
- package/src/lib/components/Callout.test.ts +0 -100
- package/src/lib/components/CodeBlock.test.ts +0 -133
- package/src/lib/components/Image.test.ts +0 -163
- package/src/lib/components/Sidebar.svelte +0 -110
- package/src/lib/components/Tabs.test.ts +0 -102
- package/src/lib/config.test.ts +0 -140
- package/src/lib/config.ts +0 -179
- package/src/lib/configIntegration.test.ts +0 -272
- package/src/lib/configLoader.ts +0 -231
- package/src/lib/configParser.test.ts +0 -217
- package/src/lib/configParser.ts +0 -234
- package/src/lib/index.ts +0 -37
- package/src/lib/integration.test.ts +0 -426
- package/src/lib/navigationBuilder.test.ts +0 -338
- package/src/lib/navigationBuilder.ts +0 -268
- package/src/lib/performance.test.ts +0 -369
- package/src/lib/routing.test.ts +0 -202
- package/src/lib/routing.ts +0 -127
- package/src/lib/search-functionality.test.ts +0 -493
- package/src/lib/stores/i18n.test.ts +0 -180
- package/src/lib/stores/i18n.ts +0 -143
- package/src/lib/stores/nav.ts +0 -36
- package/src/lib/stores/search.test.ts +0 -140
- package/src/lib/stores/search.ts +0 -162
- package/src/lib/stores/theme.test.ts +0 -117
- package/src/lib/stores/theme.ts +0 -167
- package/src/lib/stores/version.test.ts +0 -139
- package/src/lib/stores/version.ts +0 -111
- package/src/lib/themeCustomization.test.ts +0 -223
- package/src/lib/themeCustomization.ts +0 -212
- package/src/lib/utils/highlight.test.ts +0 -136
- package/src/lib/utils/highlight.ts +0 -100
- package/src/lib/utils/index.ts +0 -7
- package/src/lib/utils/markdown.test.ts +0 -357
- package/src/lib/utils/markdown.ts +0 -77
- package/src/routes/+layout.server.ts +0 -1
- package/src/routes/+layout.svelte +0 -29
- package/src/routes/+page.svelte +0 -165
- package/src/routes/quote-demo/+page.svelte +0 -141
- package/static/robots.txt +0 -3
- package/svelte.config.js +0 -15
- package/tailwind.config.ts +0 -55
- package/template-starter/.github/workflows/build.yml +0 -40
- package/template-starter/.github/workflows/deploy-github-pages.yml +0 -47
- package/template-starter/.github/workflows/deploy-netlify.yml +0 -41
- package/template-starter/.github/workflows/deploy-vercel.yml +0 -64
- package/template-starter/NPM-PACKAGE-SETUP.md +0 -233
- package/template-starter/README.md +0 -320
- package/template-starter/docs/_config.json +0 -39
- package/template-starter/docs/api/components.md +0 -257
- package/template-starter/docs/api/overview.md +0 -169
- package/template-starter/docs/guides/configuration.md +0 -145
- package/template-starter/docs/guides/github-pages-deployment.md +0 -254
- package/template-starter/docs/guides/netlify-deployment.md +0 -159
- package/template-starter/docs/guides/vercel-deployment.md +0 -131
- package/template-starter/docs/index.md +0 -49
- package/template-starter/docs/setup.md +0 -149
- package/template-starter/package.json +0 -31
- package/template-starter/pagefind.toml +0 -3
- package/template-starter/postcss.config.js +0 -5
- package/template-starter/src/app.css +0 -34
- package/template-starter/src/app.d.ts +0 -13
- package/template-starter/src/app.html +0 -11
- package/template-starter/src/lib/components/APITable.svelte +0 -120
- package/template-starter/src/lib/components/APITable.test.ts +0 -96
- package/template-starter/src/lib/components/Breadcrumbs.svelte +0 -85
- package/template-starter/src/lib/components/Breadcrumbs.test.ts +0 -82
- package/template-starter/src/lib/components/Callout.svelte +0 -60
- package/template-starter/src/lib/components/Callout.test.ts +0 -91
- package/template-starter/src/lib/components/CodeBlock.svelte +0 -68
- package/template-starter/src/lib/components/CodeBlock.test.ts +0 -62
- package/template-starter/src/lib/components/DocLayout.svelte +0 -84
- package/template-starter/src/lib/components/Footer.svelte +0 -78
- package/template-starter/src/lib/components/Image.svelte +0 -100
- package/template-starter/src/lib/components/Image.test.ts +0 -81
- package/template-starter/src/lib/components/Navbar.svelte +0 -141
- package/template-starter/src/lib/components/Search.svelte +0 -248
- package/template-starter/src/lib/components/Tabs.svelte +0 -48
- package/template-starter/src/lib/components/Tabs.test.ts +0 -89
- package/template-starter/src/routes/+layout.svelte +0 -28
- package/template-starter/src/routes/+page.svelte +0 -92
- package/template-starter/svelte.config.js +0 -17
- package/template-starter/tailwind.config.ts +0 -17
- package/template-starter/tsconfig.json +0 -13
- package/template-starter/vite.config.ts +0 -6
- package/tests/e2e/example.spec.ts +0 -345
- package/tsconfig.json +0 -20
- package/vite.config.ts +0 -6
- package/vitest.config.ts +0 -33
- package/vitest.setup.ts +0 -21
- /package/{src/lib → dist}/assets/favicon.svg +0 -0
- /package/{src/lib → dist}/components/APITable.svelte +0 -0
- /package/{src/lib → dist}/components/Breadcrumbs.svelte +0 -0
- /package/{src/lib → dist}/components/Callout.svelte +0 -0
- /package/{src/lib → dist}/components/CodeBlock.svelte +0 -0
- /package/{src/lib → dist}/components/Footer.svelte +0 -0
- /package/{src/lib → dist}/components/Image.svelte +0 -0
- /package/{src/lib → dist}/components/Tabs.svelte +0 -0
- /package/{src/lib → dist}/svelte-component-library.d.ts +0 -0
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Unit tests for CodeBlock component
|
|
5
|
-
* Tests code formatting and syntax highlighting
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
describe('CodeBlock Component', () => {
|
|
9
|
-
describe('Code Input', () => {
|
|
10
|
-
it('should accept code as string', () => {
|
|
11
|
-
const code = 'console.log("hello")';
|
|
12
|
-
expect(typeof code).toBe('string');
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it('should accept empty code string', () => {
|
|
16
|
-
const code = '';
|
|
17
|
-
expect(code.length).toBe(0);
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('should preserve whitespace and indentation', () => {
|
|
21
|
-
const code = `function example() {
|
|
22
|
-
return true;
|
|
23
|
-
}`;
|
|
24
|
-
expect(code).toContain(' ');
|
|
25
|
-
expect(code).toContain('\n');
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('should handle special characters', () => {
|
|
29
|
-
const code = 'const str = "hello<world>&friends";';
|
|
30
|
-
expect(code).toContain('<');
|
|
31
|
-
expect(code).toContain('>');
|
|
32
|
-
expect(code).toContain('&');
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
describe('Language Detection', () => {
|
|
37
|
-
it('should support common programming languages', () => {
|
|
38
|
-
const languages = ['javascript', 'typescript', 'python', 'rust', 'bash', 'json', 'html', 'css'];
|
|
39
|
-
languages.forEach((lang) => {
|
|
40
|
-
expect(typeof lang).toBe('string');
|
|
41
|
-
expect(lang.length).toBeGreaterThan(0);
|
|
42
|
-
});
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it('should accept language as prop', () => {
|
|
46
|
-
const language = 'typescript';
|
|
47
|
-
expect(typeof language).toBe('string');
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('should default to plain text if language not provided', () => {
|
|
51
|
-
const defaultLanguage = 'plaintext';
|
|
52
|
-
expect(defaultLanguage).toBeDefined();
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it('should detect language from code fence', () => {
|
|
56
|
-
const fence = '```javascript';
|
|
57
|
-
const match = fence.match(/```(\w+)?/);
|
|
58
|
-
expect(match).toBeTruthy();
|
|
59
|
-
if (match && match[1]) {
|
|
60
|
-
expect(match[1]).toBe('javascript');
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
describe('Syntax Highlighting', () => {
|
|
66
|
-
it('should apply syntax highlighting tokens', () => {
|
|
67
|
-
const token = {
|
|
68
|
-
type: 'keyword',
|
|
69
|
-
content: 'function',
|
|
70
|
-
class: 'hljs-keyword'
|
|
71
|
-
};
|
|
72
|
-
expect(token.type).toBeDefined();
|
|
73
|
-
expect(token.content).toBeDefined();
|
|
74
|
-
expect(token.class).toBeTruthy();
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('should support dark mode highlighting', () => {
|
|
78
|
-
const colorSchemes = ['light', 'dark'];
|
|
79
|
-
colorSchemes.forEach((scheme) => {
|
|
80
|
-
expect(['light', 'dark']).toContain(scheme);
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
describe('Copy Button', () => {
|
|
86
|
-
it('should have copy functionality', () => {
|
|
87
|
-
const hasCopyButton = true;
|
|
88
|
-
expect(hasCopyButton).toBe(true);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it('should copy entire code block', () => {
|
|
92
|
-
const code = 'const x = 42;';
|
|
93
|
-
const copied = code;
|
|
94
|
-
expect(copied).toBe(code);
|
|
95
|
-
});
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
describe('Line Numbers', () => {
|
|
99
|
-
it('should support optional line numbers', () => {
|
|
100
|
-
const showLineNumbers = true;
|
|
101
|
-
expect(typeof showLineNumbers).toBe('boolean');
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
it('should number lines correctly', () => {
|
|
105
|
-
const lines = [
|
|
106
|
-
'line 1',
|
|
107
|
-
'line 2',
|
|
108
|
-
'line 3'
|
|
109
|
-
];
|
|
110
|
-
lines.forEach((line, index) => {
|
|
111
|
-
expect(index + 1).toBeGreaterThan(0);
|
|
112
|
-
});
|
|
113
|
-
});
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
describe('Accessibility', () => {
|
|
117
|
-
it('should be keyboard accessible', () => {
|
|
118
|
-
const canCopyWithKeyboard = true;
|
|
119
|
-
expect(canCopyWithKeyboard).toBe(true);
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
it('should have proper ARIA labels', () => {
|
|
123
|
-
const ariaLabel = 'Code block, javascript';
|
|
124
|
-
expect(ariaLabel).toBeTruthy();
|
|
125
|
-
expect(typeof ariaLabel).toBe('string');
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
it('should announce copy feedback to screen readers', () => {
|
|
129
|
-
const announcement = 'Code copied to clipboard';
|
|
130
|
-
expect(announcement).toBeTruthy();
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
});
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Unit tests for Image component
|
|
5
|
-
* Tests image rendering, optimization, and accessibility
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
describe('Image Component', () => {
|
|
9
|
-
describe('Image Props', () => {
|
|
10
|
-
it('should require src attribute', () => {
|
|
11
|
-
const src = '/images/example.png';
|
|
12
|
-
expect(src).toBeDefined();
|
|
13
|
-
expect(typeof src).toBe('string');
|
|
14
|
-
expect(src.startsWith('/')).toBe(true);
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it('should require alt text for accessibility', () => {
|
|
18
|
-
const alt = 'A description of the image';
|
|
19
|
-
expect(alt).toBeDefined();
|
|
20
|
-
expect(typeof alt).toBe('string');
|
|
21
|
-
expect(alt.length).toBeGreaterThan(0);
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it('should accept various image formats', () => {
|
|
25
|
-
const formats = ['.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg'];
|
|
26
|
-
const validSrc = 'image.webp';
|
|
27
|
-
expect(formats.some((fmt) => validSrc.endsWith(fmt))).toBe(true);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it('should accept optional width and height', () => {
|
|
31
|
-
const width = 800;
|
|
32
|
-
const height = 600;
|
|
33
|
-
expect(typeof width).toBe('number');
|
|
34
|
-
expect(typeof height).toBe('number');
|
|
35
|
-
expect(width).toBeGreaterThan(0);
|
|
36
|
-
expect(height).toBeGreaterThan(0);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('should accept optional caption', () => {
|
|
40
|
-
const caption = 'Figure 1: Example screenshot';
|
|
41
|
-
expect(typeof caption).toBe('string');
|
|
42
|
-
});
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
describe('Image Optimization', () => {
|
|
46
|
-
it('should support responsive images with srcset', () => {
|
|
47
|
-
const srcset =
|
|
48
|
-
'/img/small.webp 640w, /img/medium.webp 1024w, /img/large.webp 1920w';
|
|
49
|
-
expect(srcset).toContain('640w');
|
|
50
|
-
expect(srcset).toContain('1024w');
|
|
51
|
-
expect(srcset).toContain('1920w');
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('should support multiple image formats with picture element', () => {
|
|
55
|
-
const formats = ['webp', 'jpg', 'png'];
|
|
56
|
-
formats.forEach((fmt) => {
|
|
57
|
-
expect(['webp', 'jpg', 'png']).toContain(fmt);
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it('should lazy load images by default', () => {
|
|
62
|
-
const loading = 'lazy';
|
|
63
|
-
expect(['lazy', 'eager']).toContain(loading);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it('should support eager loading when needed', () => {
|
|
67
|
-
const loading = 'eager';
|
|
68
|
-
expect(['lazy', 'eager']).toContain(loading);
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
describe('Responsive Behavior', () => {
|
|
73
|
-
it('should support CSS aspect ratio', () => {
|
|
74
|
-
const aspectRatio = '16/9';
|
|
75
|
-
expect(aspectRatio).toContain('/');
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it('should preserve aspect ratio', () => {
|
|
79
|
-
const width = 800;
|
|
80
|
-
const height = 600;
|
|
81
|
-
const aspectRatio = width / height;
|
|
82
|
-
expect(aspectRatio).toBeCloseTo(1.33, 1);
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it('should scale to container width', () => {
|
|
86
|
-
const maxWidth = '100%';
|
|
87
|
-
expect(maxWidth).toBe('100%');
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
describe('Figure and Caption', () => {
|
|
92
|
-
it('should wrap in figure element', () => {
|
|
93
|
-
const element = 'figure';
|
|
94
|
-
expect(element).toBe('figure');
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
it('should support caption with figcaption', () => {
|
|
98
|
-
const caption = 'Example figure caption';
|
|
99
|
-
expect(caption).toBeTruthy();
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it('should associate caption with image', () => {
|
|
103
|
-
const figcaptionId = 'img-caption-1';
|
|
104
|
-
const ariaDescribedBy = 'img-caption-1';
|
|
105
|
-
expect(ariaDescribedBy).toBe(figcaptionId);
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
describe('Accessibility', () => {
|
|
110
|
-
it('should have descriptive alt text', () => {
|
|
111
|
-
const alt = 'A screenshot showing the dashboard with user metrics';
|
|
112
|
-
expect(alt.length).toBeGreaterThan(10);
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
it('should not have empty alt text', () => {
|
|
116
|
-
const alt = 'Important diagram';
|
|
117
|
-
expect(alt.length).toBeGreaterThan(0);
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
it('should avoid decorative image alt text', () => {
|
|
121
|
-
const decorativeAlt = 'spacer';
|
|
122
|
-
const meaningfulAlt = 'Navigation menu icon';
|
|
123
|
-
expect(meaningfulAlt.length).toBeGreaterThan(decorativeAlt.length);
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
it('should have proper figure structure', () => {
|
|
127
|
-
const figureElement = 'figure';
|
|
128
|
-
const figcaptionElement = 'figcaption';
|
|
129
|
-
expect(figureElement).toBeDefined();
|
|
130
|
-
expect(figcaptionElement).toBeDefined();
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
it('should support extended descriptions for complex images', () => {
|
|
134
|
-
const longdesc = '/docs/image-description.html';
|
|
135
|
-
expect(longdesc).toBeTruthy();
|
|
136
|
-
});
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
describe('Dark Mode Support', () => {
|
|
140
|
-
it('should support dark mode styling', () => {
|
|
141
|
-
const lightClass = 'border-gray-200';
|
|
142
|
-
const darkClass = 'dark:border-gray-700';
|
|
143
|
-
expect(darkClass).toContain('dark:');
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
it('should maintain contrast in dark mode', () => {
|
|
147
|
-
const darkModeEnabled = true;
|
|
148
|
-
expect(darkModeEnabled).toBe(true);
|
|
149
|
-
});
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
describe('Browser Support', () => {
|
|
153
|
-
it('should provide fallback for old browsers', () => {
|
|
154
|
-
const hasFallback = true;
|
|
155
|
-
expect(hasFallback).toBe(true);
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
it('should support webp with fallback', () => {
|
|
159
|
-
const hasPicture = true;
|
|
160
|
-
expect(hasPicture).toBe(true);
|
|
161
|
-
});
|
|
162
|
-
});
|
|
163
|
-
});
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { NavSection, NavItem } from '$lib/stores/nav';
|
|
3
|
-
import { sidebarOpen } from '$lib/stores/nav';
|
|
4
|
-
|
|
5
|
-
let {
|
|
6
|
-
sections = [] as NavSection[],
|
|
7
|
-
currentPath = '',
|
|
8
|
-
onNavigate = () => {},
|
|
9
|
-
}: {
|
|
10
|
-
sections?: NavSection[];
|
|
11
|
-
currentPath?: string;
|
|
12
|
-
onNavigate?: (path: string) => void;
|
|
13
|
-
} = $props();
|
|
14
|
-
|
|
15
|
-
function handleNavClick(path: string) {
|
|
16
|
-
onNavigate(path);
|
|
17
|
-
sidebarOpen.set(false);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function isActive(href: string | undefined): boolean {
|
|
21
|
-
if (!href) return false;
|
|
22
|
-
return currentPath === href || currentPath.startsWith(href + '/');
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function renderNavItem(item: NavItem) {
|
|
26
|
-
const active = isActive(item.href);
|
|
27
|
-
return {
|
|
28
|
-
label: item.label,
|
|
29
|
-
href: item.href,
|
|
30
|
-
children: item.children,
|
|
31
|
-
active,
|
|
32
|
-
icon: item.icon,
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
</script>
|
|
36
|
-
|
|
37
|
-
<!-- Sidebar Overlay for Mobile -->
|
|
38
|
-
{#if $sidebarOpen}
|
|
39
|
-
<button
|
|
40
|
-
class="fixed inset-0 z-30 bg-black/20 md:hidden"
|
|
41
|
-
onclick={() => sidebarOpen.set(false)}
|
|
42
|
-
aria-label="Close menu"
|
|
43
|
-
></button>
|
|
44
|
-
{/if}
|
|
45
|
-
|
|
46
|
-
<!-- Sidebar -->
|
|
47
|
-
<aside
|
|
48
|
-
class="fixed left-0 top-16 bottom-0 w-64 overflow-y-auto border-r border-claude-border dark:border-claude-dark-border bg-white dark:bg-claude-dark-bg-secondary transition-transform md:relative md:top-0 {$sidebarOpen
|
|
49
|
-
? 'translate-x-0'
|
|
50
|
-
: '-translate-x-full md:translate-x-0'} z-30 md:z-auto"
|
|
51
|
-
>
|
|
52
|
-
<div class="p-6 space-y-8">
|
|
53
|
-
{#each sections as section (section.title)}
|
|
54
|
-
<div>
|
|
55
|
-
<h3 class="text-sm font-semibold text-claude-text dark:text-claude-dark-text uppercase tracking-wide mb-3 opacity-60">
|
|
56
|
-
{section.title}
|
|
57
|
-
</h3>
|
|
58
|
-
<nav class="space-y-2">
|
|
59
|
-
{#each section.items as item (item.label)}
|
|
60
|
-
<a
|
|
61
|
-
href={item.href || '#'}
|
|
62
|
-
onclick={(e) => {
|
|
63
|
-
if (item.href) {
|
|
64
|
-
e.preventDefault();
|
|
65
|
-
handleNavClick(item.href);
|
|
66
|
-
}
|
|
67
|
-
}}
|
|
68
|
-
class="block px-3 py-2 rounded-lg transition-colors {isActive(
|
|
69
|
-
item.href
|
|
70
|
-
)
|
|
71
|
-
? 'bg-claude-accent text-white dark:bg-claude-dark-accent'
|
|
72
|
-
: 'text-claude-text dark:text-claude-dark-text hover:bg-claude-bg-secondary dark:hover:bg-claude-dark-bg'}"
|
|
73
|
-
>
|
|
74
|
-
<span class="flex items-center gap-2">
|
|
75
|
-
{#if item.icon}
|
|
76
|
-
<span class="text-sm">{item.icon}</span>
|
|
77
|
-
{/if}
|
|
78
|
-
<span class="text-sm font-medium">{item.label}</span>
|
|
79
|
-
</span>
|
|
80
|
-
</a>
|
|
81
|
-
|
|
82
|
-
<!-- Nested Items -->
|
|
83
|
-
{#if item.children && item.children.length > 0}
|
|
84
|
-
<div class="ml-3 space-y-1 border-l border-claude-border dark:border-claude-dark-border pl-3">
|
|
85
|
-
{#each item.children as child (child.label)}
|
|
86
|
-
<a
|
|
87
|
-
href={child.href || '#'}
|
|
88
|
-
onclick={(e) => {
|
|
89
|
-
if (child.href) {
|
|
90
|
-
e.preventDefault();
|
|
91
|
-
handleNavClick(child.href);
|
|
92
|
-
}
|
|
93
|
-
}}
|
|
94
|
-
class="block px-3 py-1 text-xs rounded transition-colors {isActive(
|
|
95
|
-
child.href
|
|
96
|
-
)
|
|
97
|
-
? 'bg-claude-accent text-white dark:bg-claude-dark-accent'
|
|
98
|
-
: 'text-claude-text-secondary dark:text-claude-dark-text-secondary hover:text-claude-text dark:hover:text-claude-dark-text'}"
|
|
99
|
-
>
|
|
100
|
-
{child.label}
|
|
101
|
-
</a>
|
|
102
|
-
{/each}
|
|
103
|
-
</div>
|
|
104
|
-
{/if}
|
|
105
|
-
{/each}
|
|
106
|
-
</nav>
|
|
107
|
-
</div>
|
|
108
|
-
{/each}
|
|
109
|
-
</div>
|
|
110
|
-
</aside>
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Unit tests for Tabs component
|
|
5
|
-
* Tests component structure and tab handling logic
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
describe('Tabs Component', () => {
|
|
9
|
-
describe('Tab Props', () => {
|
|
10
|
-
it('should accept array of tabs', () => {
|
|
11
|
-
const tabs = [
|
|
12
|
-
{ label: 'Tab 1', content: 'Content 1' },
|
|
13
|
-
{ label: 'Tab 2', content: 'Content 2' }
|
|
14
|
-
];
|
|
15
|
-
expect(Array.isArray(tabs)).toBe(true);
|
|
16
|
-
expect(tabs.length).toBe(2);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it('should require label for each tab', () => {
|
|
20
|
-
const tab = { label: 'TypeScript', content: 'code' };
|
|
21
|
-
expect(tab.label).toBeDefined();
|
|
22
|
-
expect(typeof tab.label).toBe('string');
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('should accept optional default active tab index', () => {
|
|
26
|
-
const defaultActive = 0;
|
|
27
|
-
expect(typeof defaultActive).toBe('number');
|
|
28
|
-
expect(defaultActive).toBeGreaterThanOrEqual(0);
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
describe('Tab Structure', () => {
|
|
33
|
-
it('should maintain tab order', () => {
|
|
34
|
-
const tabs = [
|
|
35
|
-
{ label: 'First', content: 'First content' },
|
|
36
|
-
{ label: 'Second', content: 'Second content' },
|
|
37
|
-
{ label: 'Third', content: 'Third content' }
|
|
38
|
-
];
|
|
39
|
-
expect(tabs[0].label).toBe('First');
|
|
40
|
-
expect(tabs[1].label).toBe('Second');
|
|
41
|
-
expect(tabs[2].label).toBe('Third');
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it('should allow empty tab list', () => {
|
|
45
|
-
const tabs: any[] = [];
|
|
46
|
-
expect(tabs.length).toBe(0);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('should support single tab', () => {
|
|
50
|
-
const tabs = [{ label: 'Only Tab', content: 'Content' }];
|
|
51
|
-
expect(tabs.length).toBe(1);
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
describe('Tab Content', () => {
|
|
56
|
-
it('should support text content', () => {
|
|
57
|
-
const tab = { label: 'Info', content: 'This is text content' };
|
|
58
|
-
expect(typeof tab.content).toBe('string');
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it('should support HTML content', () => {
|
|
62
|
-
const tab = { label: 'Code', content: '<pre>code</pre>' };
|
|
63
|
-
expect(tab.content).toContain('<');
|
|
64
|
-
expect(tab.content).toContain('>');
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it('should support code blocks', () => {
|
|
68
|
-
const tab = {
|
|
69
|
-
label: 'JavaScript',
|
|
70
|
-
content: 'console.log("hello")'
|
|
71
|
-
};
|
|
72
|
-
expect(tab.label).toBeTruthy();
|
|
73
|
-
expect(tab.content).toBeTruthy();
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
describe('Keyboard Navigation', () => {
|
|
78
|
-
it('should support keyboard navigation', () => {
|
|
79
|
-
const supportedKeys = ['ArrowLeft', 'ArrowRight', 'Home', 'End'];
|
|
80
|
-
supportedKeys.forEach((key) => {
|
|
81
|
-
expect(supportedKeys).toContain(key);
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
describe('Accessibility', () => {
|
|
87
|
-
it('should have proper ARIA attributes', () => {
|
|
88
|
-
const role = 'tablist';
|
|
89
|
-
const tabRole = 'tab';
|
|
90
|
-
const panelRole = 'tabpanel';
|
|
91
|
-
|
|
92
|
-
expect(role).toBe('tablist');
|
|
93
|
-
expect(tabRole).toBe('tab');
|
|
94
|
-
expect(panelRole).toBe('tabpanel');
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
it('should maintain tab index', () => {
|
|
98
|
-
const tabIndex = -1; // initially not in tab order
|
|
99
|
-
expect(typeof tabIndex).toBe('number');
|
|
100
|
-
});
|
|
101
|
-
});
|
|
102
|
-
});
|
package/src/lib/config.test.ts
DELETED
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { validateConfig, mergeConfig, DEFAULT_CONFIG } from './config';
|
|
3
|
-
|
|
4
|
-
describe('Config Validation', () => {
|
|
5
|
-
it('should validate a valid config', () => {
|
|
6
|
-
const config = {
|
|
7
|
-
name: 'My Docs',
|
|
8
|
-
docsRoute: '/docs',
|
|
9
|
-
enableSearch: true,
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
const result = validateConfig(config);
|
|
13
|
-
expect(result.valid).toBe(true);
|
|
14
|
-
expect(result.errors).toHaveLength(0);
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it('should reject non-object config', () => {
|
|
18
|
-
const result = validateConfig('invalid');
|
|
19
|
-
expect(result.valid).toBe(false);
|
|
20
|
-
expect(result.errors.length).toBeGreaterThan(0);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('should validate docsRoute must be a string', () => {
|
|
24
|
-
const config = { docsRoute: 123 };
|
|
25
|
-
const result = validateConfig(config);
|
|
26
|
-
expect(result.valid).toBe(false);
|
|
27
|
-
expect(result.errors.some((e) => e.includes('docsRoute'))).toBe(true);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it('should validate docsRoute must start with /', () => {
|
|
31
|
-
const config = { docsRoute: 'docs' };
|
|
32
|
-
const result = validateConfig(config);
|
|
33
|
-
expect(result.valid).toBe(false);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it('should validate layout is one of the allowed values', () => {
|
|
37
|
-
const config = { layout: 'invalid' };
|
|
38
|
-
const result = validateConfig(config);
|
|
39
|
-
expect(result.valid).toBe(false);
|
|
40
|
-
expect(result.errors.some((e) => e.includes('layout'))).toBe(true);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('should validate defaultTheme is light or dark', () => {
|
|
44
|
-
const config = { defaultTheme: 'blue' };
|
|
45
|
-
const result = validateConfig(config);
|
|
46
|
-
expect(result.valid).toBe(false);
|
|
47
|
-
expect(result.errors.some((e) => e.includes('defaultTheme'))).toBe(true);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('should accept valid theme object', () => {
|
|
51
|
-
const config = {
|
|
52
|
-
theme: {
|
|
53
|
-
primary: '#ff0000',
|
|
54
|
-
secondary: '#00ff00',
|
|
55
|
-
},
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
const result = validateConfig(config);
|
|
59
|
-
expect(result.valid).toBe(true);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('should reject invalid theme object', () => {
|
|
63
|
-
const config = { theme: 'not-an-object' };
|
|
64
|
-
const result = validateConfig(config);
|
|
65
|
-
expect(result.valid).toBe(false);
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
describe('Config Merging', () => {
|
|
70
|
-
it('should merge user config with defaults', () => {
|
|
71
|
-
const userConfig = { name: 'Custom Docs' };
|
|
72
|
-
const merged = mergeConfig(userConfig);
|
|
73
|
-
|
|
74
|
-
expect(merged.name).toBe('Custom Docs');
|
|
75
|
-
expect(merged.docsRoute).toBe(DEFAULT_CONFIG.docsRoute);
|
|
76
|
-
expect(merged.enableSearch).toBe(DEFAULT_CONFIG.enableSearch);
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('should override defaults with user values', () => {
|
|
80
|
-
const userConfig = {
|
|
81
|
-
docsRoute: '/help',
|
|
82
|
-
enableSearch: false,
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
const merged = mergeConfig(userConfig);
|
|
86
|
-
expect(merged.docsRoute).toBe('/help');
|
|
87
|
-
expect(merged.enableSearch).toBe(false);
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
it('should merge nested theme objects', () => {
|
|
91
|
-
const userConfig = {
|
|
92
|
-
theme: {
|
|
93
|
-
primary: '#ff0000',
|
|
94
|
-
},
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
const merged = mergeConfig(userConfig);
|
|
98
|
-
expect(merged.theme?.primary).toBe('#ff0000');
|
|
99
|
-
expect(merged.theme?.secondary).toBe(DEFAULT_CONFIG.theme?.secondary);
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it('should merge nested navigation objects', () => {
|
|
103
|
-
const userConfig = {
|
|
104
|
-
navigation: {
|
|
105
|
-
title: 'Custom Nav',
|
|
106
|
-
},
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
const merged = mergeConfig(userConfig);
|
|
110
|
-
expect(merged.navigation?.title).toBe('Custom Nav');
|
|
111
|
-
expect(merged.navigation?.autoGenerate).toBe(DEFAULT_CONFIG.navigation?.autoGenerate);
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it('should handle null/undefined values correctly', () => {
|
|
115
|
-
const userConfig: any = {
|
|
116
|
-
name: null,
|
|
117
|
-
docsRoute: undefined,
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
const merged = mergeConfig(userConfig);
|
|
121
|
-
expect(merged.name).toBeNull();
|
|
122
|
-
expect(merged.docsRoute).toBeUndefined();
|
|
123
|
-
});
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
describe('DEFAULT_CONFIG', () => {
|
|
127
|
-
it('should have a valid default configuration', () => {
|
|
128
|
-
const result = validateConfig(DEFAULT_CONFIG);
|
|
129
|
-
expect(result.valid).toBe(true);
|
|
130
|
-
expect(result.errors).toHaveLength(0);
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
it('should have sensible default values', () => {
|
|
134
|
-
expect(DEFAULT_CONFIG.docsRoute).toBe('/docs');
|
|
135
|
-
expect(DEFAULT_CONFIG.enableSearch).toBe(true);
|
|
136
|
-
expect(DEFAULT_CONFIG.darkMode).toBe(true);
|
|
137
|
-
expect(DEFAULT_CONFIG.breadcrumbs).toBe(true);
|
|
138
|
-
expect(DEFAULT_CONFIG.prevNext).toBe(true);
|
|
139
|
-
});
|
|
140
|
-
});
|