@baybreezy/docd 0.0.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.
- package/app/app.config.ts +239 -0
- package/app/app.vue +19 -0
- package/app/assets/css/tailwind.css +335 -0
- package/app/assets/css/theme.css +1171 -0
- package/app/components/OgImage/Docs.takumi.vue +69 -0
- package/app/components/OgImage/Landing.takumi.vue +64 -0
- package/app/components/OgImage/Site.takumi.vue +32 -0
- package/app/components/Ui/Avatar/Avatar.vue +75 -0
- package/app/components/Ui/Avatar/Badge.vue +34 -0
- package/app/components/Ui/Avatar/Fallback.vue +30 -0
- package/app/components/Ui/Avatar/Group.vue +29 -0
- package/app/components/Ui/Avatar/GroupCount.vue +29 -0
- package/app/components/Ui/Avatar/Image.vue +29 -0
- package/app/components/Ui/Badge.vue +86 -0
- package/app/components/Ui/BadgeGroup.vue +314 -0
- package/app/components/Ui/BgPattern/Grid.vue +137 -0
- package/app/components/Ui/BorderBeam.vue +97 -0
- package/app/components/Ui/Breadcrumbs.vue +103 -0
- package/app/components/Ui/Button.vue +169 -0
- package/app/components/Ui/ButtonGroup/ButtonGroup.vue +54 -0
- package/app/components/Ui/ButtonGroup/Separator.vue +38 -0
- package/app/components/Ui/ButtonGroup/Text.vue +33 -0
- package/app/components/Ui/Card/Action.vue +31 -0
- package/app/components/Ui/Card/Card.vue +58 -0
- package/app/components/Ui/Card/Content.vue +34 -0
- package/app/components/Ui/Card/Description.vue +36 -0
- package/app/components/Ui/Card/Footer.vue +31 -0
- package/app/components/Ui/Card/Header.vue +31 -0
- package/app/components/Ui/Card/Title.vue +37 -0
- package/app/components/Ui/Collapsible/Collapsible.vue +16 -0
- package/app/components/Ui/Collapsible/Content.vue +27 -0
- package/app/components/Ui/Collapsible/Trigger.vue +13 -0
- package/app/components/Ui/Command/Command.vue +115 -0
- package/app/components/Ui/Command/Dialog.vue +65 -0
- package/app/components/Ui/Command/Empty.vue +32 -0
- package/app/components/Ui/Command/Footer.vue +40 -0
- package/app/components/Ui/Command/Group.vue +58 -0
- package/app/components/Ui/Command/Input.vue +57 -0
- package/app/components/Ui/Command/Item.vue +102 -0
- package/app/components/Ui/Command/List.vue +33 -0
- package/app/components/Ui/Command/Separator.vue +30 -0
- package/app/components/Ui/Command/Shortcut.vue +28 -0
- package/app/components/Ui/Container.vue +46 -0
- package/app/components/Ui/ContextMenu/Arrow.vue +43 -0
- package/app/components/Ui/ContextMenu/CheckboxItem.vue +42 -0
- package/app/components/Ui/ContextMenu/Content.vue +53 -0
- package/app/components/Ui/ContextMenu/ContextMenu.vue +14 -0
- package/app/components/Ui/ContextMenu/Group.vue +12 -0
- package/app/components/Ui/ContextMenu/Item.vue +65 -0
- package/app/components/Ui/ContextMenu/ItemIndicator.vue +30 -0
- package/app/components/Ui/ContextMenu/Label.vue +35 -0
- package/app/components/Ui/ContextMenu/Portal.vue +12 -0
- package/app/components/Ui/ContextMenu/RadioGroup.vue +16 -0
- package/app/components/Ui/ContextMenu/RadioItem.vue +40 -0
- package/app/components/Ui/ContextMenu/Separator.vue +25 -0
- package/app/components/Ui/ContextMenu/Shortcut.vue +30 -0
- package/app/components/Ui/ContextMenu/Sub.vue +15 -0
- package/app/components/Ui/ContextMenu/SubContent.vue +55 -0
- package/app/components/Ui/ContextMenu/SubTrigger.vue +42 -0
- package/app/components/Ui/ContextMenu/Trigger.vue +12 -0
- package/app/components/Ui/Dialog/Close.vue +12 -0
- package/app/components/Ui/Dialog/Content.vue +79 -0
- package/app/components/Ui/Dialog/Description.vue +29 -0
- package/app/components/Ui/Dialog/Dialog.vue +14 -0
- package/app/components/Ui/Dialog/Footer.vue +32 -0
- package/app/components/Ui/Dialog/Header.vue +32 -0
- package/app/components/Ui/Dialog/Overlay.vue +25 -0
- package/app/components/Ui/Dialog/Portal.vue +12 -0
- package/app/components/Ui/Dialog/Title.vue +29 -0
- package/app/components/Ui/Dialog/Trigger.vue +12 -0
- package/app/components/Ui/Divider.vue +102 -0
- package/app/components/Ui/Drawer/Close.vue +12 -0
- package/app/components/Ui/Drawer/Content.vue +67 -0
- package/app/components/Ui/Drawer/Description.vue +33 -0
- package/app/components/Ui/Drawer/Drawer.vue +17 -0
- package/app/components/Ui/Drawer/Footer.vue +35 -0
- package/app/components/Ui/Drawer/Header.vue +34 -0
- package/app/components/Ui/Drawer/Overlay.vue +20 -0
- package/app/components/Ui/Drawer/Portal.vue +12 -0
- package/app/components/Ui/Drawer/Title.vue +35 -0
- package/app/components/Ui/Drawer/Trigger.vue +12 -0
- package/app/components/Ui/DropdownMenu/Arrow.vue +43 -0
- package/app/components/Ui/DropdownMenu/CheckboxItem.vue +41 -0
- package/app/components/Ui/DropdownMenu/Content.vue +56 -0
- package/app/components/Ui/DropdownMenu/DropdownMenu.vue +15 -0
- package/app/components/Ui/DropdownMenu/Group.vue +12 -0
- package/app/components/Ui/DropdownMenu/Item.vue +64 -0
- package/app/components/Ui/DropdownMenu/ItemIndicator.vue +32 -0
- package/app/components/Ui/DropdownMenu/Label.vue +34 -0
- package/app/components/Ui/DropdownMenu/Portal.vue +12 -0
- package/app/components/Ui/DropdownMenu/RadioGroup.vue +16 -0
- package/app/components/Ui/DropdownMenu/RadioItem.vue +40 -0
- package/app/components/Ui/DropdownMenu/Separator.vue +25 -0
- package/app/components/Ui/DropdownMenu/Shortcut.vue +44 -0
- package/app/components/Ui/DropdownMenu/Sub.vue +14 -0
- package/app/components/Ui/DropdownMenu/SubContent.vue +56 -0
- package/app/components/Ui/DropdownMenu/SubTrigger.vue +47 -0
- package/app/components/Ui/DropdownMenu/Trigger.vue +12 -0
- package/app/components/Ui/FancyIcon.vue +243 -0
- package/app/components/Ui/GradientDivider.vue +26 -0
- package/app/components/Ui/IframeLazy.vue +97 -0
- package/app/components/Ui/Input.vue +97 -0
- package/app/components/Ui/InputGroup/Addon.vue +66 -0
- package/app/components/Ui/InputGroup/Button.vue +50 -0
- package/app/components/Ui/InputGroup/Input.vue +25 -0
- package/app/components/Ui/InputGroup/InputGroup.vue +44 -0
- package/app/components/Ui/InputGroup/Text.vue +33 -0
- package/app/components/Ui/InputGroup/Textarea.vue +25 -0
- package/app/components/Ui/Kbd/Group.vue +32 -0
- package/app/components/Ui/Kbd/Kbd.vue +62 -0
- package/app/components/Ui/Label.vue +40 -0
- package/app/components/Ui/Popover/Anchor.vue +13 -0
- package/app/components/Ui/Popover/Arrow.vue +42 -0
- package/app/components/Ui/Popover/Close.vue +13 -0
- package/app/components/Ui/Popover/Content.vue +55 -0
- package/app/components/Ui/Popover/Popover.vue +15 -0
- package/app/components/Ui/Popover/Portal.vue +13 -0
- package/app/components/Ui/Popover/Trigger.vue +12 -0
- package/app/components/Ui/Popover/X.vue +38 -0
- package/app/components/Ui/ScrollArea/Corner.vue +12 -0
- package/app/components/Ui/ScrollArea/ScrollArea.vue +38 -0
- package/app/components/Ui/ScrollArea/Scrollbar.vue +39 -0
- package/app/components/Ui/ScrollArea/Thumb.vue +39 -0
- package/app/components/Ui/ScrollArea/Viewport.vue +27 -0
- package/app/components/Ui/Scrollspy.vue +61 -0
- package/app/components/Ui/Separator.vue +40 -0
- package/app/components/Ui/Skeleton.vue +39 -0
- package/app/components/Ui/Sonner.vue +25 -0
- package/app/components/Ui/Tabs/Content.vue +27 -0
- package/app/components/Ui/Tabs/Indicator.vue +37 -0
- package/app/components/Ui/Tabs/List.vue +37 -0
- package/app/components/Ui/Tabs/Tabs.vue +25 -0
- package/app/components/Ui/Tabs/Trigger.vue +41 -0
- package/app/components/Ui/Textarea.vue +81 -0
- package/app/components/Ui/Tooltip/Arrow.vue +30 -0
- package/app/components/Ui/Tooltip/Content.vue +50 -0
- package/app/components/Ui/Tooltip/Portal.vue +12 -0
- package/app/components/Ui/Tooltip/Provider.vue +14 -0
- package/app/components/Ui/Tooltip/Tooltip.vue +25 -0
- package/app/components/Ui/Tooltip/Trigger.vue +12 -0
- package/app/components/Ui/Tree/Item.vue +15 -0
- package/app/components/Ui/Tree/Tree.vue +15 -0
- package/app/components/Ui/Tree/Virtualizer.vue +13 -0
- package/app/components/component-api/ComponentApiSection.vue +135 -0
- package/app/components/content/docs/Callout/DocsCallout.vue +99 -0
- package/app/components/content/prose/ProseA.global.vue +31 -0
- package/app/components/content/prose/ProseBlockquote.global.vue +28 -0
- package/app/components/content/prose/ProseCallout.global.vue +306 -0
- package/app/components/content/prose/ProseCard.global.vue +100 -0
- package/app/components/content/prose/ProseCodeCollapse.global.vue +125 -0
- package/app/components/content/prose/ProseCodeCopy.global.vue +67 -0
- package/app/components/content/prose/ProseCodeGroup.global.vue +104 -0
- package/app/components/content/prose/ProseCodeTree.global.vue +277 -0
- package/app/components/content/prose/ProseCollapsible.global.vue +64 -0
- package/app/components/content/prose/ProseColorModeImage.global.vue +58 -0
- package/app/components/content/prose/ProseComponentApi.global.vue +104 -0
- package/app/components/content/prose/ProseComponentEvents.global.vue +27 -0
- package/app/components/content/prose/ProseComponentExposed.global.vue +27 -0
- package/app/components/content/prose/ProseComponentProps.global.vue +27 -0
- package/app/components/content/prose/ProseComponentSlots.global.vue +27 -0
- package/app/components/content/prose/ProseEm.global.vue +5 -0
- package/app/components/content/prose/ProseField.global.vue +118 -0
- package/app/components/content/prose/ProseFieldGroup.global.vue +62 -0
- package/app/components/content/prose/ProseH1.global.vue +58 -0
- package/app/components/content/prose/ProseH2.global.vue +58 -0
- package/app/components/content/prose/ProseH3.global.vue +58 -0
- package/app/components/content/prose/ProseH4.global.vue +58 -0
- package/app/components/content/prose/ProseH5.global.vue +47 -0
- package/app/components/content/prose/ProseH6.global.vue +47 -0
- package/app/components/content/prose/ProseHr.global.vue +33 -0
- package/app/components/content/prose/ProseIconList.global.vue +113 -0
- package/app/components/content/prose/ProseImg.global.vue +119 -0
- package/app/components/content/prose/ProseLead.global.vue +28 -0
- package/app/components/content/prose/ProseLi.global.vue +25 -0
- package/app/components/content/prose/ProseMermaid.global.vue +127 -0
- package/app/components/content/prose/ProseOl.global.vue +25 -0
- package/app/components/content/prose/ProseP.global.vue +25 -0
- package/app/components/content/prose/ProsePmInstall.global.vue +60 -0
- package/app/components/content/prose/ProsePmRun.global.vue +51 -0
- package/app/components/content/prose/ProsePmX.global.vue +56 -0
- package/app/components/content/prose/ProsePre.global.vue +181 -0
- package/app/components/content/prose/ProseShowCase.global.vue +56 -0
- package/app/components/content/prose/ProseSmartIcon.global.vue +54 -0
- package/app/components/content/prose/ProseStep.global.vue +22 -0
- package/app/components/content/prose/ProseSteps.global.vue +22 -0
- package/app/components/content/prose/ProseStrong.global.vue +34 -0
- package/app/components/content/prose/ProseTable.global.vue +34 -0
- package/app/components/content/prose/ProseTabs.global.vue +104 -0
- package/app/components/content/prose/ProseTabsInner.global.vue +274 -0
- package/app/components/content/prose/ProseTbody.global.vue +5 -0
- package/app/components/content/prose/ProseTd.global.vue +25 -0
- package/app/components/content/prose/ProseTh.global.vue +25 -0
- package/app/components/content/prose/ProseThead.global.vue +9 -0
- package/app/components/content/prose/ProseTr.global.vue +35 -0
- package/app/components/content/prose/ProseUl.global.vue +25 -0
- package/app/components/docs/DocsExtraStuff.vue +39 -0
- package/app/components/docs/DocsGithubLink.vue +11 -0
- package/app/components/docs/DocsHeader.vue +3 -0
- package/app/components/docs/DocsLogo.vue +74 -0
- package/app/components/docs/DocsMobileBar.vue +26 -0
- package/app/components/docs/DocsMobileNav.vue +49 -0
- package/app/components/docs/DocsNav.vue +161 -0
- package/app/components/docs/DocsPageTransition.vue +32 -0
- package/app/components/docs/DocsSearch.vue +220 -0
- package/app/components/docs/DocsSearchButton.vue +20 -0
- package/app/components/docs/DocsThemeCustomizer.vue +229 -0
- package/app/components/docs/DocsThemeToggler.vue +98 -0
- package/app/components/docs/DocsTocRail.vue +162 -0
- package/app/components/docs/DocsToclink.vue +52 -0
- package/app/components/docs/DocsZigZagRail.vue +70 -0
- package/app/components/landing/Hero.vue +222 -0
- package/app/components/page/PageFooter.vue +49 -0
- package/app/components/page/PageHeader.vue +68 -0
- package/app/components/page/PageHeaderLinks.vue +138 -0
- package/app/components/page/PageMobileToc.vue +162 -0
- package/app/components/page/PageToc.vue +33 -0
- package/app/composables/useDefaultSlotItems.ts +90 -0
- package/app/composables/useDocPage.ts +66 -0
- package/app/composables/useDocSearch.ts +23 -0
- package/app/composables/useDocd.ts +107 -0
- package/app/composables/useLogoAssets.ts +319 -0
- package/app/composables/usePm.ts +73 -0
- package/app/composables/useProseComponentMeta.ts +30 -0
- package/app/composables/useScrollspy.ts +327 -0
- package/app/composables/useSeo.ts +240 -0
- package/app/composables/useUIConfig.ts +36 -0
- package/app/layouts/default.vue +5 -0
- package/app/layouts/docs.vue +64 -0
- package/app/middleware/colorMode.global.ts +8 -0
- package/app/middleware/doc-page-layout.ts +11 -0
- package/app/middleware/landing-page-layout.ts +11 -0
- package/app/pages/[...slug].vue +63 -0
- package/app/plugins/mermaid.client.ts +35 -0
- package/app/plugins/navigation-direction.client.ts +15 -0
- package/app/plugins/theme-restore.client.ts +7 -0
- package/app/templates/landing.vue +40 -0
- package/app/transitions/presets.ts +71 -0
- package/app/types/prose-component-meta.d.ts +4 -0
- package/app/utils/og.ts +26 -0
- package/app/utils/prerender.ts +9 -0
- package/app/utils/translucent.ts +56 -0
- package/app/utils/tw-helper.ts +4 -0
- package/content.config.ts +81 -0
- package/index.d.ts +25 -0
- package/modules/config.ts +89 -0
- package/modules/custom-icons.ts +17 -0
- package/modules/markdown-rewrite.ts +96 -0
- package/modules/prose-component-meta.ts +150 -0
- package/modules/routing.ts +22 -0
- package/modules/skills/index.ts +167 -0
- package/modules/skills/runtime/server/routes/skills-files.ts +49 -0
- package/modules/skills/runtime/server/routes/skills-index.ts +8 -0
- package/nuxt.config.ts +96 -0
- package/nuxt.schema.ts +288 -0
- package/package.json +95 -0
- package/server/mcp/tools/get-page.ts +66 -0
- package/server/mcp/tools/list-pages.ts +61 -0
- package/server/routes/sitemap.xml.ts +73 -0
- package/server/utils/content.ts +3 -0
- package/tailwind.config.cjs +55 -0
- package/utils/component-api-content.ts +467 -0
- package/utils/component-api-discovery.ts +165 -0
- package/utils/component-api-schema.ts +28 -0
- package/utils/component-api.ts +243 -0
- package/utils/generate-prose-component-meta.ts +303 -0
- package/utils/git.ts +123 -0
- package/utils/meta.ts +40 -0
- package/utils/pages.ts +21 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div data-slot="prose-pre-wrapper" :class="styles().wrapper({ class: $attrs?.class as any })">
|
|
3
|
+
<template v-if="hasFileName">
|
|
4
|
+
<div data-slot="prose-pre-file-name-wrapper" :class="styles().fileNameWrapper()">
|
|
5
|
+
<prose-smart-icon v-if="iconFromMeta" :name="iconFromMeta" class="size-4 shrink-0" />
|
|
6
|
+
<img
|
|
7
|
+
v-else-if="language || filename"
|
|
8
|
+
:src="getMaterialFileIcon(language! || filename!)"
|
|
9
|
+
:alt="language || filename"
|
|
10
|
+
class="size-4 shrink-0"
|
|
11
|
+
/>
|
|
12
|
+
|
|
13
|
+
<p data-slot="prose-pre-file-name" :class="styles().fileName()">{{ fileNameEdited }}</p>
|
|
14
|
+
</div>
|
|
15
|
+
</template>
|
|
16
|
+
<div
|
|
17
|
+
v-if="!hideCopyButton"
|
|
18
|
+
class="absolute right-3.5 flex items-center justify-center"
|
|
19
|
+
:class="[hasFileName ? 'top-2.75' : 'top-3']"
|
|
20
|
+
>
|
|
21
|
+
<prose-code-copy :code @code-copied="onCopy" />
|
|
22
|
+
</div>
|
|
23
|
+
<ProseMermaid v-if="isMermaid" :code="code" @mermaid-error="onMermaidError">
|
|
24
|
+
<slot />
|
|
25
|
+
</ProseMermaid>
|
|
26
|
+
<pre v-else :class="[$attrs?.class, 'shadow-xs ring-1 ring-border/60']"><slot /></pre>
|
|
27
|
+
</div>
|
|
28
|
+
</template>
|
|
29
|
+
|
|
30
|
+
<script lang="ts" setup>
|
|
31
|
+
import { getMaterialFileIcon } from "@baybreezy/file-extension-icon";
|
|
32
|
+
import { startCase } from "lodash-es";
|
|
33
|
+
|
|
34
|
+
const { page } = await useDocPage();
|
|
35
|
+
const route = useRoute();
|
|
36
|
+
|
|
37
|
+
const props = defineProps<{
|
|
38
|
+
/**
|
|
39
|
+
* The code content to display
|
|
40
|
+
*/
|
|
41
|
+
code?: string;
|
|
42
|
+
/**
|
|
43
|
+
* The programming language of the code block
|
|
44
|
+
*/
|
|
45
|
+
language?: string;
|
|
46
|
+
/**
|
|
47
|
+
* The filename to display in the header (if any)
|
|
48
|
+
*/
|
|
49
|
+
filename?: string;
|
|
50
|
+
/**
|
|
51
|
+
* An array of line numbers to highlight
|
|
52
|
+
*/
|
|
53
|
+
highlights?: Array<number>;
|
|
54
|
+
/**
|
|
55
|
+
* Additional meta information for the code block
|
|
56
|
+
*/
|
|
57
|
+
meta?: string;
|
|
58
|
+
/**
|
|
59
|
+
* Optional icon name to display next to the filename
|
|
60
|
+
*/
|
|
61
|
+
icon?: string;
|
|
62
|
+
}>();
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Parse meta string and create a lowercase key map for easy checking
|
|
66
|
+
* Example: "noFormat hideHeader icon='lucide:code'" => Map { 'noformat' => true, 'hideheader' => true, 'icon' => 'lucide:code' }
|
|
67
|
+
*/
|
|
68
|
+
const metaMap = computed(() => {
|
|
69
|
+
const map = new Map<string, string | boolean>();
|
|
70
|
+
if (!props.meta) return map;
|
|
71
|
+
|
|
72
|
+
// Split by spaces but preserve quoted values
|
|
73
|
+
const parts = props.meta.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g) || [];
|
|
74
|
+
|
|
75
|
+
parts.forEach((part) => {
|
|
76
|
+
// Check if it's a key=value pair
|
|
77
|
+
const keyValueMatch = part.match(/^([^=]+)=(.+)$/);
|
|
78
|
+
if (keyValueMatch) {
|
|
79
|
+
const key = keyValueMatch[1]!.toLowerCase();
|
|
80
|
+
// Remove quotes from value if present
|
|
81
|
+
const value = keyValueMatch[2]!.replace(/^["']|["']$/g, "");
|
|
82
|
+
map.set(key, value);
|
|
83
|
+
} else {
|
|
84
|
+
// It's just a flag (boolean)
|
|
85
|
+
map.set(part.toLowerCase(), true);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
return map;
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const hideCopyButton = ref(false);
|
|
93
|
+
const noFormatMeta = computed(() => metaMap.value.has("noformat"));
|
|
94
|
+
const hideHeaderMeta = computed(
|
|
95
|
+
() => metaMap.value.has("hideheader") || metaMap.value.has("noheader")
|
|
96
|
+
);
|
|
97
|
+
const hasLinesInMeta = computed(() => metaMap.value.has("lines"));
|
|
98
|
+
const metaHasMermaid = computed(() => metaMap.value.has("mermaid"));
|
|
99
|
+
|
|
100
|
+
const iconFromMeta = computed(() => {
|
|
101
|
+
// First check if icon is passed as a direct prop
|
|
102
|
+
if (props.icon) return props.icon;
|
|
103
|
+
// Then check metaMap for icon key
|
|
104
|
+
const icon = metaMap.value.get("icon");
|
|
105
|
+
return typeof icon === "string" ? icon : undefined;
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const fileNameEdited = computed(() => {
|
|
109
|
+
if (!props.filename) return;
|
|
110
|
+
if (noFormatMeta.value) return props.filename;
|
|
111
|
+
|
|
112
|
+
let processedName = props.filename;
|
|
113
|
+
|
|
114
|
+
// Check if it looks like a filename (ends with .[anything])
|
|
115
|
+
const hasFileExtension = /\.[^.]+$/.test(processedName);
|
|
116
|
+
|
|
117
|
+
if (hasFileExtension) {
|
|
118
|
+
// It's a filename - remove the extension
|
|
119
|
+
processedName = processedName.split(".").slice(0, -1).join(".");
|
|
120
|
+
// if we have something like .env or .gitignore, we might end up with an empty string
|
|
121
|
+
if (!processedName) {
|
|
122
|
+
processedName = props.filename;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Clean up any extra spaces and apply startCase
|
|
127
|
+
return startCase(processedName.trim());
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
const hasFileName = computed(() => !!props.filename && !hideHeaderMeta.value);
|
|
131
|
+
const isMermaid = computed(() => props.language === "mermaid" || metaHasMermaid.value);
|
|
132
|
+
|
|
133
|
+
const onMermaidError = (errorMessage?: string) => {
|
|
134
|
+
if (errorMessage) {
|
|
135
|
+
hideCopyButton.value = true;
|
|
136
|
+
} else {
|
|
137
|
+
hideCopyButton.value = false;
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const onCopy = () => {
|
|
142
|
+
// Track copied code event
|
|
143
|
+
useTrackEvent("copy_code", {
|
|
144
|
+
code_source: "inline",
|
|
145
|
+
code_language: props.language,
|
|
146
|
+
file_name: props.filename,
|
|
147
|
+
block_path: "N/A",
|
|
148
|
+
component: props.filename,
|
|
149
|
+
page_title: page.value?.title || "unknown",
|
|
150
|
+
page_path: route.path,
|
|
151
|
+
page_location: window.location.href,
|
|
152
|
+
});
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const styles = tv({
|
|
156
|
+
slots: {
|
|
157
|
+
wrapper: [
|
|
158
|
+
"relative mt-3 rounded-lg border bg-muted/60 p-1.5 dark:bg-muted/10",
|
|
159
|
+
hasLinesInMeta.value && "show-line-number",
|
|
160
|
+
],
|
|
161
|
+
fileNameWrapper: "not-prose flex items-center gap-2 p-2 pb-4",
|
|
162
|
+
fileName: "truncate text-sm font-medium text-ellipsis",
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
</script>
|
|
166
|
+
|
|
167
|
+
<style>
|
|
168
|
+
.show-line-number .line::before {
|
|
169
|
+
font-size: var(--text-sm);
|
|
170
|
+
line-height: var(--tw-leading, var(--text-xs--line-height));
|
|
171
|
+
width: calc(var(--spacing) * 5);
|
|
172
|
+
display: inline-block;
|
|
173
|
+
text-align: center;
|
|
174
|
+
margin-right: calc(var(--spacing) * 4);
|
|
175
|
+
color: var(--muted-foreground);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.show-line-number .line:not(.diff)::before {
|
|
179
|
+
content: attr(line);
|
|
180
|
+
}
|
|
181
|
+
</style>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<TabsRoot v-model="tab">
|
|
3
|
+
<TabsList class="relative inline-flex items-center">
|
|
4
|
+
<UiTabsTrigger aria-label="Preview" :pill="false" value="preview"> Preview </UiTabsTrigger>
|
|
5
|
+
<UiTabsTrigger aria-label="Code" :pill="false" value="code"> Code </UiTabsTrigger>
|
|
6
|
+
<UiTabsIndicator class="px-3" />
|
|
7
|
+
</TabsList>
|
|
8
|
+
<LayoutGroup>
|
|
9
|
+
<AnimatePresence mode="wait">
|
|
10
|
+
<Motion
|
|
11
|
+
v-if="tab == 'preview'"
|
|
12
|
+
layout="position"
|
|
13
|
+
:initial="false"
|
|
14
|
+
:animate="{ opacity: 1 }"
|
|
15
|
+
:exit="{ opacity: 0 }"
|
|
16
|
+
:transition="{ duration: 0.2 }"
|
|
17
|
+
>
|
|
18
|
+
<TabsContent force-mount value="preview">
|
|
19
|
+
<div
|
|
20
|
+
class="mt-4 flex min-h-75 items-center justify-center rounded-lg border p-3 lg:p-10"
|
|
21
|
+
:class="[isDashed ? 'border-dashed' : '']"
|
|
22
|
+
>
|
|
23
|
+
<div class="mx-auto w-full" :class="[!props.prose ? 'not-prose' : '']">
|
|
24
|
+
<slot />
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
</TabsContent>
|
|
28
|
+
</Motion>
|
|
29
|
+
<Motion
|
|
30
|
+
v-else
|
|
31
|
+
layout="position"
|
|
32
|
+
:initial="{ opacity: 0 }"
|
|
33
|
+
:animate="{ opacity: 1 }"
|
|
34
|
+
:exit="{ opacity: 0 }"
|
|
35
|
+
:transition="{ duration: 0.2 }"
|
|
36
|
+
>
|
|
37
|
+
<TabsContent force-mount value="code">
|
|
38
|
+
<slot name="code" mdc-unwrap="p" />
|
|
39
|
+
</TabsContent>
|
|
40
|
+
</Motion>
|
|
41
|
+
</AnimatePresence>
|
|
42
|
+
</LayoutGroup>
|
|
43
|
+
</TabsRoot>
|
|
44
|
+
</template>
|
|
45
|
+
|
|
46
|
+
<script lang="ts" setup>
|
|
47
|
+
import { TabsContent, TabsList, TabsRoot } from "reka-ui";
|
|
48
|
+
|
|
49
|
+
const tab = ref("preview");
|
|
50
|
+
|
|
51
|
+
const props = defineProps<{
|
|
52
|
+
prose?: boolean;
|
|
53
|
+
}>();
|
|
54
|
+
|
|
55
|
+
const { isDashed } = useDocd();
|
|
56
|
+
</script>
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<!-- Iconify Icons -->
|
|
3
|
+
<Icon v-if="checkIcon(name)" :name :size />
|
|
4
|
+
<!-- Emojis -->
|
|
5
|
+
<span
|
|
6
|
+
v-else-if="
|
|
7
|
+
/(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])/g.test(
|
|
8
|
+
name
|
|
9
|
+
)
|
|
10
|
+
"
|
|
11
|
+
:style="`font-size: ${size}px;`"
|
|
12
|
+
aria-hidden="true"
|
|
13
|
+
>{{ name }}</span
|
|
14
|
+
>
|
|
15
|
+
<!-- Link -->
|
|
16
|
+
<NuxtImg
|
|
17
|
+
v-else
|
|
18
|
+
:src="name"
|
|
19
|
+
:style="`width: ${size}px; height: ${size}px;`"
|
|
20
|
+
:class="['not-prose inline', $attrs.class]"
|
|
21
|
+
/>
|
|
22
|
+
</template>
|
|
23
|
+
|
|
24
|
+
<script lang="ts">
|
|
25
|
+
import { stringToIcon, validateIconName } from "@iconify/utils";
|
|
26
|
+
|
|
27
|
+
export type SmartIconProps = {
|
|
28
|
+
/**
|
|
29
|
+
* This can be on of the following:
|
|
30
|
+
*
|
|
31
|
+
* - An [Iconify](https://icon-sets.iconify.design/) icon name, e.g. `mdi:home`
|
|
32
|
+
* - An emoji, e.g. `😀`
|
|
33
|
+
* - A link to an image, e.g. `https://example.com/icon.png`
|
|
34
|
+
*/
|
|
35
|
+
name: string;
|
|
36
|
+
/**
|
|
37
|
+
* Size of the icon in pixels (default: 16)
|
|
38
|
+
* @default 16
|
|
39
|
+
*/
|
|
40
|
+
size?: number;
|
|
41
|
+
};
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
<script setup lang="ts">
|
|
45
|
+
const { size = 16 } = defineProps<SmartIconProps>();
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Check if the provided name is a valid Iconify icon name
|
|
49
|
+
*/
|
|
50
|
+
function checkIcon(name: string): boolean {
|
|
51
|
+
if (name.includes("http") || name.startsWith("data:image/")) return false;
|
|
52
|
+
return validateIconName(stringToIcon(name));
|
|
53
|
+
}
|
|
54
|
+
</script>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="styles({ class: normalizeClass(props.class) || undefined })">
|
|
3
|
+
<slot />
|
|
4
|
+
</div>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script lang="ts" setup>
|
|
8
|
+
import { normalizeClass } from "vue";
|
|
9
|
+
import type { HtmlHTMLAttributes } from "vue";
|
|
10
|
+
|
|
11
|
+
const props = withDefaults(
|
|
12
|
+
defineProps<{
|
|
13
|
+
/** Additional CSS classes to apply to the step item */
|
|
14
|
+
class?: HtmlHTMLAttributes["class"];
|
|
15
|
+
}>(),
|
|
16
|
+
{}
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
const styles = tv({
|
|
20
|
+
base: "before:absolute before:-left-4 before:z-10 before:flex before:h-8 before:w-8 before:items-center before:justify-center before:rounded-full before:bg-secondary before:text-sm before:text-secondary-foreground before:content-[counter(step)] before:[counter-increment:step]",
|
|
21
|
+
});
|
|
22
|
+
</script>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="styles({ class: normalizeClass(props.class) || undefined })">
|
|
3
|
+
<slot />
|
|
4
|
+
</div>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script lang="ts" setup>
|
|
8
|
+
import { normalizeClass } from "vue";
|
|
9
|
+
import type { HtmlHTMLAttributes } from "vue";
|
|
10
|
+
|
|
11
|
+
const props = withDefaults(
|
|
12
|
+
defineProps<{
|
|
13
|
+
/** Additional CSS classes to apply to the steps container */
|
|
14
|
+
class?: HtmlHTMLAttributes["class"];
|
|
15
|
+
}>(),
|
|
16
|
+
{}
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
const styles = tv({
|
|
20
|
+
base: "relative ml-4 border-l pl-7 [counter-reset:step]",
|
|
21
|
+
});
|
|
22
|
+
</script>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<strong
|
|
3
|
+
data-slot="prose-strong"
|
|
4
|
+
:class="proseStrongStyles({ class: normalizeClass(_class) || undefined })"
|
|
5
|
+
>
|
|
6
|
+
<slot />
|
|
7
|
+
</strong>
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<script lang="ts">
|
|
11
|
+
import { normalizeClass } from "vue";
|
|
12
|
+
import type { HTMLAttributes } from "vue";
|
|
13
|
+
|
|
14
|
+
export type ProseStrongProps = {
|
|
15
|
+
/**
|
|
16
|
+
* Additional classes for the parent element
|
|
17
|
+
*/
|
|
18
|
+
class?: HTMLAttributes["class"];
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const proseStrongStyles = tv({
|
|
22
|
+
base: "font-semibold text-inherit",
|
|
23
|
+
});
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<script setup lang="ts">
|
|
27
|
+
const { class: _class } = defineProps<ProseStrongProps>();
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<style>
|
|
31
|
+
[data-slot="prose-strong"] + [data-slot="prose-strong"] {
|
|
32
|
+
margin-inline-start: 0.25em;
|
|
33
|
+
}
|
|
34
|
+
</style>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="proseTableStyles({ class: normalizeClass(_class) || undefined, isDashed })">
|
|
3
|
+
<table class="relative mt-0 mb-0 w-full overflow-hidden border-none" data-slot="prose-table">
|
|
4
|
+
<slot />
|
|
5
|
+
</table>
|
|
6
|
+
</div>
|
|
7
|
+
</template>
|
|
8
|
+
|
|
9
|
+
<script lang="ts">
|
|
10
|
+
import { normalizeClass } from "vue";
|
|
11
|
+
import type { HTMLAttributes } from "vue";
|
|
12
|
+
|
|
13
|
+
export type ProseTableProps = {
|
|
14
|
+
/**
|
|
15
|
+
* Additional classes for the parent element
|
|
16
|
+
*/
|
|
17
|
+
class?: HTMLAttributes["class"];
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const proseTableStyles = tv({
|
|
21
|
+
base: "w-full overflow-y-auto rounded-md border not-last:mb-6",
|
|
22
|
+
variants: {
|
|
23
|
+
isDashed: {
|
|
24
|
+
true: "border-dashed",
|
|
25
|
+
false: "",
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<script setup lang="ts">
|
|
32
|
+
const { class: _class } = defineProps<ProseTableProps>();
|
|
33
|
+
const { isDashed } = useDocd();
|
|
34
|
+
</script>
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<render />
|
|
3
|
+
</template>
|
|
4
|
+
|
|
5
|
+
<script lang="ts">
|
|
6
|
+
import type { HTMLAttributes } from "vue";
|
|
7
|
+
|
|
8
|
+
import { ProseTabsInner } from "#components";
|
|
9
|
+
|
|
10
|
+
export type ProseTabsProps = {
|
|
11
|
+
/**
|
|
12
|
+
* The variant of the tabs
|
|
13
|
+
* @default 'separate'
|
|
14
|
+
*/
|
|
15
|
+
variant?: "separate" | "card" | "line" | "combobox";
|
|
16
|
+
/**
|
|
17
|
+
* Whether to add padding around the tabs
|
|
18
|
+
* @default true
|
|
19
|
+
*/
|
|
20
|
+
padded?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Whether the tabs are in a stack (e.g. accordion)
|
|
23
|
+
* @default false
|
|
24
|
+
*/
|
|
25
|
+
inStack?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Disable the search functionality
|
|
28
|
+
* @default false
|
|
29
|
+
*/
|
|
30
|
+
disableSearch?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Placeholder text for the search input
|
|
33
|
+
* @default 'Search Tab...'
|
|
34
|
+
*/
|
|
35
|
+
searchPlaceholder?: string;
|
|
36
|
+
/**
|
|
37
|
+
* Text to display when no tab is found
|
|
38
|
+
* @default 'No tab found.'
|
|
39
|
+
*/
|
|
40
|
+
searchEmpty?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Whether the combobox should take the full width of the container
|
|
43
|
+
* @default false
|
|
44
|
+
*/
|
|
45
|
+
comboBoxFullWidth?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* A scope to sync the active tab state with other tab groups
|
|
48
|
+
*/
|
|
49
|
+
sync?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Additional classes to add to the wrapper div
|
|
52
|
+
*/
|
|
53
|
+
class?: HTMLAttributes["class"];
|
|
54
|
+
};
|
|
55
|
+
</script>
|
|
56
|
+
|
|
57
|
+
<script setup lang="ts">
|
|
58
|
+
const {
|
|
59
|
+
variant = "separate",
|
|
60
|
+
padded = true,
|
|
61
|
+
inStack = false,
|
|
62
|
+
disableSearch = false,
|
|
63
|
+
searchPlaceholder = "Search Tab...",
|
|
64
|
+
searchEmpty = "No tab found.",
|
|
65
|
+
...rest
|
|
66
|
+
} = defineProps<ProseTabsProps>();
|
|
67
|
+
|
|
68
|
+
const _slots = useSlots();
|
|
69
|
+
const { items: slotItems } = useDefaultSlotItems({
|
|
70
|
+
slots: _slots,
|
|
71
|
+
mapMeta: ({ props, index }) => ({
|
|
72
|
+
label: props.label ?? props.filename ?? `Tab ${index + 1}`,
|
|
73
|
+
icon: props?.icon,
|
|
74
|
+
}),
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const slotsData = computed(() =>
|
|
78
|
+
slotItems.value.map(({ index, meta, props }) => ({
|
|
79
|
+
index,
|
|
80
|
+
label: meta.label,
|
|
81
|
+
icon: props.icon || meta.icon,
|
|
82
|
+
}))
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Render function to pass slots as props to ProseTabsInner
|
|
87
|
+
*/
|
|
88
|
+
function render() {
|
|
89
|
+
return h(
|
|
90
|
+
ProseTabsInner,
|
|
91
|
+
{
|
|
92
|
+
variant,
|
|
93
|
+
padded,
|
|
94
|
+
inStack,
|
|
95
|
+
disableSearch,
|
|
96
|
+
searchEmpty,
|
|
97
|
+
searchPlaceholder,
|
|
98
|
+
slotsData: slotsData.value,
|
|
99
|
+
...rest,
|
|
100
|
+
},
|
|
101
|
+
() => slotItems.value.map(({ vnode }) => vnode)
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
</script>
|