@wordup-md/nuxt-layer-shadcn-unocss 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.
Files changed (359) hide show
  1. package/.cursor/rules/active-context-rule.mdc +8 -0
  2. package/.cursor/rules/memory-bank-overview.mdc +17 -0
  3. package/.cursor/rules/product-context-rule.mdc +8 -0
  4. package/.cursor/rules/progress-rule.mdc +8 -0
  5. package/.cursor/rules/projectbrief-rule.mdc +8 -0
  6. package/.cursor/rules/system-patterns-rule.mdc +8 -0
  7. package/.cursor/rules/tech-context-rule.mdc +8 -0
  8. package/.cursorrules +52 -0
  9. package/.editorconfig +12 -0
  10. package/.nuxtrc +1 -0
  11. package/.playground/app.config.ts +189 -0
  12. package/.playground/assets/style.css +15 -0
  13. package/.playground/components/content/MdcExample.vue +81 -0
  14. package/.playground/components/content/MdcReplay.vue +319 -0
  15. package/.playground/content/1.getting-started/1.introduction.md +8 -0
  16. package/.playground/content/1.getting-started/2.writing/1.markdown.md +56 -0
  17. package/.playground/content/1.getting-started/2.writing/2.pages.md +177 -0
  18. package/.playground/content/1.getting-started/2.writing/3.folders.md +56 -0
  19. package/.playground/content/1.getting-started/2.writing/_dir.yml +3 -0
  20. package/.playground/content/1.getting-started/_dir.yml +3 -0
  21. package/.playground/content/2.content-elements/1.text-formatting.md +60 -0
  22. package/.playground/content/2.content-elements/10.horizontal-rule.md +25 -0
  23. package/.playground/content/2.content-elements/11.tables.md +25 -0
  24. package/.playground/content/2.content-elements/12.overview.md +93 -0
  25. package/.playground/content/2.content-elements/13.text-components.md +36 -0
  26. package/.playground/content/2.content-elements/2.headings.md +32 -0
  27. package/.playground/content/2.content-elements/3.paragraphs.md +39 -0
  28. package/.playground/content/2.content-elements/4.lists.md +37 -0
  29. package/.playground/content/2.content-elements/5.links.md +17 -0
  30. package/.playground/content/2.content-elements/6.images.md +17 -0
  31. package/.playground/content/2.content-elements/7.blockquotes.md +17 -0
  32. package/.playground/content/2.content-elements/8.code-blocks.md +141 -0
  33. package/.playground/content/2.content-elements/9.inline-code.md +21 -0
  34. package/.playground/content/2.content-elements/_dir.yml +3 -0
  35. package/.playground/content/2.content-elements/index.md +8 -0
  36. package/.playground/content/3.components/1.index.md +187 -0
  37. package/.playground/content/3.components/2.docs/_dir.yml +3 -0
  38. package/.playground/content/3.components/2.docs/alert.md +152 -0
  39. package/.playground/content/3.components/2.docs/badge.md +131 -0
  40. package/.playground/content/3.components/2.docs/button-link.md +53 -0
  41. package/.playground/content/3.components/2.docs/callout.md +16 -0
  42. package/.playground/content/3.components/2.docs/code-group.md +77 -0
  43. package/.playground/content/3.components/2.docs/code-snippet.md +129 -0
  44. package/.playground/content/3.components/2.docs/field-group.md +62 -0
  45. package/.playground/content/3.components/2.docs/field.md +39 -0
  46. package/.playground/content/3.components/2.docs/file-tree.md +144 -0
  47. package/.playground/content/3.components/2.docs/icon.md +94 -0
  48. package/.playground/content/3.components/2.docs/pm.md +67 -0
  49. package/.playground/content/3.components/2.docs/read-more.md +44 -0
  50. package/.playground/content/3.components/2.docs/shortcut.md +36 -0
  51. package/.playground/content/3.components/2.docs/stack.md +81 -0
  52. package/.playground/content/3.components/2.docs/steps.md +148 -0
  53. package/.playground/content/3.components/2.docs/tabs.md +375 -0
  54. package/.playground/content/3.components/3.page/_dir.yml +2 -0
  55. package/.playground/content/3.components/3.page/accordion.md +74 -0
  56. package/.playground/content/3.components/3.page/card-group.md +115 -0
  57. package/.playground/content/3.components/3.page/card.md +142 -0
  58. package/.playground/content/3.components/3.page/collapsible.md +61 -0
  59. package/.playground/content/3.components/3.page/hero-alt.md +118 -0
  60. package/.playground/content/3.components/3.page/hero.md +60 -0
  61. package/.playground/content/3.components/3.page/team-card.md +82 -0
  62. package/.playground/content/3.components/_dir.yml +2 -0
  63. package/.playground/content/4.development/1.configuration/1.overview.md +297 -0
  64. package/.playground/content/4.development/1.configuration/2.nuxt-content.md +105 -0
  65. package/.playground/content/4.development/1.configuration/3.og-image.md +86 -0
  66. package/.playground/content/4.development/1.configuration/4.edit-link.md +63 -0
  67. package/.playground/content/4.development/1.configuration/5.banner.md +52 -0
  68. package/.playground/content/4.development/1.configuration/6.carbon-ads.md +65 -0
  69. package/.playground/content/4.development/1.configuration/7.umami.md +41 -0
  70. package/.playground/content/4.development/1.configuration/_dir.yml +3 -0
  71. package/.playground/content/4.development/2.advanced/1.override.md +49 -0
  72. package/.playground/content/4.development/2.advanced/2.math.md +89 -0
  73. package/.playground/content/4.development/2.advanced/_dir.yml +3 -0
  74. package/.playground/content/4.development/3.themes.md +9 -0
  75. package/.playground/content/4.development/4.composables.md +38 -0
  76. package/.playground/content/4.development/5.installation.md +36 -0
  77. package/.playground/content/4.development/_dir.yml +3 -0
  78. package/.playground/content/_menu-footer.md +5 -0
  79. package/.playground/content/index.md +67 -0
  80. package/.playground/content/test-card.md +187 -0
  81. package/.playground/content/test.md +88 -0
  82. package/.playground/content/test2.md +12 -0
  83. package/.playground/content/test3.md +187 -0
  84. package/.playground/nuxt.config.ts +52 -0
  85. package/.playground/public/banner-preview.png +0 -0
  86. package/.playground/public/favicon.ico +0 -0
  87. package/.playground/public/front-matter-showcase/authors.png +0 -0
  88. package/.playground/public/front-matter-showcase/badges.png +0 -0
  89. package/.playground/public/front-matter-showcase/nav-badges.png +0 -0
  90. package/.playground/public/hero.png +0 -0
  91. package/.playground/public/logo-dark.svg +12 -0
  92. package/.playground/public/logo.svg +12 -0
  93. package/.playground/public/og-nuxt-seo.png +0 -0
  94. package/.playground/public/og-nuxt.png +0 -0
  95. package/.playground/public/og-shadcn-docs-dark.png +0 -0
  96. package/.playground/public/og-shadcn-docs.png +0 -0
  97. package/.playground/public/sidebar-default.png +0 -0
  98. package/.playground/public/sidebar-group.png +0 -0
  99. package/.playground/public/sidebar-tree.png +0 -0
  100. package/.playground/uno.config.ts +16 -0
  101. package/README.md +93 -0
  102. package/app.vue +59 -0
  103. package/assets/css/a11y.css +48 -0
  104. package/assets/css/mdc-editor.css +91 -0
  105. package/components/A11yModeToggle.vue +23 -0
  106. package/components/DarkModeToggle.vue +26 -0
  107. package/components/LinkIcon.vue +32 -0
  108. package/components/OgImage/ShadcnDocs.vue +55 -0
  109. package/components/ThemeCustomizer.vue +156 -0
  110. package/components/ThemePopover.vue +27 -0
  111. package/components/content/Accordion.vue +18 -0
  112. package/components/content/AccordionItem.vue +32 -0
  113. package/components/content/Alert.vue +100 -0
  114. package/components/content/Badge.vue +52 -0
  115. package/components/content/ButtonLink.vue +38 -0
  116. package/components/content/Callout.vue +17 -0
  117. package/components/content/Card.vue +173 -0
  118. package/components/content/CardGroup.vue +38 -0
  119. package/components/content/CodeCopy.vue +52 -0
  120. package/components/content/CodeGroup._vue +27 -0
  121. package/components/content/CodeSnippet._vue +78 -0
  122. package/components/content/Collapsible.vue +80 -0
  123. package/components/content/Field.vue +53 -0
  124. package/components/content/FieldGroup.vue +5 -0
  125. package/components/content/FileTree.vue +110 -0
  126. package/components/content/FileTreeItem.vue +64 -0
  127. package/components/content/FileTreeRoot.vue +27 -0
  128. package/components/content/Hero.vue +154 -0
  129. package/components/content/HeroAlt.vue +116 -0
  130. package/components/content/Icon.vue +69 -0
  131. package/components/content/Kbd.vue +20 -0
  132. package/components/content/PmInstall.vue +35 -0
  133. package/components/content/PmRun.vue +31 -0
  134. package/components/content/PmX.vue +31 -0
  135. package/components/content/ProseA.vue +21 -0
  136. package/components/content/ProseBlockquote.vue +5 -0
  137. package/components/content/ProseCode.vue +121 -0
  138. package/components/content/ProseCodeInline.vue +24 -0
  139. package/components/content/ProseEm.vue +5 -0
  140. package/components/content/ProseH1.vue +27 -0
  141. package/components/content/ProseH2.vue +22 -0
  142. package/components/content/ProseH3.vue +21 -0
  143. package/components/content/ProseH4.vue +21 -0
  144. package/components/content/ProseH5.vue +21 -0
  145. package/components/content/ProseH6.vue +21 -0
  146. package/components/content/ProseHr.vue +3 -0
  147. package/components/content/ProseImg.vue +42 -0
  148. package/components/content/ProseLi.vue +5 -0
  149. package/components/content/ProseOl.vue +5 -0
  150. package/components/content/ProseP.vue +5 -0
  151. package/components/content/ProsePre.vue +56 -0
  152. package/components/content/ProseSection.vue +27 -0
  153. package/components/content/ProseStrong.vue +5 -0
  154. package/components/content/ProseTable.vue +7 -0
  155. package/components/content/ProseTbody.vue +5 -0
  156. package/components/content/ProseTd.vue +5 -0
  157. package/components/content/ProseTh.vue +5 -0
  158. package/components/content/ProseThead.vue +5 -0
  159. package/components/content/ProseTr.vue +5 -0
  160. package/components/content/ProseUl.vue +5 -0
  161. package/components/content/ReadMore.vue +41 -0
  162. package/components/content/Shortcut.vue +20 -0
  163. package/components/content/Stack.vue +17 -0
  164. package/components/content/Steps.vue +23 -0
  165. package/components/content/Tabs.vue +52 -0
  166. package/components/content/TabsInner.vue +263 -0
  167. package/components/content/TeamCard.vue +52 -0
  168. package/components/content/TeamCardGroup.vue +5 -0
  169. package/components/content/global/AlertEditor.vue +58 -0
  170. package/components/content/global/BadgeEditor.vue +56 -0
  171. package/components/content/global/BrEditor.vue +3 -0
  172. package/components/content/global/CardEditor.vue +142 -0
  173. package/components/content/global/CardGroupEditor.vue +50 -0
  174. package/components/content/global/CodeGroup.vue +13 -0
  175. package/components/content/global/CodeGroupEditor.vue +50 -0
  176. package/components/content/global/DivEditor.vue +22 -0
  177. package/components/content/global/FieldEditor.vue +38 -0
  178. package/components/content/global/FieldGroupEditor.vue +24 -0
  179. package/components/content/global/HeroEditor.vue +67 -0
  180. package/components/content/global/ProseSectionEditor.vue +180 -0
  181. package/components/content/global/ReadMoreEditor.vue +70 -0
  182. package/components/content/global/SectionEditor.vue +22 -0
  183. package/components/content/global/StackEditor.vue +35 -0
  184. package/components/content/global/StepsEditor.vue +55 -0
  185. package/components/content/global/Tabs._vue +97 -0
  186. package/components/content/global/TabsEditor.vue +38 -0
  187. package/components/layout/Aside.vue +83 -0
  188. package/components/layout/AsideTree.vue +25 -0
  189. package/components/layout/AsideTreeItem.vue +86 -0
  190. package/components/layout/AsideTreeItemButton.vue +32 -0
  191. package/components/layout/Banner.vue +77 -0
  192. package/components/layout/Breadcrumb.vue +34 -0
  193. package/components/layout/DocsFooter.vue +6 -0
  194. package/components/layout/EditLink.vue +23 -0
  195. package/components/layout/Footer.vue +80 -0
  196. package/components/layout/FooterItem.vue +50 -0
  197. package/components/layout/FooterSubmenuItem.vue +39 -0
  198. package/components/layout/Header/Logo.vue +30 -0
  199. package/components/layout/Header/MenuItem.vue +83 -0
  200. package/components/layout/Header/Nav.vue +112 -0
  201. package/components/layout/Header/NavMobile.vue +14 -0
  202. package/components/layout/Header/NavMobileItem.vue +79 -0
  203. package/components/layout/Header/SubmenuItem.vue +39 -0
  204. package/components/layout/Header.vue +160 -0
  205. package/components/layout/LangSwitcher.vue +90 -0
  206. package/components/layout/MobileNav.vue +44 -0
  207. package/components/layout/PrevNext.vue +24 -0
  208. package/components/layout/PrevNextButton.vue +50 -0
  209. package/components/layout/SearchButton.vue +46 -0
  210. package/components/layout/SearchDialog.vue +217 -0
  211. package/components/layout/Title.vue +98 -0
  212. package/components/layout/Toc.vue +99 -0
  213. package/components/layout/TocTree.vue +42 -0
  214. package/components/ui/accordion/Accordion.vue +19 -0
  215. package/components/ui/accordion/AccordionContent.vue +24 -0
  216. package/components/ui/accordion/AccordionItem.vue +24 -0
  217. package/components/ui/accordion/AccordionTrigger.vue +39 -0
  218. package/components/ui/accordion/index.ts +4 -0
  219. package/components/ui/alert/Alert.vue +19 -0
  220. package/components/ui/alert/AlertDescription.vue +14 -0
  221. package/components/ui/alert/AlertTitle.vue +14 -0
  222. package/components/ui/alert/index.ts +23 -0
  223. package/components/ui/avatar/Avatar.vue +25 -0
  224. package/components/ui/avatar/AvatarFallback.vue +11 -0
  225. package/components/ui/avatar/AvatarImage.vue +12 -0
  226. package/components/ui/avatar/index.ts +24 -0
  227. package/components/ui/badge/Badge.vue +17 -0
  228. package/components/ui/badge/index.ts +71 -0
  229. package/components/ui/breadcrumb/Breadcrumb.vue +16 -0
  230. package/components/ui/breadcrumb/BreadcrumbItem.vue +16 -0
  231. package/components/ui/breadcrumb/BreadcrumbLink.vue +23 -0
  232. package/components/ui/breadcrumb/BreadcrumbList.vue +16 -0
  233. package/components/ui/breadcrumb/BreadcrumbPage.vue +19 -0
  234. package/components/ui/breadcrumb/BreadcrumbSeparator.vue +23 -0
  235. package/components/ui/breadcrumb/index.ts +6 -0
  236. package/components/ui/button/Button.vue +29 -0
  237. package/components/ui/button/index.ts +35 -0
  238. package/components/ui/card/Card.vue +21 -0
  239. package/components/ui/card/CardContent.vue +14 -0
  240. package/components/ui/card/CardDescription.vue +14 -0
  241. package/components/ui/card/CardFooter.vue +14 -0
  242. package/components/ui/card/CardHeader.vue +14 -0
  243. package/components/ui/card/CardTitle.vue +18 -0
  244. package/components/ui/card/index.ts +6 -0
  245. package/components/ui/collapsible/Collapsible.vue +18 -0
  246. package/components/ui/collapsible/CollapsibleContent.vue +14 -0
  247. package/components/ui/collapsible/CollapsibleTrigger.vue +11 -0
  248. package/components/ui/collapsible/index.ts +3 -0
  249. package/components/ui/command/Command.vue +89 -0
  250. package/components/ui/command/CommandEmpty.vue +30 -0
  251. package/components/ui/command/CommandGroup.vue +50 -0
  252. package/components/ui/command/CommandInput.vue +44 -0
  253. package/components/ui/command/CommandInputOnly.vue +50 -0
  254. package/components/ui/command/CommandItem.vue +79 -0
  255. package/components/ui/command/CommandList.vue +28 -0
  256. package/components/ui/command/CommandSeparator.vue +24 -0
  257. package/components/ui/command/index.ts +24 -0
  258. package/components/ui/dialog/Dialog.vue +14 -0
  259. package/components/ui/dialog/DialogClose.vue +11 -0
  260. package/components/ui/dialog/DialogContent.vue +52 -0
  261. package/components/ui/dialog/DialogDescription.vue +24 -0
  262. package/components/ui/dialog/DialogFooter.vue +19 -0
  263. package/components/ui/dialog/DialogHeader.vue +16 -0
  264. package/components/ui/dialog/DialogScrollContent.vue +61 -0
  265. package/components/ui/dialog/DialogTitle.vue +29 -0
  266. package/components/ui/dialog/DialogTrigger.vue +11 -0
  267. package/components/ui/dialog/index.ts +9 -0
  268. package/components/ui/input/Input.vue +27 -0
  269. package/components/ui/input/index.ts +1 -0
  270. package/components/ui/label/Label.vue +27 -0
  271. package/components/ui/label/index.ts +1 -0
  272. package/components/ui/navigation-menu/NavigationMenu.vue +33 -0
  273. package/components/ui/navigation-menu/NavigationMenuContent.vue +34 -0
  274. package/components/ui/navigation-menu/NavigationMenuIndicator.vue +24 -0
  275. package/components/ui/navigation-menu/NavigationMenuItem.vue +11 -0
  276. package/components/ui/navigation-menu/NavigationMenuLink.vue +19 -0
  277. package/components/ui/navigation-menu/NavigationMenuList.vue +33 -0
  278. package/components/ui/navigation-menu/NavigationMenuTrigger.vue +34 -0
  279. package/components/ui/navigation-menu/NavigationMenuViewport.vue +33 -0
  280. package/components/ui/navigation-menu/index.ts +14 -0
  281. package/components/ui/popover/Popover.vue +15 -0
  282. package/components/ui/popover/PopoverContent.vue +49 -0
  283. package/components/ui/popover/PopoverTrigger.vue +11 -0
  284. package/components/ui/popover/index.ts +4 -0
  285. package/components/ui/scroll-area/ScrollArea.vue +32 -0
  286. package/components/ui/scroll-area/ScrollBar.vue +41 -0
  287. package/components/ui/scroll-area/index.ts +2 -0
  288. package/components/ui/separator/Separator.vue +20 -0
  289. package/components/ui/separator/index.ts +1 -0
  290. package/components/ui/sheet/Sheet.vue +14 -0
  291. package/components/ui/sheet/SheetClose.vue +11 -0
  292. package/components/ui/sheet/SheetContent.vue +58 -0
  293. package/components/ui/sheet/SheetDescription.vue +22 -0
  294. package/components/ui/sheet/SheetFooter.vue +19 -0
  295. package/components/ui/sheet/SheetHeader.vue +16 -0
  296. package/components/ui/sheet/SheetTitle.vue +22 -0
  297. package/components/ui/sheet/SheetTrigger.vue +11 -0
  298. package/components/ui/sheet/index.ts +31 -0
  299. package/components/ui/slider/Slider.vue +36 -0
  300. package/components/ui/slider/index.ts +1 -0
  301. package/components/ui/tabs/Tabs.vue +15 -0
  302. package/components/ui/tabs/TabsContent.vue +22 -0
  303. package/components/ui/tabs/TabsList.vue +25 -0
  304. package/components/ui/tabs/TabsTrigger.vue +27 -0
  305. package/components/ui/tabs/index.ts +4 -0
  306. package/components/ui/textarea/Textarea.vue +27 -0
  307. package/components/ui/textarea/index.ts +1 -0
  308. package/components/ui/toast/Toast.vue +28 -0
  309. package/components/ui/toast/ToastAction.vue +22 -0
  310. package/components/ui/toast/ToastClose.vue +27 -0
  311. package/components/ui/toast/ToastDescription.vue +22 -0
  312. package/components/ui/toast/ToastProvider.vue +11 -0
  313. package/components/ui/toast/ToastTitle.vue +22 -0
  314. package/components/ui/toast/ToastViewport.vue +20 -0
  315. package/components/ui/toast/Toaster.vue +34 -0
  316. package/components/ui/toast/index.ts +38 -0
  317. package/components/ui/toast/use-toast.ts +165 -0
  318. package/components.json +18 -0
  319. package/composables/useBreadcrumb.ts +47 -0
  320. package/composables/useCollapsedMap.ts +3 -0
  321. package/composables/useConfig.ts +227 -0
  322. package/composables/useEditLink.ts +27 -0
  323. package/composables/useI18nDocs.ts +114 -0
  324. package/composables/useMdcMenu.ts +204 -0
  325. package/composables/usePm.ts +58 -0
  326. package/composables/useScrollspy.ts +51 -0
  327. package/composables/useThemes.ts +46 -0
  328. package/composables/useToast.ts +1 -0
  329. package/content/index.md +45 -0
  330. package/eslint.config.js +3 -0
  331. package/i18n/i18n.config.ts +414 -0
  332. package/index.d.ts +610 -0
  333. package/layouts/blank.vue +5 -0
  334. package/layouts/default.vue +9 -0
  335. package/layouts/editorial.vue +83 -0
  336. package/lib/registry/themes.ts +636 -0
  337. package/lib/uno-preset.ts +143 -0
  338. package/memory-bank/activeContext.md +17 -0
  339. package/memory-bank/productContext.md +21 -0
  340. package/memory-bank/progress.md +16 -0
  341. package/memory-bank/projectbrief.md +20 -0
  342. package/memory-bank/systemPatterns.md +25 -0
  343. package/memory-bank/techContext.md +29 -0
  344. package/modules/inject-css.ts +40 -0
  345. package/nuxt.config.ts +124 -0
  346. package/package.json +71 -0
  347. package/pages/[...slug].vue +109 -0
  348. package/pages/admin/[...slug].vue +145 -0
  349. package/pages/index.vue +24 -0
  350. package/plugins/injectCssHmr.ts +26 -0
  351. package/plugins/wordup.ts +130 -0
  352. package/public/content-doc.json +792 -0
  353. package/public/iconesjs.svg +4 -0
  354. package/scripts/buildContentDoc-cli.ts +8 -0
  355. package/scripts/buildContentDoc.ts +165 -0
  356. package/tailwind.config.js +1 -0
  357. package/tsconfig.json +3 -0
  358. package/uno.config.mjs +58 -0
  359. package/utils/index.ts +12 -0
