specra 0.1.13 → 0.2.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/LICENSE.MD +25 -4
- package/README.md +67 -58
- package/config/specra.config.schema.json +16 -0
- package/config/svelte-config.js +63 -0
- package/dist/api-parser.types.d.ts +59 -0
- package/dist/api-parser.types.js +5 -0
- package/dist/api.types.d.ts +137 -0
- package/dist/api.types.js +5 -0
- package/dist/category.d.ts +21 -0
- package/dist/category.js +48 -0
- package/dist/components/ConfigProvider.svelte +13 -0
- package/dist/components/ConfigProvider.svelte.d.ts +31 -0
- package/dist/components/docs/Accordion.svelte +18 -0
- package/dist/components/docs/Accordion.svelte.d.ts +10 -0
- package/dist/components/docs/AccordionItem.svelte +41 -0
- package/dist/components/docs/AccordionItem.svelte.d.ts +10 -0
- package/dist/components/docs/Badge.svelte +28 -0
- package/dist/components/docs/Badge.svelte.d.ts +9 -0
- package/dist/components/docs/Breadcrumb.svelte +80 -0
- package/dist/components/docs/Breadcrumb.svelte.d.ts +8 -0
- package/dist/components/docs/Callout.svelte +96 -0
- package/dist/components/docs/Callout.svelte.d.ts +10 -0
- package/dist/components/docs/Card.svelte +63 -0
- package/dist/components/docs/Card.svelte.d.ts +12 -0
- package/dist/components/docs/CardGrid.svelte +24 -0
- package/dist/components/docs/CardGrid.svelte.d.ts +8 -0
- package/dist/components/docs/CategoryIndex.svelte +110 -0
- package/dist/components/docs/CategoryIndex.svelte.d.ts +29 -0
- package/dist/components/docs/CodeBlock.svelte +172 -0
- package/dist/components/docs/CodeBlock.svelte.d.ts +8 -0
- package/dist/components/docs/Column.svelte +25 -0
- package/dist/components/docs/Column.svelte.d.ts +8 -0
- package/dist/components/docs/Columns.svelte +38 -0
- package/dist/components/docs/Columns.svelte.d.ts +13 -0
- package/dist/components/docs/DevModeBadge.svelte +15 -0
- package/dist/components/docs/DevModeBadge.svelte.d.ts +18 -0
- package/dist/components/docs/DocBadge.svelte +28 -0
- package/dist/components/docs/DocBadge.svelte.d.ts +9 -0
- package/dist/components/docs/DocLayout.svelte +107 -0
- package/dist/components/docs/DocLayout.svelte.d.ts +32 -0
- package/dist/components/docs/DocLoading.svelte +53 -0
- package/dist/components/docs/DocLoading.svelte.d.ts +18 -0
- package/dist/components/docs/DocMetadata.svelte +106 -0
- package/dist/components/docs/DocMetadata.svelte.d.ts +18 -0
- package/dist/components/docs/DocNavigation.svelte +56 -0
- package/dist/components/docs/DocNavigation.svelte.d.ts +12 -0
- package/dist/components/docs/DocTags.svelte +22 -0
- package/dist/components/docs/DocTags.svelte.d.ts +6 -0
- package/dist/components/docs/DraftBadge.svelte +10 -0
- package/dist/components/docs/DraftBadge.svelte.d.ts +18 -0
- package/dist/components/docs/Footer.svelte +72 -0
- package/dist/components/docs/Footer.svelte.d.ts +7 -0
- package/dist/components/docs/Frame.svelte +27 -0
- package/dist/components/docs/Frame.svelte.d.ts +9 -0
- package/dist/components/docs/Header.svelte +123 -0
- package/dist/components/docs/Header.svelte.d.ts +9 -0
- package/dist/components/docs/HeaderWithMenu.svelte +34 -0
- package/dist/components/docs/HeaderWithMenu.svelte.d.ts +17 -0
- package/dist/components/docs/HotReloadIndicator.svelte +44 -0
- package/dist/components/docs/HotReloadIndicator.svelte.d.ts +3 -0
- package/dist/components/docs/Icon.svelte +103 -0
- package/dist/components/docs/Icon.svelte.d.ts +11 -0
- package/dist/components/docs/Image.svelte +88 -0
- package/dist/components/docs/Image.svelte.d.ts +11 -0
- package/dist/components/docs/ImageCard.svelte +91 -0
- package/dist/components/docs/ImageCard.svelte.d.ts +12 -0
- package/dist/components/docs/ImageCardGrid.svelte +25 -0
- package/dist/components/docs/ImageCardGrid.svelte.d.ts +8 -0
- package/dist/components/docs/LayoutProviders.svelte +57 -0
- package/dist/components/docs/LayoutProviders.svelte.d.ts +9 -0
- package/dist/components/docs/Logo.svelte +25 -0
- package/dist/components/docs/Logo.svelte.d.ts +11 -0
- package/dist/components/docs/Math.svelte +54 -0
- package/dist/components/docs/Math.svelte.d.ts +7 -0
- package/dist/components/docs/MdxContent.svelte +41 -0
- package/dist/components/docs/MdxHotReload.svelte +78 -0
- package/dist/components/docs/MdxHotReload.svelte.d.ts +9 -0
- package/dist/components/docs/MdxLayout.svelte +16 -0
- package/dist/components/docs/MdxLayout.svelte.d.ts +6 -0
- package/dist/components/docs/Mermaid.svelte +88 -0
- package/dist/components/docs/Mermaid.svelte.d.ts +7 -0
- package/dist/components/docs/MobileDocLayout.svelte +211 -0
- package/dist/components/docs/MobileDocLayout.svelte.d.ts +35 -0
- package/dist/components/docs/MobileSidebar.svelte +122 -0
- package/dist/components/docs/MobileSidebar.svelte.d.ts +31 -0
- package/dist/components/docs/MobileSidebarWrapper.svelte +122 -0
- package/dist/components/docs/MobileSidebarWrapper.svelte.d.ts +32 -0
- package/dist/components/docs/NotFoundContent.svelte +40 -0
- package/dist/components/docs/NotFoundContent.svelte.d.ts +6 -0
- package/dist/components/docs/SearchHighlight.svelte +116 -0
- package/dist/components/docs/SearchHighlight.svelte.d.ts +3 -0
- package/dist/components/docs/SearchModal.svelte +239 -0
- package/dist/components/docs/SearchModal.svelte.d.ts +9 -0
- package/dist/components/docs/Sidebar.svelte +69 -0
- package/dist/components/docs/Sidebar.svelte.d.ts +31 -0
- package/dist/components/docs/SidebarMenuItems.svelte +344 -0
- package/dist/components/docs/SidebarMenuItems.svelte.d.ts +33 -0
- package/dist/components/docs/SidebarSkeleton.svelte +50 -0
- package/dist/components/docs/SidebarSkeleton.svelte.d.ts +18 -0
- package/dist/components/docs/SiteBanner.svelte +92 -0
- package/dist/components/docs/SiteBanner.svelte.d.ts +7 -0
- package/dist/components/docs/Step.svelte +44 -0
- package/dist/components/docs/Step.svelte.d.ts +8 -0
- package/dist/components/docs/Steps.svelte +15 -0
- package/dist/components/docs/Steps.svelte.d.ts +7 -0
- package/dist/components/docs/Tab.svelte +40 -0
- package/dist/components/docs/Tab.svelte.d.ts +8 -0
- package/dist/components/docs/TabGroups.svelte +183 -0
- package/dist/components/docs/TabGroups.svelte.d.ts +25 -0
- package/dist/components/docs/TableOfContents.svelte +100 -0
- package/dist/components/docs/TableOfContents.svelte.d.ts +9 -0
- package/dist/components/docs/Tabs.svelte +69 -0
- package/dist/components/docs/Tabs.svelte.d.ts +8 -0
- package/dist/components/docs/ThemeToggle.svelte +16 -0
- package/dist/components/docs/ThemeToggle.svelte.d.ts +18 -0
- package/dist/components/docs/Tooltip.svelte +44 -0
- package/dist/components/docs/Tooltip.svelte.d.ts +10 -0
- package/dist/components/docs/VersionSwitcher.svelte +95 -0
- package/dist/components/docs/VersionSwitcher.svelte.d.ts +7 -0
- package/dist/components/docs/Video.svelte +84 -0
- package/dist/components/docs/Video.svelte.d.ts +12 -0
- package/dist/components/docs/api/ApiEndpoint.svelte +61 -0
- package/dist/components/docs/api/ApiEndpoint.svelte.d.ts +11 -0
- package/dist/components/docs/api/ApiParams.svelte +80 -0
- package/dist/components/docs/api/ApiParams.svelte.d.ts +14 -0
- package/dist/components/docs/api/ApiPlayground.svelte +259 -0
- package/dist/components/docs/api/ApiPlayground.svelte.d.ts +16 -0
- package/dist/components/docs/api/ApiReference.svelte +278 -0
- package/dist/components/docs/api/ApiReference.svelte.d.ts +23 -0
- package/dist/components/docs/api/ApiResponse.svelte +66 -0
- package/dist/components/docs/api/ApiResponse.svelte.d.ts +9 -0
- package/dist/components/docs/api/index.d.ts +5 -0
- package/dist/components/docs/api/index.js +5 -0
- package/dist/components/docs/componentTextProps.d.ts +3 -0
- package/dist/components/docs/componentTextProps.js +61 -0
- package/dist/components/docs/index.d.ts +54 -0
- package/dist/components/docs/index.js +56 -0
- package/dist/components/global/VersionNotFound.svelte +48 -0
- package/dist/components/global/VersionNotFound.svelte.d.ts +7 -0
- package/dist/components/global/index.d.ts +1 -0
- package/dist/components/global/index.js +1 -0
- package/dist/components/index.d.ts +6 -822
- package/dist/components/index.js +11 -3854
- package/dist/components/ui/Badge.svelte +48 -0
- package/dist/components/ui/Badge.svelte.d.ts +15 -0
- package/dist/components/ui/Button.svelte +58 -0
- package/dist/components/ui/Button.svelte.d.ts +17 -0
- package/dist/components/ui/Dialog.svelte +16 -0
- package/dist/components/ui/Dialog.svelte.d.ts +9 -0
- package/dist/components/ui/DialogClose.svelte +16 -0
- package/dist/components/ui/DialogClose.svelte.d.ts +9 -0
- package/dist/components/ui/DialogContent.svelte +43 -0
- package/dist/components/ui/DialogContent.svelte.d.ts +10 -0
- package/dist/components/ui/DialogDescription.svelte +21 -0
- package/dist/components/ui/DialogDescription.svelte.d.ts +9 -0
- package/dist/components/ui/DialogFooter.svelte +20 -0
- package/dist/components/ui/DialogFooter.svelte.d.ts +9 -0
- package/dist/components/ui/DialogHeader.svelte +20 -0
- package/dist/components/ui/DialogHeader.svelte.d.ts +9 -0
- package/dist/components/ui/DialogTitle.svelte +21 -0
- package/dist/components/ui/DialogTitle.svelte.d.ts +9 -0
- package/dist/components/ui/Input.svelte +23 -0
- package/dist/components/ui/Input.svelte.d.ts +8 -0
- package/dist/components/ui/Textarea.svelte +19 -0
- package/dist/components/ui/Textarea.svelte.d.ts +7 -0
- package/dist/components/ui/index.d.ts +11 -0
- package/dist/components/ui/index.js +11 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.js +9 -0
- package/dist/config.schema.json +471 -0
- package/dist/config.server.d.ts +46 -0
- package/dist/config.server.js +149 -0
- package/dist/{mdx-ColN3Cyg.d.mts → config.types.d.ts} +22 -75
- package/dist/config.types.js +39 -0
- package/dist/dev-utils.d.ts +29 -0
- package/dist/dev-utils.js +63 -0
- package/dist/index.d.ts +19 -4
- package/dist/index.js +25 -4861
- package/dist/mdx-cache.d.ts +41 -0
- package/dist/mdx-cache.js +160 -0
- package/dist/mdx-components.js +50 -1931
- package/dist/mdx-security.d.ts +76 -0
- package/dist/mdx-security.js +217 -0
- package/dist/mdx.d.ts +73 -0
- package/dist/mdx.js +1099 -0
- package/dist/middleware/index.d.ts +1 -0
- package/dist/middleware/index.js +2 -0
- package/dist/middleware/security.d.ts +22 -47
- package/dist/middleware/security.js +111 -137
- package/dist/parsers/base-parser.d.ts +14 -0
- package/dist/parsers/base-parser.js +1 -0
- package/dist/parsers/index.d.ts +16 -0
- package/dist/parsers/index.js +51 -0
- package/dist/parsers/openapi-parser.d.ts +18 -0
- package/dist/parsers/openapi-parser.js +209 -0
- package/dist/parsers/postman-parser.d.ts +20 -0
- package/dist/parsers/postman-parser.js +260 -0
- package/dist/parsers/specra-parser.d.ts +10 -0
- package/dist/parsers/specra-parser.js +18 -0
- package/dist/redirects.d.ts +12 -0
- package/dist/redirects.js +30 -0
- package/dist/remark-code-meta.d.ts +6 -0
- package/dist/remark-code-meta.js +21 -0
- package/dist/sidebar-utils.d.ts +59 -0
- package/dist/sidebar-utils.js +144 -0
- package/dist/stores/config.d.ts +20 -0
- package/dist/stores/config.js +45 -0
- package/dist/stores/index.d.ts +4 -0
- package/dist/stores/index.js +4 -0
- package/dist/stores/sidebar.d.ts +7 -0
- package/dist/stores/sidebar.js +12 -0
- package/dist/stores/tabs.d.ts +6 -0
- package/dist/stores/tabs.js +41 -0
- package/dist/stores/theme.d.ts +7 -0
- package/dist/stores/theme.js +75 -0
- package/dist/{styles.css → styles/globals.css} +136 -6
- package/dist/toc.d.ts +9 -0
- package/dist/toc.js +15 -0
- package/dist/utils.d.ts +13 -0
- package/dist/utils.js +30 -0
- package/package.json +47 -90
- package/dist/app/api/mdx-watch/route.d.mts +0 -10
- package/dist/app/api/mdx-watch/route.d.ts +0 -10
- package/dist/app/api/mdx-watch/route.js +0 -118
- package/dist/app/api/mdx-watch/route.js.map +0 -1
- package/dist/app/api/mdx-watch/route.mjs +0 -91
- package/dist/app/api/mdx-watch/route.mjs.map +0 -1
- package/dist/chunk-6S3EJVEO.mjs +0 -259
- package/dist/chunk-6S3EJVEO.mjs.map +0 -1
- package/dist/chunk-BE7EROIW.mjs +0 -212
- package/dist/chunk-BE7EROIW.mjs.map +0 -1
- package/dist/chunk-CWHRZHZO.mjs +0 -168
- package/dist/chunk-CWHRZHZO.mjs.map +0 -1
- package/dist/chunk-D5VDVYFY.mjs +0 -1325
- package/dist/chunk-D5VDVYFY.mjs.map +0 -1
- package/dist/chunk-WMCO2UX5.mjs +0 -585
- package/dist/chunk-WMCO2UX5.mjs.map +0 -1
- package/dist/chunk-XEMGCPZZ.mjs +0 -475
- package/dist/chunk-XEMGCPZZ.mjs.map +0 -1
- package/dist/components/index.d.mts +0 -822
- package/dist/components/index.js.map +0 -1
- package/dist/components/index.mjs +0 -3741
- package/dist/components/index.mjs.map +0 -1
- package/dist/index.d.mts +0 -4
- package/dist/index.js.map +0 -1
- package/dist/index.mjs +0 -1897
- package/dist/index.mjs.map +0 -1
- package/dist/layouts/index.d.mts +0 -34
- package/dist/layouts/index.d.ts +0 -34
- package/dist/layouts/index.js +0 -453
- package/dist/layouts/index.js.map +0 -1
- package/dist/layouts/index.mjs +0 -173
- package/dist/layouts/index.mjs.map +0 -1
- package/dist/lib/index.d.mts +0 -583
- package/dist/lib/index.d.ts +0 -583
- package/dist/lib/index.js +0 -1595
- package/dist/lib/index.js.map +0 -1
- package/dist/lib/index.mjs +0 -111
- package/dist/lib/index.mjs.map +0 -1
- package/dist/mdx-ColN3Cyg.d.ts +0 -352
- package/dist/mdx-components.d.mts +0 -86
- package/dist/mdx-components.d.ts +0 -86
- package/dist/mdx-components.js.map +0 -1
- package/dist/mdx-components.mjs +0 -206
- package/dist/mdx-components.mjs.map +0 -1
- package/dist/middleware/security.d.mts +0 -82
- package/dist/middleware/security.js.map +0 -1
- package/dist/middleware/security.mjs +0 -84
- package/dist/middleware/security.mjs.map +0 -1
- package/dist/styles.css.map +0 -1
- package/dist/styles.d.mts +0 -2
- package/dist/styles.d.ts +0 -2
- package/dist/styles.js +0 -2
- package/dist/styles.js.map +0 -1
- package/dist/styles.mjs +0 -1
- package/dist/styles.mjs.map +0 -1
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { SpecraConfig } from '../../config.types.js';
|
|
2
|
+
interface DocMeta {
|
|
3
|
+
readingTime?: number;
|
|
4
|
+
lastUpdated?: string;
|
|
5
|
+
authors?: Array<string | {
|
|
6
|
+
name: string;
|
|
7
|
+
avatar?: string;
|
|
8
|
+
url?: string;
|
|
9
|
+
}>;
|
|
10
|
+
[key: string]: unknown;
|
|
11
|
+
}
|
|
12
|
+
interface Props {
|
|
13
|
+
meta: DocMeta;
|
|
14
|
+
config: SpecraConfig;
|
|
15
|
+
}
|
|
16
|
+
declare const DocMetadata: import("svelte").Component<Props, {}, "">;
|
|
17
|
+
type DocMetadata = ReturnType<typeof DocMetadata>;
|
|
18
|
+
export default DocMetadata;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { ChevronLeft, ChevronRight } from 'lucide-svelte';
|
|
3
|
+
|
|
4
|
+
interface NavDoc {
|
|
5
|
+
title: string;
|
|
6
|
+
slug: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
previousDoc?: NavDoc;
|
|
11
|
+
nextDoc?: NavDoc;
|
|
12
|
+
version: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
let { previousDoc, nextDoc, version }: Props = $props();
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
{#if previousDoc || nextDoc}
|
|
19
|
+
<div class="mt-12 pt-8 border-t border-border grid grid-cols-2 gap-4">
|
|
20
|
+
{#if previousDoc}
|
|
21
|
+
<a
|
|
22
|
+
href="/docs/{version}/{previousDoc.slug}"
|
|
23
|
+
class="group flex flex-col gap-2 p-4 rounded-xl border border-border hover:border-primary/50 hover:bg-muted/50 transition-all"
|
|
24
|
+
style="text-decoration: none !important;"
|
|
25
|
+
>
|
|
26
|
+
<div class="flex items-center gap-2 text-sm text-muted-foreground">
|
|
27
|
+
<ChevronLeft class="h-4 w-4" />
|
|
28
|
+
<span>Previous</span>
|
|
29
|
+
</div>
|
|
30
|
+
<div class="text-base font-medium text-foreground group-hover:text-primary transition-colors">
|
|
31
|
+
{previousDoc.title}
|
|
32
|
+
</div>
|
|
33
|
+
</a>
|
|
34
|
+
{:else}
|
|
35
|
+
<div></div>
|
|
36
|
+
{/if}
|
|
37
|
+
|
|
38
|
+
{#if nextDoc}
|
|
39
|
+
<a
|
|
40
|
+
href="/docs/{version}/{nextDoc.slug}"
|
|
41
|
+
class="group flex flex-col gap-2 p-4 rounded-xl border border-border hover:border-primary/50 hover:bg-muted/50 transition-all text-right"
|
|
42
|
+
style="text-decoration: none !important;"
|
|
43
|
+
>
|
|
44
|
+
<div class="flex items-center justify-end gap-2 text-sm text-muted-foreground">
|
|
45
|
+
<span>Next</span>
|
|
46
|
+
<ChevronRight class="h-4 w-4" />
|
|
47
|
+
</div>
|
|
48
|
+
<div class="text-base font-medium text-foreground group-hover:text-primary transition-colors">
|
|
49
|
+
{nextDoc.title}
|
|
50
|
+
</div>
|
|
51
|
+
</a>
|
|
52
|
+
{:else}
|
|
53
|
+
<div></div>
|
|
54
|
+
{/if}
|
|
55
|
+
</div>
|
|
56
|
+
{/if}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface NavDoc {
|
|
2
|
+
title: string;
|
|
3
|
+
slug: string;
|
|
4
|
+
}
|
|
5
|
+
interface Props {
|
|
6
|
+
previousDoc?: NavDoc;
|
|
7
|
+
nextDoc?: NavDoc;
|
|
8
|
+
version: string;
|
|
9
|
+
}
|
|
10
|
+
declare const DocNavigation: import("svelte").Component<Props, {}, "">;
|
|
11
|
+
type DocNavigation = ReturnType<typeof DocNavigation>;
|
|
12
|
+
export default DocNavigation;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Tag } from 'lucide-svelte';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
tags: string[];
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
let { tags }: Props = $props();
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
{#if tags && tags.length > 0}
|
|
12
|
+
<div class="flex flex-wrap items-center gap-2 mt-6 pt-4 border-t border-border">
|
|
13
|
+
<Tag class="h-3.5 w-3.5 text-muted-foreground" />
|
|
14
|
+
{#each tags as tag}
|
|
15
|
+
<span
|
|
16
|
+
class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-secondary text-secondary-foreground"
|
|
17
|
+
>
|
|
18
|
+
{tag}
|
|
19
|
+
</span>
|
|
20
|
+
{/each}
|
|
21
|
+
</div>
|
|
22
|
+
{/if}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Eye } from 'lucide-svelte';
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
<div
|
|
6
|
+
class="inline-flex items-center gap-1.5 px-3 py-1 rounded-md bg-yellow-500/10 border border-yellow-500/20 text-yellow-700 dark:text-yellow-300 text-xs font-medium mb-4"
|
|
7
|
+
>
|
|
8
|
+
<Eye class="h-3.5 w-3.5" />
|
|
9
|
+
<span>Draft - Not visible in production</span>
|
|
10
|
+
</div>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
2
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
|
+
$$bindings?: Bindings;
|
|
4
|
+
} & Exports;
|
|
5
|
+
(internal: unknown, props: {
|
|
6
|
+
$$events?: Events;
|
|
7
|
+
$$slots?: Slots;
|
|
8
|
+
}): Exports & {
|
|
9
|
+
$set?: any;
|
|
10
|
+
$on?: any;
|
|
11
|
+
};
|
|
12
|
+
z_$$bindings?: Bindings;
|
|
13
|
+
}
|
|
14
|
+
declare const DraftBadge: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
15
|
+
[evt: string]: CustomEvent<any>;
|
|
16
|
+
}, {}, {}, string>;
|
|
17
|
+
type DraftBadge = InstanceType<typeof DraftBadge>;
|
|
18
|
+
export default DraftBadge;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { SpecraConfig } from '../../config.types.js';
|
|
3
|
+
import Logo from './Logo.svelte';
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
config: SpecraConfig;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let { config }: Props = $props();
|
|
10
|
+
|
|
11
|
+
// The watermark is ALWAYS shown by default per the license.
|
|
12
|
+
// It can only be hidden with an active paid subscription (Starter+).
|
|
13
|
+
// Setting showBranding: false without a paid tier is a license violation.
|
|
14
|
+
let hideBranding = $derived(config.footer?.branding?.showBranding === false);
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<footer class="bg-muted/30 dark:bg-muted/10 rounded-2xl mt-24">
|
|
18
|
+
<div class="px-2 md:px-6 py-12">
|
|
19
|
+
{#if config.footer?.links && config.footer.links.length > 0}
|
|
20
|
+
<div class="grid grid-cols-2 md:grid-cols-4 gap-8 mb-8">
|
|
21
|
+
{#each config.footer.links as column, idx (idx)}
|
|
22
|
+
<div>
|
|
23
|
+
<h3 class="font-semibold text-foreground mb-4">{column.title}</h3>
|
|
24
|
+
<ul class="space-y-2">
|
|
25
|
+
{#each column.items as item, itemIdx (itemIdx)}
|
|
26
|
+
<li>
|
|
27
|
+
<a
|
|
28
|
+
href={item.href}
|
|
29
|
+
class="text-sm text-muted-foreground hover:text-foreground transition-colors"
|
|
30
|
+
>
|
|
31
|
+
{item.label}
|
|
32
|
+
</a>
|
|
33
|
+
</li>
|
|
34
|
+
{/each}
|
|
35
|
+
</ul>
|
|
36
|
+
</div>
|
|
37
|
+
{/each}
|
|
38
|
+
</div>
|
|
39
|
+
{/if}
|
|
40
|
+
|
|
41
|
+
<div class="pt-8 border-t border-border/50">
|
|
42
|
+
<div class="flex flex-col md:flex-row items-center justify-between gap-4">
|
|
43
|
+
{#if config.footer?.copyright}
|
|
44
|
+
<p class="text-sm text-muted-foreground text-center md:text-left">
|
|
45
|
+
{config.footer.copyright}
|
|
46
|
+
</p>
|
|
47
|
+
{/if}
|
|
48
|
+
|
|
49
|
+
{#if !hideBranding}
|
|
50
|
+
<div class="flex items-center gap-2 text-sm text-muted-foreground">
|
|
51
|
+
{#if config.footer?.branding?.logo}
|
|
52
|
+
<Logo
|
|
53
|
+
logo={config.footer.branding.logo}
|
|
54
|
+
alt={config.footer.branding.title || 'Powered by'}
|
|
55
|
+
className="h-5 w-auto object-contain"
|
|
56
|
+
/>
|
|
57
|
+
{/if}
|
|
58
|
+
<span>Powered by</span>
|
|
59
|
+
<a
|
|
60
|
+
href="https://specra-docs.com"
|
|
61
|
+
target="_blank"
|
|
62
|
+
rel="noopener noreferrer"
|
|
63
|
+
class="font-semibold hover:text-foreground transition-colors"
|
|
64
|
+
>
|
|
65
|
+
Specra
|
|
66
|
+
</a>
|
|
67
|
+
</div>
|
|
68
|
+
{/if}
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
</footer>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
interface Props {
|
|
3
|
+
src: string;
|
|
4
|
+
title?: string;
|
|
5
|
+
height?: number | string;
|
|
6
|
+
width?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let {
|
|
10
|
+
src,
|
|
11
|
+
title = 'Embedded content',
|
|
12
|
+
height = 500,
|
|
13
|
+
width = '100%',
|
|
14
|
+
}: Props = $props();
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<div class="my-6 rounded-xl border border-border overflow-hidden bg-muted/30">
|
|
18
|
+
<iframe
|
|
19
|
+
{src}
|
|
20
|
+
{title}
|
|
21
|
+
{width}
|
|
22
|
+
{height}
|
|
23
|
+
class="w-full"
|
|
24
|
+
loading="lazy"
|
|
25
|
+
sandbox="allow-scripts allow-same-origin allow-forms allow-popups"
|
|
26
|
+
></iframe>
|
|
27
|
+
</div>
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Search, Menu, Github, Twitter, MessageCircle } from 'lucide-svelte';
|
|
3
|
+
import { getConfigContext } from '../../stores/config.js';
|
|
4
|
+
import { sidebarStore } from '../../stores/sidebar.js';
|
|
5
|
+
import VersionSwitcher from './VersionSwitcher.svelte';
|
|
6
|
+
import ThemeToggle from './ThemeToggle.svelte';
|
|
7
|
+
import SearchModal from './SearchModal.svelte';
|
|
8
|
+
import Logo from './Logo.svelte';
|
|
9
|
+
import type { SpecraConfig } from '../../config.types.js';
|
|
10
|
+
|
|
11
|
+
interface Props {
|
|
12
|
+
currentVersion: string;
|
|
13
|
+
versions: string[];
|
|
14
|
+
config?: SpecraConfig;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let { currentVersion, versions, config: configProp }: Props = $props();
|
|
18
|
+
|
|
19
|
+
const configStore = getConfigContext();
|
|
20
|
+
let config = $derived(configProp || $configStore);
|
|
21
|
+
let searchOpen = $state(false);
|
|
22
|
+
let isFlush = $derived(config?.navigation?.sidebarStyle === 'flush');
|
|
23
|
+
|
|
24
|
+
$effect(() => {
|
|
25
|
+
const handleKeyDown = (e: KeyboardEvent) => {
|
|
26
|
+
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
|
|
27
|
+
e.preventDefault();
|
|
28
|
+
searchOpen = true;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
window.addEventListener('keydown', handleKeyDown);
|
|
32
|
+
return () => window.removeEventListener('keydown', handleKeyDown);
|
|
33
|
+
});
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
<header class="sticky top-0 z-50 w-full border-b border-border bg-background/95 backdrop-blur supports-backdrop-filter:bg-background/60">
|
|
37
|
+
<div class="{isFlush ? '' : 'container mx-auto'} flex h-16 items-center justify-between px-4 md:px-6">
|
|
38
|
+
<div class="flex items-center gap-1">
|
|
39
|
+
<button
|
|
40
|
+
onclick={() => sidebarStore.toggle()}
|
|
41
|
+
class="lg:hidden hover:bg-muted p-2 rounded-md transition-colors"
|
|
42
|
+
aria-label="Toggle menu"
|
|
43
|
+
>
|
|
44
|
+
<Menu class="h-5 w-5" />
|
|
45
|
+
</button>
|
|
46
|
+
<a href="/" class="flex items-center gap-2">
|
|
47
|
+
{#if !config.site.hideLogo}
|
|
48
|
+
{#if config.site.logo}
|
|
49
|
+
<Logo logo={config.site.logo} alt={config.site.title} className="w-18 object-contain" />
|
|
50
|
+
{:else}
|
|
51
|
+
<div class="h-8 w-8 rounded-xl bg-primary flex items-center justify-center">
|
|
52
|
+
<span class="text-primary-foreground font-bold text-lg">
|
|
53
|
+
{config.site.title.charAt(0).toUpperCase()}
|
|
54
|
+
</span>
|
|
55
|
+
</div>
|
|
56
|
+
{/if}
|
|
57
|
+
{/if}
|
|
58
|
+
{#if !config.site.hideTitle}
|
|
59
|
+
<span class="font-semibold text-lg text-foreground">{config.site.title ?? 'Specra'}</span>
|
|
60
|
+
{/if}
|
|
61
|
+
</a>
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
<div class="flex items-center gap-2">
|
|
65
|
+
{#if config.search?.enabled}
|
|
66
|
+
<button
|
|
67
|
+
onclick={() => (searchOpen = true)}
|
|
68
|
+
class="flex items-center gap-2 px-3 py-2 text-sm text-muted-foreground hover:text-foreground bg-muted rounded-md transition-colors"
|
|
69
|
+
>
|
|
70
|
+
<Search class="h-4 w-4" />
|
|
71
|
+
<span class="hidden sm:inline">{config.search.placeholder || 'Search'}</span>
|
|
72
|
+
<kbd class="hidden sm:inline-flex h-5 select-none items-center gap-1 rounded border border-border bg-background px-1.5 font-mono text-xs font-medium">
|
|
73
|
+
⌘K
|
|
74
|
+
</kbd>
|
|
75
|
+
</button>
|
|
76
|
+
{/if}
|
|
77
|
+
|
|
78
|
+
{#if config.features?.versioning}
|
|
79
|
+
<VersionSwitcher {currentVersion} {versions} />
|
|
80
|
+
{/if}
|
|
81
|
+
|
|
82
|
+
<!-- Social Links -->
|
|
83
|
+
{#if config.social?.github}
|
|
84
|
+
<a
|
|
85
|
+
href={config.social.github}
|
|
86
|
+
target="_blank"
|
|
87
|
+
rel="noopener noreferrer"
|
|
88
|
+
class="hidden md:flex items-center justify-center h-9 w-9 rounded-md hover:bg-muted transition-colors"
|
|
89
|
+
aria-label="GitHub"
|
|
90
|
+
>
|
|
91
|
+
<Github class="h-4 w-4" />
|
|
92
|
+
</a>
|
|
93
|
+
{/if}
|
|
94
|
+
{#if config.social?.twitter}
|
|
95
|
+
<a
|
|
96
|
+
href={config.social.twitter}
|
|
97
|
+
target="_blank"
|
|
98
|
+
rel="noopener noreferrer"
|
|
99
|
+
class="hidden md:flex items-center justify-center h-9 w-9 rounded-md hover:bg-muted transition-colors"
|
|
100
|
+
aria-label="Twitter"
|
|
101
|
+
>
|
|
102
|
+
<Twitter class="h-4 w-4" />
|
|
103
|
+
</a>
|
|
104
|
+
{/if}
|
|
105
|
+
{#if config.social?.discord}
|
|
106
|
+
<a
|
|
107
|
+
href={config.social.discord}
|
|
108
|
+
target="_blank"
|
|
109
|
+
rel="noopener noreferrer"
|
|
110
|
+
class="hidden md:flex items-center justify-center h-9 w-9 rounded-md hover:bg-muted transition-colors"
|
|
111
|
+
aria-label="Discord"
|
|
112
|
+
>
|
|
113
|
+
<MessageCircle class="h-4 w-4" />
|
|
114
|
+
</a>
|
|
115
|
+
{/if}
|
|
116
|
+
|
|
117
|
+
<ThemeToggle />
|
|
118
|
+
</div>
|
|
119
|
+
</div>
|
|
120
|
+
|
|
121
|
+
<!-- Search Modal -->
|
|
122
|
+
<SearchModal isOpen={searchOpen} onClose={() => (searchOpen = false)} {config} />
|
|
123
|
+
</header>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SpecraConfig } from '../../config.types.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
currentVersion: string;
|
|
4
|
+
versions: string[];
|
|
5
|
+
config?: SpecraConfig;
|
|
6
|
+
}
|
|
7
|
+
declare const Header: import("svelte").Component<Props, {}, "">;
|
|
8
|
+
type Header = ReturnType<typeof Header>;
|
|
9
|
+
export default Header;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { sidebarStore } from '../../stores/sidebar.js';
|
|
3
|
+
import type { Snippet } from 'svelte';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* HeaderWithMenu wraps a header snippet and provides mobile menu toggle functionality.
|
|
7
|
+
* In Svelte, instead of React's cloneElement pattern, the header component
|
|
8
|
+
* directly accesses the sidebarStore for toggle behavior.
|
|
9
|
+
* This component exists as a thin wrapper for layout composition.
|
|
10
|
+
*/
|
|
11
|
+
interface Props {
|
|
12
|
+
/** Header content to render */
|
|
13
|
+
header?: Snippet;
|
|
14
|
+
/** Optional: override the toggle handler */
|
|
15
|
+
onMenuClick?: () => void;
|
|
16
|
+
children?: Snippet;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let { header, onMenuClick, children }: Props = $props();
|
|
20
|
+
|
|
21
|
+
function handleMenuClick() {
|
|
22
|
+
if (onMenuClick) {
|
|
23
|
+
onMenuClick();
|
|
24
|
+
} else {
|
|
25
|
+
sidebarStore.toggle();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
{#if header}
|
|
31
|
+
{@render header()}
|
|
32
|
+
{:else if children}
|
|
33
|
+
{@render children()}
|
|
34
|
+
{/if}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
/**
|
|
3
|
+
* HeaderWithMenu wraps a header snippet and provides mobile menu toggle functionality.
|
|
4
|
+
* In Svelte, instead of React's cloneElement pattern, the header component
|
|
5
|
+
* directly accesses the sidebarStore for toggle behavior.
|
|
6
|
+
* This component exists as a thin wrapper for layout composition.
|
|
7
|
+
*/
|
|
8
|
+
interface Props {
|
|
9
|
+
/** Header content to render */
|
|
10
|
+
header?: Snippet;
|
|
11
|
+
/** Optional: override the toggle handler */
|
|
12
|
+
onMenuClick?: () => void;
|
|
13
|
+
children?: Snippet;
|
|
14
|
+
}
|
|
15
|
+
declare const HeaderWithMenu: import("svelte").Component<Props, {}, "">;
|
|
16
|
+
type HeaderWithMenu = ReturnType<typeof HeaderWithMenu>;
|
|
17
|
+
export default HeaderWithMenu;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { RefreshCw } from 'lucide-svelte';
|
|
3
|
+
import { browser } from '$app/environment';
|
|
4
|
+
import { dev } from '$app/environment';
|
|
5
|
+
|
|
6
|
+
let isReloading = $state(false);
|
|
7
|
+
let showIndicator = $state(false);
|
|
8
|
+
|
|
9
|
+
$effect(() => {
|
|
10
|
+
if (!browser || !dev) return;
|
|
11
|
+
|
|
12
|
+
// Listen for Vite HMR events
|
|
13
|
+
if (import.meta.hot) {
|
|
14
|
+
import.meta.hot.on('vite:beforeUpdate', () => {
|
|
15
|
+
isReloading = true;
|
|
16
|
+
showIndicator = true;
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
import.meta.hot.on('vite:afterUpdate', () => {
|
|
20
|
+
isReloading = false;
|
|
21
|
+
// Keep indicator visible briefly after update
|
|
22
|
+
setTimeout(() => {
|
|
23
|
+
showIndicator = false;
|
|
24
|
+
}, 1500);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
import.meta.hot.on('vite:error', () => {
|
|
28
|
+
isReloading = false;
|
|
29
|
+
showIndicator = false;
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
{#if dev && showIndicator}
|
|
36
|
+
<div
|
|
37
|
+
class="fixed top-4 right-4 z-50 inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full shadow-lg backdrop-blur-sm text-xs font-medium transition-all duration-300 {isReloading
|
|
38
|
+
? 'bg-blue-500/90 text-white'
|
|
39
|
+
: 'bg-green-500/90 text-white'}"
|
|
40
|
+
>
|
|
41
|
+
<RefreshCw class="h-3 w-3 {isReloading ? 'animate-spin' : ''}" />
|
|
42
|
+
<span>{isReloading ? 'Reloading...' : 'Updated'}</span>
|
|
43
|
+
</div>
|
|
44
|
+
{/if}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import * as icons from 'lucide-svelte';
|
|
3
|
+
import type { ComponentType } from 'svelte';
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
icon: string | ComponentType;
|
|
7
|
+
iconType?: 'lucide' | 'url' | 'fa' | 'auto';
|
|
8
|
+
color?: string;
|
|
9
|
+
size?: number | string;
|
|
10
|
+
className?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let { icon, iconType = 'auto', color, size = 20, className = '' }: Props = $props();
|
|
14
|
+
|
|
15
|
+
// Convert kebab-case or lowercase to PascalCase for Lucide icon lookup
|
|
16
|
+
function toPascalCase(str: string): string {
|
|
17
|
+
return str
|
|
18
|
+
.split(/[-_\s]/)
|
|
19
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
20
|
+
.join('');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Resolve a string icon name to a Lucide component
|
|
24
|
+
function getLucideIcon(name: string): ComponentType | null {
|
|
25
|
+
const pascalName = toPascalCase(name);
|
|
26
|
+
const iconMap = icons as Record<string, ComponentType>;
|
|
27
|
+
return iconMap[pascalName] || null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Determine icon type from the icon value
|
|
31
|
+
function detectIconType(iconValue: string): 'lucide' | 'url' | 'fa' | 'text' {
|
|
32
|
+
if (iconValue.startsWith('http') || iconValue.startsWith('/') || iconValue.startsWith('data:')) {
|
|
33
|
+
return 'url';
|
|
34
|
+
}
|
|
35
|
+
if (iconValue.startsWith('fa-') || iconValue.startsWith('fas ') || iconValue.startsWith('fab ') || iconValue.startsWith('far ')) {
|
|
36
|
+
return 'fa';
|
|
37
|
+
}
|
|
38
|
+
// Check if it's a valid Lucide icon
|
|
39
|
+
if (getLucideIcon(iconValue)) {
|
|
40
|
+
return 'lucide';
|
|
41
|
+
}
|
|
42
|
+
return 'text';
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const resolvedType = $derived(
|
|
46
|
+
typeof icon === 'string'
|
|
47
|
+
? iconType === 'auto'
|
|
48
|
+
? detectIconType(icon)
|
|
49
|
+
: iconType
|
|
50
|
+
: 'component'
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const lucideComponent = $derived(
|
|
54
|
+
typeof icon === 'string' && resolvedType === 'lucide' ? getLucideIcon(icon) : null
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const sizeValue = $derived(typeof size === 'number' ? `${size}px` : size);
|
|
58
|
+
const sizeNum = $derived(typeof size === 'string' ? parseInt(size, 10) || 20 : size);
|
|
59
|
+
</script>
|
|
60
|
+
|
|
61
|
+
{#if typeof icon !== 'string'}
|
|
62
|
+
<!-- Svelte component passed directly -->
|
|
63
|
+
<svelte:component
|
|
64
|
+
this={icon}
|
|
65
|
+
size={sizeNum}
|
|
66
|
+
class="inline-block {className}"
|
|
67
|
+
style={color ? `color: ${color}` : undefined}
|
|
68
|
+
/>
|
|
69
|
+
{:else if resolvedType === 'lucide' && lucideComponent}
|
|
70
|
+
<!-- Lucide icon by name -->
|
|
71
|
+
<svelte:component
|
|
72
|
+
this={lucideComponent}
|
|
73
|
+
size={sizeNum}
|
|
74
|
+
class="inline-block {className}"
|
|
75
|
+
style={color ? `color: ${color}` : undefined}
|
|
76
|
+
/>
|
|
77
|
+
{:else if resolvedType === 'url'}
|
|
78
|
+
<!-- URL-based icon (image) -->
|
|
79
|
+
<img
|
|
80
|
+
src={icon}
|
|
81
|
+
alt=""
|
|
82
|
+
width={sizeNum}
|
|
83
|
+
height={sizeNum}
|
|
84
|
+
class="inline-block object-contain {className}"
|
|
85
|
+
style="width: {sizeValue}; height: {sizeValue};"
|
|
86
|
+
/>
|
|
87
|
+
{:else if resolvedType === 'fa'}
|
|
88
|
+
<!-- Font Awesome icon -->
|
|
89
|
+
<i
|
|
90
|
+
class="{icon} {className}"
|
|
91
|
+
style="font-size: {sizeValue}; {color ? `color: ${color}` : ''}"
|
|
92
|
+
aria-hidden="true"
|
|
93
|
+
></i>
|
|
94
|
+
{:else}
|
|
95
|
+
<!-- Fallback: render text (emoji or single char) -->
|
|
96
|
+
<span
|
|
97
|
+
class="inline-flex items-center justify-center {className}"
|
|
98
|
+
style="width: {sizeValue}; height: {sizeValue}; font-size: {sizeValue}; line-height: 1; {color ? `color: ${color}` : ''}"
|
|
99
|
+
aria-hidden="true"
|
|
100
|
+
>
|
|
101
|
+
{icon}
|
|
102
|
+
</span>
|
|
103
|
+
{/if}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ComponentType } from 'svelte';
|
|
2
|
+
interface Props {
|
|
3
|
+
icon: string | ComponentType;
|
|
4
|
+
iconType?: 'lucide' | 'url' | 'fa' | 'auto';
|
|
5
|
+
color?: string;
|
|
6
|
+
size?: number | string;
|
|
7
|
+
className?: string;
|
|
8
|
+
}
|
|
9
|
+
declare const Icon: import("svelte").Component<Props, {}, "">;
|
|
10
|
+
type Icon = ReturnType<typeof Icon>;
|
|
11
|
+
export default Icon;
|