@@ -0,0 +1,227 @@
1
+ import { createDefu } from 'defu'
2
+
3
+ const customDefu = createDefu((obj, key, value) => {
4
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5
+ if (Array.isArray(value) && value.every((x: any) => typeof x === 'string')) {
6
+ obj[key] = value
7
+ return true
8
+ }
9
+ })
10
+
11
+ const defaultConfig: DefaultConfig = {
12
+ site: {
13
+ name: 'shadcn-docs',
14
+ description: 'Beautifully designed Nuxt Content template built with shadcn-vue. Customizable. Compatible. Open Source.',
15
+ ogImage: '/hero.png',
16
+ ogImageComponent: 'ShadcnDocs',
17
+ ogImageColor: 'light',
18
+ umami: {
19
+ enable: false,
20
+ src: 'https://cloud.umami.is/script.js',
21
+ dataWebsiteId: '',
22
+ },
23
+ },
24
+ theme: {
25
+ customizable: true,
26
+ color: 'zinc',
27
+ radius: 0.5,
28
+ },
29
+ banner: {
30
+ enable: false,
31
+ showClose: true,
32
+ content: 'Welcome to **shadcn-docs-nuxt**',
33
+ to: '',
34
+ target: '_blank',
35
+ border: true,
36
+ height: '3rem',
37
+ },
38
+ header: {
39
+ showLoadingIndicator: true,
40
+ title: 'shadcn-docs',
41
+ showTitle: true,
42
+ logo: {
43
+ light: '/logo.svg',
44
+ dark: '/logo-dark.svg',
45
+ },
46
+ showTitleInMobile: false,
47
+ border: false,
48
+ position: null,
49
+ behavior: 'fixed',
50
+ class: '',
51
+ darkModeToggle: true,
52
+ languageSwitcher: {
53
+ enable: false,
54
+ triggerType: 'icon',
55
+ dropdownType: 'select',
56
+ },
57
+ nav: [],
58
+ links: [],
59
+ height: '3.5rem',
60
+ },
61
+ aside: {
62
+ useLevel: true,
63
+ collapse: false,
64
+ collapseLevel: 1,
65
+ folderStyle: 'default',
66
+ },
67
+ sidebarRight: {
68
+ enable: true,
69
+ title: 'On This Page',
70
+ components: [],
71
+ },
72
+ main: {
73
+ breadCrumb: {
74
+ showIcon: true,
75
+ iconSize: 16,
76
+ home: {
77
+ title: '',
78
+ href: '/',
79
+ icon: 'i-lucide-house',
80
+ iconSize: 18,
81
+ },
82
+ },
83
+ showTitle: true,
84
+ codeCopyToast: true,
85
+ codeCopyToastText: 'Copied to clipboard!',
86
+ fieldRequiredText: 'required',
87
+ padded: true,
88
+ editLink: {
89
+ enable: false,
90
+ pattern: '',
91
+ text: 'Edit this page',
92
+ icon: 'lucide:square-pen',
93
+ placement: ['docsFooter'],
94
+ },
95
+ pm: ['npm', 'pnpm', 'bun', 'yarn'],
96
+ codeIcon: {
97
+ 'package.json': 'vscode-icons:file-type-node',
98
+ 'tsconfig.json': 'vscode-icons:file-type-tsconfig',
99
+ '.npmrc': 'vscode-icons:file-type-npm',
100
+ '.editorconfig': 'vscode-icons:file-type-editorconfig',
101
+ '.eslintrc': 'vscode-icons:file-type-eslint',
102
+ '.eslintrc.cjs': 'vscode-icons:file-type-eslint',
103
+ '.eslintignore': 'vscode-icons:file-type-eslint',
104
+ 'eslint.config.js': 'vscode-icons:file-type-eslint',
105
+ 'eslint.config.mjs': 'vscode-icons:file-type-eslint',
106
+ 'eslint.config.cjs': 'vscode-icons:file-type-eslint',
107
+ '.gitignore': 'vscode-icons:file-type-git',
108
+ 'yarn.lock': 'vscode-icons:file-type-yarn',
109
+ '.env': 'vscode-icons:file-type-dotenv',
110
+ '.env.example': 'vscode-icons:file-type-dotenv',
111
+ '.vscode/settings.json': 'vscode-icons:file-type-vscode',
112
+ 'nuxt': 'vscode-icons:file-type-nuxt',
113
+ '.nuxtrc': 'vscode-icons:file-type-nuxt',
114
+ '.nuxtignore': 'vscode-icons:file-type-nuxt',
115
+ 'nuxt.config.js': 'vscode-icons:file-type-nuxt',
116
+ 'nuxt.config.ts': 'vscode-icons:file-type-nuxt',
117
+ 'nuxt.schema.ts': 'vscode-icons:file-type-nuxt',
118
+ 'tailwind.config.js': 'vscode-icons:file-type-tailwind',
119
+ 'tailwind.config.ts': 'vscode-icons:file-type-tailwind',
120
+ 'vue': 'vscode-icons:file-type-vue',
121
+ 'ts': 'vscode-icons:file-type-typescript',
122
+ 'tsx': 'vscode-icons:file-type-typescript',
123
+ 'mjs': 'vscode-icons:file-type-js',
124
+ 'cjs': 'vscode-icons:file-type-js',
125
+ 'js': 'vscode-icons:file-type-js',
126
+ 'jsx': 'vscode-icons:file-type-js',
127
+ 'md': 'vscode-icons:file-type-markdown',
128
+ 'mdc': 'vscode-icons:file-type-markdown',
129
+ 'py': 'vscode-icons:file-type-python',
130
+ 'npm': 'vscode-icons:file-type-npm',
131
+ 'pnpm': 'vscode-icons:file-type-pnpm',
132
+ 'npx': 'vscode-icons:file-type-npm',
133
+ 'yarn': 'vscode-icons:file-type-yarn',
134
+ 'bun': 'vscode-icons:file-type-bun',
135
+ 'deno': 'vscode-icons:file-type-deno',
136
+ 'yml': 'vscode-icons:file-type-yaml',
137
+ 'json': 'vscode-icons:file-type-json',
138
+ 'terminal': 'lucide:terminal',
139
+ },
140
+ },
141
+ footer: {
142
+ credits: '',
143
+ links: [],
144
+ class: '',
145
+ },
146
+ toc: {
147
+ enable: true,
148
+ enableInMobile: false,
149
+ title: 'On This Page',
150
+ links: [],
151
+ carbonAds: {
152
+ enable: false,
153
+ disableInDev: false,
154
+ code: '',
155
+ placement: '',
156
+ format: 'cover',
157
+ },
158
+ },
159
+ search: {
160
+ enable: true,
161
+ inAside: false,
162
+ style: 'input',
163
+ placeholder: 'Search...',
164
+ displayShortcut: true,
165
+ placeholderDetailed: 'Search documentation...',
166
+ },
167
+ }
168
+
169
+ export function useConfig() {
170
+ // return computed(() => customDefu(useAppConfig()?.shadcnDocs, defaultConfig))
171
+ const appConfig = computed(() => useAppConfig()?.shadcnDocs || {})
172
+ const { navKeyFromPath } = useContentHelpers()
173
+ const { navigation, page } = useContent()
174
+ const route = useRoute()
175
+
176
+ return computed(
177
+ () => {
178
+ const processedConfig = customDefu(appConfig.value, defaultConfig)
179
+ const header = processedConfig.header
180
+ const banner = processedConfig.banner
181
+ const main = processedConfig.main
182
+ const aside = processedConfig.aside
183
+ const sidebarRight = processedConfig.sidebarRight
184
+ const toc = processedConfig.toc
185
+ const footer = processedConfig.footer
186
+
187
+ return {
188
+ ...processedConfig,
189
+ header: {
190
+ ...header,
191
+ ...navKeyFromPath(route.path, 'header', navigation.value || []),
192
+ ...page.value?.header,
193
+ } as (typeof header & DefaultConfig['header']),
194
+ banner: {
195
+ ...banner,
196
+ ...navKeyFromPath(route.path, 'banner', navigation.value || []),
197
+ ...page.value?.banner,
198
+ } as (typeof banner & DefaultConfig['banner']),
199
+ main: {
200
+ ...main,
201
+ ...navKeyFromPath(route.path, 'main', navigation.value || []),
202
+ ...page.value?.main,
203
+ } as (typeof main & DefaultConfig['main']),
204
+ aside: {
205
+ ...aside,
206
+ ...navKeyFromPath(route.path, 'aside', navigation.value || []),
207
+ ...page.value?.aside,
208
+ } as (typeof aside & DefaultConfig['aside']),
209
+ sidebarRight: {
210
+ ...sidebarRight,
211
+ ...navKeyFromPath(route.path, 'sidebarRight', navigation.value || []),
212
+ ...page.value?.sidebarRight,
213
+ } as (typeof toc & DefaultConfig['sidebarRight']),
214
+ toc: {
215
+ ...toc,
216
+ ...navKeyFromPath(route.path, 'toc', navigation.value || []),
217
+ ...page.value?.toc,
218
+ } as (typeof toc & DefaultConfig['toc']),
219
+ footer: {
220
+ ...footer,
221
+ ...navKeyFromPath(route.path, 'footer', navigation.value || []),
222
+ ...page.value?.footer,
223
+ } as (typeof footer & DefaultConfig['footer']),
224
+ }
225
+ },
226
+ )
227
+ }
@@ -0,0 +1,27 @@
1
+ export function useEditLink() {
2
+ const { page } = useContent()
3
+ const { enable, pattern, text, icon, placement } = useConfig().value.main.editLink
4
+
5
+ const url = computed(
6
+ () => pattern.replace(/:path/g, page.value._file ?? ''),
7
+ )
8
+
9
+ const enabled = computed(
10
+ () => enable && page.value.editLink !== false && page.value._file && url.value !== '',
11
+ )
12
+
13
+ const enabledToc = computed(
14
+ () => enabled.value && placement.includes('toc'),
15
+ )
16
+ const enabledDocsFooter = computed(
17
+ () => enabled.value && placement.includes('docsFooter'),
18
+ )
19
+
20
+ return {
21
+ url,
22
+ text,
23
+ icon,
24
+ enabledToc,
25
+ enabledDocsFooter,
26
+ }
27
+ }
@@ -0,0 +1,114 @@
1
+ import type { SearchResult } from 'minisearch'
2
+
3
+ /**
4
+ * A wrapper around useI18n that provides safe internationalization utilities
5
+ * and handles navigation filtering based on the current locale.
6
+ * Falls back gracefully when i18n is not configured.
7
+ */
8
+ export function useI18nDocs() {
9
+ // Check if i18n is enabled by verifying config exists and there are multiple locales
10
+ const i18nEnabled = !!useI18n() && useI18n().availableLocales?.length > 1
11
+
12
+ // Get content navigation and i18n utilities
13
+ const { navigation, next, prev } = useContent()
14
+ const { locale, locales, defaultLocale, availableLocales } = useI18n()
15
+
16
+ // Get all locales except the default one
17
+ const otherLocales = availableLocales.filter(l => l !== defaultLocale)
18
+
19
+ /**
20
+ * Filters navigation items based on the current locale
21
+ * - For default locale: shows only default paths (no locale prefix)
22
+ * - For other locales: shows only paths with matching locale prefix
23
+ */
24
+ const localizedNavigation = computed(() => {
25
+ if (!i18nEnabled)
26
+ return navigation.value
27
+ const filteredNav = navigation.value.filter((nav) => {
28
+ if (locale.value === defaultLocale) {
29
+ return !otherLocales.some(l => nav._path.startsWith(`/${l}`))
30
+ }
31
+ return nav._path.startsWith(`/${locale.value}`)
32
+ })
33
+ console.log(locale.value, 'aa', !!defaultLocale, 'pp', filteredNav)
34
+ return locale.value === defaultLocale ? filteredNav : filteredNav[0]?.children
35
+ })
36
+
37
+ /**
38
+ * Filters previous navigation item based on the current locale
39
+ * - For default locale: shows only prev if page exists with default paths (no locale prefix)
40
+ * - For other locales: shows only prev if page exists with matching locale prefix
41
+ */
42
+ const localizedPrev = computed(() => {
43
+ if (!i18nEnabled)
44
+ return prev.value
45
+ if (locale.value === defaultLocale) {
46
+ if (otherLocales.some(l => prev.value?._path.startsWith(`/${l}/`)))
47
+ return null
48
+ }
49
+ else {
50
+ if (!prev.value?._path.startsWith(`/${locale.value}`)) {
51
+ return null
52
+ }
53
+ }
54
+ return prev.value
55
+ })
56
+
57
+ /**
58
+ * Filters next navigation item based on the current locale
59
+ * - For default locale: shows only next if page exists with default paths (no locale prefix)
60
+ * - For other locales: shows only next if page exists with matching locale prefix
61
+ */
62
+ const localizedNext = computed(() => {
63
+ if (!i18nEnabled)
64
+ return next.value
65
+ if (locale.value === defaultLocale) {
66
+ if (otherLocales.some(l => next.value?._path.startsWith(`/${l}/`)))
67
+ return null
68
+ }
69
+ else {
70
+ if (!next.value?._path.startsWith(`/${locale.value}`)) {
71
+ return null
72
+ }
73
+ }
74
+ return next.value
75
+ })
76
+
77
+ /**
78
+ * Safe wrapper for useLocalePath
79
+ * Returns original path if i18n is not enabled
80
+ */
81
+ const localePath = i18nEnabled ? useLocalePath() : (path: string) => path
82
+
83
+ /**
84
+ * Filters search results based on the current locale
85
+ * - For default locale: shows only default results (no locale prefix)
86
+ * - For other locales: shows only results with matching locale prefix
87
+ */
88
+ const localizeSearchResult = i18nEnabled
89
+ ? (result: SearchResult[]) => result.filter((r) => {
90
+ if (locale.value === defaultLocale)
91
+ return !otherLocales.some(l => r.id.startsWith(`/${l}/`))
92
+
93
+ return r.id.startsWith(`/${locale.value}`)
94
+ })
95
+ : (result: SearchResult[]) => result
96
+
97
+ // Get the locale switcher utility
98
+ const switchLocalePath = useSwitchLocalePath()
99
+
100
+ return {
101
+ i18nEnabled, // Whether i18n is enabled and configured
102
+ locale, // Current locale
103
+ locales, // All locales
104
+ defaultLocale, // Default locale from config
105
+ availableLocales, // All available locales
106
+ otherLocales, // All locales except default
107
+ navigation: localizedNavigation, // Navigation filtered by current locale
108
+ prev: localizedPrev, // Previous page navigation filtered by current locale
109
+ next: localizedNext, // Next page navigation filtered by current locale
110
+ localePath, // Safe path localization function
111
+ localizeSearchResult, // Search results filter by locale
112
+ switchLocalePath, // Function to switch between locales
113
+ }
114
+ }
@@ -0,0 +1,204 @@
1
+ import type { MDCElement, MDCRoot, MDCNode } from '@nuxtjs/mdc'
2
+ import type { ParsedContent } from '@nuxt/content'
3
+
4
+ export async function useMdcMenu(menu: Ref<ParsedContent | null>, {
5
+ menuComponentName = 'menu-item',
6
+ submenuComponentName = 'submenu-item',
7
+ includeElementsBeforeFirstTag = true,
8
+ }: {
9
+ menuComponentName?: string
10
+ submenuComponentName?: string
11
+ includeElementsBeforeFirstTag?: boolean
12
+ } = {}) {
13
+ const tree = computed<MDCRoot | undefined>(() => {
14
+ if (!menu?.value?.body?.children) return
15
+
16
+ // Clone the content to avoid mutating the original data
17
+ const content = JSON.parse(JSON.stringify(menu.value!.body!.children))
18
+
19
+ const grouped = groupElementsAfterElement(content,
20
+ ['h1', 'menu-item'],
21
+ )
22
+
23
+ const _tree = [] as MDCNode[]
24
+ for (const item of grouped) {
25
+ if (item.tag === 'h1') {
26
+ const convertedItem = convertH1ToMenuItem({
27
+ item,
28
+ menuComponentName,
29
+ submenuComponentName,
30
+ })
31
+ if (convertedItem) _tree.push(convertedItem)
32
+ }
33
+ else if (item.tag === menuComponentName) {
34
+ _tree.push(item)
35
+ }
36
+ else if (item.tag === 'div') {
37
+ _tree.push(item)
38
+ }
39
+ else if (includeElementsBeforeFirstTag) {
40
+ _tree.push(item)
41
+ }
42
+ }
43
+
44
+ return {
45
+ type: 'root',
46
+ children: _tree,
47
+ }
48
+ })
49
+
50
+ return tree
51
+ }
52
+
53
+ function convertH1ToMenuItem({
54
+ item,
55
+ menuComponentName,
56
+ submenuComponentName,
57
+ }: {
58
+ item: MDCElement
59
+ menuComponentName: string
60
+ submenuComponentName: string
61
+ }) {
62
+ let treeItem: MDCElement | undefined = undefined
63
+
64
+ if (item.tag === 'h1') {
65
+ treeItem = {
66
+ type: 'element',
67
+ tag: menuComponentName,
68
+ props: {},
69
+ children: JSON.parse(JSON.stringify(toRaw(item.children))), // break reactivity
70
+ }
71
+ const aItem = item.children[0] as MDCElement
72
+ treeItem.props!.className = aItem.props?.className
73
+ treeItem.props!.dropdownClass = aItem.props?.['dropdown-class']
74
+
75
+ if ((item.children?.[0] as MDCElement).tag === 'a') {
76
+ let href = aItem.props?.href
77
+
78
+ treeItem.children = JSON.parse(
79
+ JSON.stringify(toRaw(aItem.children) || []),
80
+ )
81
+
82
+ const { navDirFromPath, navPageFromPath } = useContentHelpers()
83
+ const { navigation } = useContent()
84
+
85
+ // Link to page or list sub-pages
86
+ if (href.startsWith('/') && href.endsWith('/') && navigation.value) {
87
+ href = href.replace(/\/$/, '')
88
+ const dir = navDirFromPath(href, navigation.value)
89
+ if (dir) {
90
+ const parentProps = (item.children[0] as MDCElement).props!
91
+ const children = dir
92
+ .map(child => ({
93
+ type: 'element',
94
+ tag: submenuComponentName,
95
+ props: {
96
+ to: child._path,
97
+ title: child.title,
98
+ icon: [false, 'false'].includes(parentProps.icon)
99
+ ? undefined
100
+ : child.icon,
101
+ description: [false, 'false'].includes(parentProps.description)
102
+ ? undefined
103
+ : child.description,
104
+ },
105
+ children: [],
106
+ }))
107
+ .slice(0, parentProps.limit || Infinity) as MDCElement[]
108
+
109
+ treeItem.children.push({
110
+ type: 'element',
111
+ tag: 'template',
112
+ props: {
113
+ 'v-slot:content': '',
114
+ },
115
+ children,
116
+ })
117
+ }
118
+ }
119
+ else {
120
+ treeItem.props!.to = href
121
+
122
+ if (/https?:\/\//.test(href)) {
123
+ treeItem.props!.target = '_blank'
124
+ treeItem.props!.rel = 'noopener noreferrer'
125
+ treeItem.props!.showLinkIcon = true
126
+ }
127
+ }
128
+
129
+ // If the link has an icon, use it.
130
+ if (aItem.props?.[':icon'] !== 'false' && aItem.props?.icon !== 'false')
131
+ treeItem.props!.icon = aItem.props?.icon
132
+
133
+ // Auto-fill empty link with page data. [](/page)
134
+ if (!aItem.children?.length && navigation.value) {
135
+ const page = navPageFromPath(href, navigation.value)
136
+ treeItem.props!.title = page?.title || 'Not found'
137
+
138
+ // If the link has an icon, use it.
139
+ if (aItem.props?.[':icon'] !== 'false' && aItem.props?.icon !== 'false')
140
+ treeItem.props!.icon = page?.icon
141
+ }
142
+ }
143
+ }
144
+ else if (item.tag === 'div') {
145
+ treeItem = item
146
+ }
147
+ return treeItem
148
+ }
149
+
150
+ function groupElementsAfterElement(
151
+ elements: MDCElement[],
152
+ tags?: string | string[],
153
+ ) {
154
+ const _tags = typeof tags === 'string' ? [tags] : tags
155
+ const result = []
156
+ let currentTag = null
157
+ let currentGroup: MDCElement | null = null
158
+ let foundFirstTag = false
159
+
160
+ for (const element of elements) {
161
+ if (_tags?.includes(element.tag)) {
162
+ foundFirstTag = true
163
+
164
+ // Finalize the previous group (if any)
165
+ if (currentGroup && currentTag) {
166
+ currentTag.children.push(currentGroup)
167
+ currentGroup = null
168
+ }
169
+
170
+ // Track the new tag
171
+ currentTag = element
172
+ result.push(currentTag)
173
+ }
174
+ else if (element.tag === 'div') {
175
+ result.push(element)
176
+ }
177
+ else {
178
+ if (!foundFirstTag) {
179
+ result.push(element)
180
+ continue
181
+ }
182
+
183
+ // Create a group container if none exists
184
+ if (!currentGroup) {
185
+ currentGroup = {
186
+ type: 'element',
187
+ tag: 'template',
188
+ props: {
189
+ 'v-slot:content': '',
190
+ },
191
+ children: [],
192
+ }
193
+ }
194
+ currentGroup.children.push(element)
195
+ }
196
+ }
197
+
198
+ // Add the last group to its tag (if any)
199
+ if (currentGroup && currentTag) {
200
+ currentTag.children.push(currentGroup)
201
+ }
202
+
203
+ return result
204
+ }
@@ -0,0 +1,58 @@
1
+ const packageManagersCode: {
2
+ name: 'npm' | 'pnpm' | 'bun' | 'yarn'
3
+ command: string
4
+ install: string
5
+ installEmpty: string
6
+ run: string
7
+ x: string
8
+ saveDev: string
9
+ }[] = [
10
+ {
11
+ name: 'npm',
12
+ command: 'npm ',
13
+ install: 'i ',
14
+ installEmpty: 'install',
15
+ run: 'run ',
16
+ x: 'npx ',
17
+ saveDev: '-D ',
18
+ },
19
+ {
20
+ name: 'pnpm',
21
+ command: 'pnpm ',
22
+ install: 'i ',
23
+ installEmpty: 'install',
24
+ run: 'run ',
25
+ x: 'pnpm dlx ',
26
+ saveDev: '-D ',
27
+ },
28
+ {
29
+ name: 'bun',
30
+ command: 'bun ',
31
+ install: 'add ',
32
+ installEmpty: 'install',
33
+ run: 'run ',
34
+ x: 'bun x ',
35
+ saveDev: '-d ',
36
+ },
37
+ {
38
+ name: 'yarn',
39
+ command: 'yarn ',
40
+ install: 'add ',
41
+ installEmpty: 'install',
42
+ run: 'run ',
43
+ x: 'yarn dlx ',
44
+ saveDev: '-D ',
45
+ },
46
+ ]
47
+
48
+ export function usePm() {
49
+ const { pm } = useConfig().value.main
50
+
51
+ const packageManagers = computed(
52
+ () => packageManagersCode.filter(x => pm.includes(x.name)),
53
+ )
54
+
55
+ return {
56
+ packageManagers,
57
+ }
58
+ }
@@ -0,0 +1,51 @@
1
+ // Credit: nuxt-themes/docus
2
+
3
+ /**
4
+ * Scrollspy allows you to watch visible headings in a specific page.
5
+ * Useful for table of contents live style updates.
6
+ */
7
+ export function useScrollspy() {
8
+ const observer = ref() as Ref<IntersectionObserver>
9
+ const visibleHeadings = ref([]) as Ref<string[]>
10
+ const activeHeadings = ref([]) as Ref<string[]>
11
+
12
+ const observerCallback = (entries: IntersectionObserverEntry[]) =>
13
+ entries.forEach((entry) => {
14
+ const id = entry.target.id
15
+
16
+ if (entry.isIntersecting)
17
+ visibleHeadings.value.push(id)
18
+ else visibleHeadings.value = visibleHeadings.value.filter(t => t !== id)
19
+ })
20
+
21
+ const updateHeadings = (headings: Element[]) => {
22
+ if (observer.value)
23
+ observer.value.disconnect()
24
+ observer.value = new IntersectionObserver(observerCallback)
25
+
26
+ headings.forEach((heading) => {
27
+ observer.value.observe(heading)
28
+ })
29
+ }
30
+
31
+ watch(
32
+ visibleHeadings,
33
+ (val, oldVal) => {
34
+ if (val.length === 0)
35
+ activeHeadings.value = oldVal
36
+ else
37
+ activeHeadings.value = val
38
+ },
39
+ { deep: true },
40
+ )
41
+
42
+ onBeforeUnmount(() => {
43
+ observer.value?.disconnect()
44
+ })
45
+
46
+ return {
47
+ visibleHeadings,
48
+ activeHeadings,
49
+ updateHeadings,
50
+ }
51
+ }