zudoku 0.0.0-fa903e7 → 0.0.0-fc5c03b

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 (212) hide show
  1. package/client.d.ts +7 -0
  2. package/dist/app/entry.client.d.ts +1 -0
  3. package/dist/app/entry.client.js +13 -0
  4. package/dist/app/entry.client.js.map +1 -1
  5. package/dist/app/entry.server.d.ts +1 -0
  6. package/dist/app/entry.server.js +1 -0
  7. package/dist/app/entry.server.js.map +1 -1
  8. package/dist/app/main.js +2 -1
  9. package/dist/app/main.js.map +1 -1
  10. package/dist/app/sentry.d.ts +3 -0
  11. package/dist/app/sentry.js +19 -0
  12. package/dist/app/sentry.js.map +1 -0
  13. package/dist/app/tailwind.d.ts +2 -1
  14. package/dist/app/tailwind.js +64 -52
  15. package/dist/app/tailwind.js.map +1 -1
  16. package/dist/cli/cli.js +0 -2
  17. package/dist/cli/cli.js.map +1 -1
  18. package/dist/cli/common/outdated.js +2 -1
  19. package/dist/cli/common/outdated.js.map +1 -1
  20. package/dist/config/common.d.ts +8 -0
  21. package/dist/config/common.js +2 -0
  22. package/dist/config/common.js.map +1 -0
  23. package/dist/config/config.d.ts +3 -2
  24. package/dist/config/loader.d.ts +20 -0
  25. package/dist/config/loader.js +154 -0
  26. package/dist/config/loader.js.map +1 -0
  27. package/dist/config/validators/InputSidebarSchema.d.ts +14 -13
  28. package/dist/config/validators/InputSidebarSchema.js.map +1 -1
  29. package/dist/config/validators/common.d.ts +4911 -0
  30. package/dist/config/validators/common.js +276 -0
  31. package/dist/config/validators/common.js.map +1 -0
  32. package/dist/config/validators/icon-types.d.ts +1 -0
  33. package/dist/config/validators/icon-types.js +2 -0
  34. package/dist/config/validators/icon-types.js.map +1 -0
  35. package/dist/config/validators/validate.d.ts +760 -524
  36. package/dist/config/validators/validate.js +9 -234
  37. package/dist/config/validators/validate.js.map +1 -1
  38. package/dist/lib/authentication/providers/openid.js +7 -2
  39. package/dist/lib/authentication/providers/openid.js.map +1 -1
  40. package/dist/lib/components/Heading.d.ts +4 -4
  41. package/dist/lib/components/Heading.js +1 -1
  42. package/dist/lib/components/Heading.js.map +1 -1
  43. package/dist/lib/components/Layout.js +3 -2
  44. package/dist/lib/components/Layout.js.map +1 -1
  45. package/dist/lib/components/Markdown.js +1 -1
  46. package/dist/lib/components/Markdown.js.map +1 -1
  47. package/dist/lib/components/MobileTopNavigation.js +1 -1
  48. package/dist/lib/components/MobileTopNavigation.js.map +1 -1
  49. package/dist/lib/components/ReactMarkdown.d.ts +29 -0
  50. package/dist/lib/components/ReactMarkdown.js +182 -0
  51. package/dist/lib/components/ReactMarkdown.js.map +1 -0
  52. package/dist/lib/components/Search.d.ts +3 -1
  53. package/dist/lib/components/Search.js +3 -3
  54. package/dist/lib/components/Search.js.map +1 -1
  55. package/dist/lib/components/SyntaxHighlight.js +0 -4
  56. package/dist/lib/components/SyntaxHighlight.js.map +1 -1
  57. package/dist/lib/components/TopNavigation.d.ts +1 -1
  58. package/dist/lib/components/navigation/Sidebar.d.ts +3 -1
  59. package/dist/lib/components/navigation/Sidebar.js +2 -2
  60. package/dist/lib/components/navigation/Sidebar.js.map +1 -1
  61. package/dist/lib/components/navigation/SidebarCategory.d.ts +2 -2
  62. package/dist/lib/components/navigation/SidebarCategory.js +3 -4
  63. package/dist/lib/components/navigation/SidebarCategory.js.map +1 -1
  64. package/dist/lib/components/navigation/SidebarItem.d.ts +2 -4
  65. package/dist/lib/components/navigation/SidebarItem.js +5 -10
  66. package/dist/lib/components/navigation/SidebarItem.js.map +1 -1
  67. package/dist/lib/components/navigation/SidebarWrapper.js +1 -1
  68. package/dist/lib/components/navigation/SidebarWrapper.js.map +1 -1
  69. package/dist/lib/core/ZudokuContext.d.ts +1 -1
  70. package/dist/lib/oas/graphql/index.js +4 -1
  71. package/dist/lib/oas/graphql/index.js.map +1 -1
  72. package/dist/lib/plugins/api-catalog/Catalog.d.ts +6 -0
  73. package/dist/lib/plugins/api-catalog/Catalog.js +29 -0
  74. package/dist/lib/plugins/api-catalog/Catalog.js.map +1 -0
  75. package/dist/lib/plugins/api-catalog/index.d.ts +23 -0
  76. package/dist/lib/plugins/api-catalog/index.js +15 -0
  77. package/dist/lib/plugins/api-catalog/index.js.map +1 -0
  78. package/dist/lib/plugins/markdown/MdxPage.d.ts +1 -1
  79. package/dist/lib/plugins/markdown/MdxPage.js +2 -2
  80. package/dist/lib/plugins/markdown/MdxPage.js.map +1 -1
  81. package/dist/lib/plugins/markdown/index.d.ts +2 -1
  82. package/dist/lib/plugins/markdown/index.js.map +1 -1
  83. package/dist/lib/plugins/markdown/resolver.js.map +1 -1
  84. package/dist/lib/plugins/openapi/OperationList.js +47 -2
  85. package/dist/lib/plugins/openapi/OperationList.js.map +1 -1
  86. package/dist/lib/plugins/openapi/graphql/gql.d.ts +1 -1
  87. package/dist/lib/plugins/openapi/graphql/gql.js +1 -1
  88. package/dist/lib/plugins/openapi/graphql/gql.js.map +1 -1
  89. package/dist/lib/plugins/openapi/graphql/graphql.d.ts +2 -0
  90. package/dist/lib/plugins/openapi/graphql/graphql.js +1 -0
  91. package/dist/lib/plugins/openapi/graphql/graphql.js.map +1 -1
  92. package/dist/lib/plugins/openapi/playground/PathParams.js +1 -1
  93. package/dist/lib/plugins/openapi/playground/PathParams.js.map +1 -1
  94. package/dist/lib/plugins/redirect/index.d.ts +1 -1
  95. package/dist/lib/ui/Button.d.ts +1 -1
  96. package/dist/lib/ui/Command.d.ts +1 -1
  97. package/dist/lib/util/MdxComponents.d.ts +2 -3
  98. package/dist/lib/util/MdxComponents.js.map +1 -1
  99. package/dist/vite/build.js +15 -3
  100. package/dist/vite/build.js.map +1 -1
  101. package/dist/vite/config.d.ts +6 -4
  102. package/dist/vite/config.js +42 -15
  103. package/dist/vite/config.js.map +1 -1
  104. package/dist/vite/config.test.js +4 -1
  105. package/dist/vite/config.test.js.map +1 -1
  106. package/dist/vite/dev-server.js +12 -3
  107. package/dist/vite/dev-server.js.map +1 -1
  108. package/dist/vite/output.d.ts +1 -1
  109. package/dist/vite/output.js +25 -16
  110. package/dist/vite/output.js.map +1 -1
  111. package/dist/vite/plugin-api.js +44 -1
  112. package/dist/vite/plugin-api.js.map +1 -1
  113. package/dist/vite/plugin-component.js +1 -0
  114. package/dist/vite/plugin-component.js.map +1 -1
  115. package/dist/vite/plugin-config-reload.d.ts +1 -2
  116. package/dist/vite/plugin-config-reload.js.map +1 -1
  117. package/dist/vite/plugin-config.js +20 -0
  118. package/dist/vite/plugin-config.js.map +1 -1
  119. package/dist/vite/plugin-mdx.js +48 -1
  120. package/dist/vite/plugin-mdx.js.map +1 -1
  121. package/dist/vite/{plugin-custom-css.d.ts → plugin-theme-css.d.ts} +2 -2
  122. package/dist/vite/{plugin-custom-css.js → plugin-theme-css.js} +10 -3
  123. package/dist/vite/plugin-theme-css.js.map +1 -0
  124. package/dist/vite/plugin.d.ts +1 -2
  125. package/dist/vite/plugin.js +2 -2
  126. package/dist/vite/plugin.js.map +1 -1
  127. package/dist/vite/prerender.d.ts +2 -1
  128. package/dist/vite/prerender.js +2 -2
  129. package/dist/vite/prerender.js.map +1 -1
  130. package/dist/vite/sitemap.d.ts +1 -1
  131. package/dist/zuplo/env.d.ts +6 -0
  132. package/dist/zuplo/env.js +9 -0
  133. package/dist/zuplo/env.js.map +1 -0
  134. package/dist/zuplo/with-zuplo.d.ts +2 -2
  135. package/dist/zuplo/with-zuplo.js.map +1 -1
  136. package/lib/AnchorLink-BR0MvI7n.js +35 -0
  137. package/lib/AnchorLink-BR0MvI7n.js.map +1 -0
  138. package/lib/{Markdown-ievDDhFT.js → Markdown-CRsmPPfY.js} +13084 -13096
  139. package/lib/Markdown-CRsmPPfY.js.map +1 -0
  140. package/lib/{MdxPage-B2FpJ9KC.js → MdxPage-Wp8QU0-q.js} +85 -80
  141. package/lib/MdxPage-Wp8QU0-q.js.map +1 -0
  142. package/lib/{OperationList-BkNQEsNs.js → OperationList-u8xHU9-b.js} +982 -969
  143. package/lib/{OperationList-BkNQEsNs.js.map → OperationList-u8xHU9-b.js.map} +1 -1
  144. package/lib/{SlotletProvider-DyomlzGx.js → SlotletProvider-BgvYIPQe.js} +2 -2
  145. package/lib/{SlotletProvider-DyomlzGx.js.map → SlotletProvider-BgvYIPQe.js.map} +1 -1
  146. package/lib/{SyntaxHighlight-DkLOsjHS.js → SyntaxHighlight-C31iouiO.js} +1 -3
  147. package/lib/{SyntaxHighlight-DkLOsjHS.js.map → SyntaxHighlight-C31iouiO.js.map} +1 -1
  148. package/lib/assets/{worker-BHClFO3A.js → worker-C_2va8B8.js} +435 -432
  149. package/lib/assets/{worker-BHClFO3A.js.map → worker-C_2va8B8.js.map} +1 -1
  150. package/lib/{createServer-CpJlUPtn.js → createServer-BCAHdrpE.js} +5 -2
  151. package/lib/{createServer-CpJlUPtn.js.map → createServer-BCAHdrpE.js.map} +1 -1
  152. package/lib/{index-C7SaIME0.js → index-CmdLGbbk.js} +7 -5
  153. package/lib/index-CmdLGbbk.js.map +1 -0
  154. package/lib/{AnchorLink-CDlhr8gL.js → index.esm-Bm8pj-bc.js} +223 -254
  155. package/lib/index.esm-Bm8pj-bc.js.map +1 -0
  156. package/lib/ui/Drawer.js +79 -79
  157. package/lib/ui/Drawer.js.map +1 -1
  158. package/lib/zudoku.auth-openid.js +42 -37
  159. package/lib/zudoku.auth-openid.js.map +1 -1
  160. package/lib/zudoku.components.js +386 -367
  161. package/lib/zudoku.components.js.map +1 -1
  162. package/lib/zudoku.openapi-worker.js +1 -1
  163. package/lib/zudoku.plugin-api-catalog.js +121 -0
  164. package/lib/zudoku.plugin-api-catalog.js.map +1 -0
  165. package/lib/zudoku.plugin-api-keys.js +1 -1
  166. package/lib/zudoku.plugin-custom-pages.js +1 -1
  167. package/lib/zudoku.plugin-markdown.js +1 -1
  168. package/lib/zudoku.plugin-markdown.js.map +1 -1
  169. package/lib/zudoku.plugin-openapi.js +1 -1
  170. package/lib/zudoku.plugin-redirect.js.map +1 -1
  171. package/package.json +19 -6
  172. package/src/app/entry.client.tsx +15 -0
  173. package/src/app/entry.server.tsx +1 -0
  174. package/src/app/main.tsx +5 -1
  175. package/src/app/sentry.ts +24 -0
  176. package/src/app/tailwind.ts +67 -52
  177. package/src/lib/authentication/providers/openid.tsx +7 -2
  178. package/src/lib/components/Heading.tsx +13 -13
  179. package/src/lib/components/Layout.tsx +8 -3
  180. package/src/lib/components/Markdown.tsx +1 -1
  181. package/src/lib/components/MobileTopNavigation.tsx +18 -18
  182. package/src/lib/components/ReactMarkdown.license.txt +21 -0
  183. package/src/lib/components/ReactMarkdown.tsx +264 -0
  184. package/src/lib/components/Search.tsx +3 -3
  185. package/src/lib/components/SyntaxHighlight.tsx +0 -4
  186. package/src/lib/components/TopNavigation.tsx +1 -1
  187. package/src/lib/components/navigation/Sidebar.tsx +18 -8
  188. package/src/lib/components/navigation/SidebarCategory.tsx +10 -9
  189. package/src/lib/components/navigation/SidebarItem.tsx +10 -13
  190. package/src/lib/components/navigation/SidebarWrapper.tsx +1 -1
  191. package/src/lib/core/ZudokuContext.ts +1 -1
  192. package/src/lib/oas/graphql/index.ts +4 -1
  193. package/src/lib/plugins/api-catalog/Catalog.tsx +124 -0
  194. package/src/lib/plugins/api-catalog/index.tsx +50 -0
  195. package/src/lib/plugins/markdown/MdxPage.tsx +2 -0
  196. package/src/lib/plugins/markdown/index.tsx +2 -1
  197. package/src/lib/plugins/markdown/resolver.ts +2 -4
  198. package/src/lib/plugins/openapi/OperationList.tsx +64 -3
  199. package/src/lib/plugins/openapi/graphql/gql.ts +2 -2
  200. package/src/lib/plugins/openapi/graphql/graphql.ts +3 -0
  201. package/src/lib/plugins/openapi/playground/PathParams.tsx +1 -0
  202. package/src/lib/plugins/redirect/index.tsx +1 -1
  203. package/src/lib/util/MdxComponents.tsx +2 -5
  204. package/dist/vite/plugin-custom-css.js.map +0 -1
  205. package/lib/AnchorLink-CDlhr8gL.js.map +0 -1
  206. package/lib/Markdown-ievDDhFT.js.map +0 -1
  207. package/lib/MdxPage-B2FpJ9KC.js.map +0 -1
  208. package/lib/index-C7SaIME0.js.map +0 -1
  209. package/lib/prism-markup-templating-DZrrEs0A.js +0 -62
  210. package/lib/prism-markup-templating-DZrrEs0A.js.map +0 -1
  211. package/lib/prism-php.min-o7FpoMP_.js +0 -11
  212. package/lib/prism-php.min-o7FpoMP_.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  import { Helmet } from "@zudoku/react-helmet-async";
2
2
  import { PanelLeftIcon } from "lucide-react";
3
- import { Suspense, useEffect, useRef, type ReactNode } from "react";
3
+ import { Suspense, useEffect, useRef, useState, type ReactNode } from "react";
4
4
  import { Outlet, useLocation, useNavigation } from "react-router-dom";
5
5
  import { useSpinDelay } from "spin-delay";
6
6
  import { Drawer, DrawerTrigger } from "../ui/Drawer.js";
@@ -49,6 +49,7 @@ export const Layout = ({ children }: { children?: ReactNode }) => {
49
49
  delay: 300,
50
50
  minDuration: 500,
51
51
  });
52
+ const [isDrawerOpen, setDrawerOpen] = useState(false);
52
53
 
53
54
  return (
54
55
  <>
@@ -70,8 +71,12 @@ export const Layout = ({ children }: { children?: ReactNode }) => {
70
71
  <LoadingFallback />
71
72
  ) : (
72
73
  <Suspense fallback={<LoadingFallback />}>
73
- <Drawer direction="left">
74
- <Sidebar />
74
+ <Drawer
75
+ direction="left"
76
+ open={isDrawerOpen}
77
+ onOpenChange={(open) => setDrawerOpen(open)}
78
+ >
79
+ <Sidebar onRequestClose={() => setDrawerOpen(false)} />
75
80
  <div
76
81
  className={cn(
77
82
  "lg:hidden -mx-10 px-10 py-2 sticky bg-background/80 backdrop-blur z-10 top-0 left-0 right-0 border-b",
@@ -1,8 +1,8 @@
1
- import ReactMarkdown from "react-markdown";
2
1
  import rehypeRaw from "rehype-raw";
3
2
  import remarkGfm from "remark-gfm";
4
3
  import { visit } from "unist-util-visit";
5
4
  import { MdxComponents } from "../util/MdxComponents.js";
5
+ import { ReactMarkdown } from "./ReactMarkdown.js";
6
6
 
7
7
  // same as in packages/dev-portal/framework/vite.ts
8
8
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -30,27 +30,27 @@ export const MobileTopNavigation = () => {
30
30
  </DrawerTrigger>
31
31
  </div>
32
32
  <DrawerContent
33
- className="lg:hidden h-screen right-0 left-auto w-[320px] rounded-none overflow-auto"
33
+ className="lg:hidden h-[100dvh] right-0 left-auto w-[320px] rounded-none"
34
34
  aria-describedby={undefined}
35
35
  >
36
- <VisuallyHidden>
37
- <DrawerTitle>Navigation</DrawerTitle>
38
- </VisuallyHidden>
39
- <div className="flex p-4">
40
- <Search />
41
- </div>
42
- <ul className="flex flex-col items-center gap-4 p-4">
43
- <li>
44
- <ThemeSwitch />
45
- </li>
46
- {topNavigation.filter(isHiddenItem(isAuthenticated)).map((item) => (
47
- <li key={item.label}>
48
- <button onClick={() => setDrawerOpen(false)}>
49
- <TopNavItem {...item} />
50
- </button>
36
+ <div className="p-6 overflow-y-auto overscroll-none">
37
+ <VisuallyHidden>
38
+ <DrawerTitle>Navigation</DrawerTitle>
39
+ </VisuallyHidden>
40
+ <Search className="flex p-4" />
41
+ <ul className="flex flex-col items-center gap-4 p-4">
42
+ <li>
43
+ <ThemeSwitch />
51
44
  </li>
52
- ))}
53
- </ul>
45
+ {topNavigation.filter(isHiddenItem(isAuthenticated)).map((item) => (
46
+ <li key={item.label}>
47
+ <button onClick={() => setDrawerOpen(false)}>
48
+ <TopNavItem {...item} />
49
+ </button>
50
+ </li>
51
+ ))}
52
+ </ul>
53
+ </div>
54
54
  </DrawerContent>
55
55
  </Drawer>
56
56
  );
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) Espen Hovlandsdal
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,264 @@
1
+ /* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
2
+ /* eslint-disable @typescript-eslint/no-unnecessary-condition */
3
+
4
+ /**
5
+ * This is a fork of `react-markdown` converted to typescript.
6
+ * The reason we fork it is because react-markdown is comptaible with
7
+ * unified 11, but references the unified 10 and related packages causing
8
+ * type errors and a bunch of extra imports
9
+ *
10
+ * Source: https://github.com/remarkjs/react-markdown/blob/main/index.js
11
+ */
12
+
13
+ import { unreachable } from "devlop";
14
+ import type { Element, ElementContent, Nodes, Parents } from "hast";
15
+ import {
16
+ Components as JsxRuntimeComponents,
17
+ toJsxRuntime,
18
+ } from "hast-util-to-jsx-runtime";
19
+ import { urlAttributes } from "html-url-attributes";
20
+ import { ReactElement } from "react";
21
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
22
+ import remarkParse from "remark-parse";
23
+ import remarkRehype, { Options as RemarkRehypeOptions } from "remark-rehype";
24
+ import { PluggableList, unified } from "unified";
25
+ import { visit } from "unist-util-visit";
26
+ import { VFile } from "vfile";
27
+
28
+ const changelog =
29
+ "https://github.com/remarkjs/react-markdown/blob/main/changelog.md";
30
+
31
+ const emptyPlugins: PluggableList = [];
32
+ const emptyRemarkRehypeOptions: Readonly<RemarkRehypeOptions> = {
33
+ allowDangerousHtml: true,
34
+ };
35
+ const safeProtocol = /^(https?|ircs?|mailto|xmpp)$/i;
36
+
37
+ interface Deprecation {
38
+ from: string;
39
+ id: string;
40
+ to?: keyof Options;
41
+ }
42
+
43
+ interface AllowElement {
44
+ (
45
+ element: Readonly<Element>,
46
+ index: number,
47
+ parent: Readonly<Parents> | undefined,
48
+ ): boolean | null | undefined;
49
+ }
50
+
51
+ interface UrlTransform {
52
+ (
53
+ url: string,
54
+ key: string,
55
+ node: Readonly<Element>,
56
+ ): string | null | undefined;
57
+ }
58
+
59
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
60
+ interface Components extends Partial<JsxRuntimeComponents> {}
61
+
62
+ interface Options {
63
+ allowElement?: AllowElement | null;
64
+ allowedElements?: ReadonlyArray<string> | null;
65
+ children?: string | null;
66
+ className?: string | null;
67
+ components?: Components | null;
68
+ disallowedElements?: ReadonlyArray<string> | null;
69
+ rehypePlugins?: PluggableList | null;
70
+ remarkPlugins?: PluggableList | null;
71
+ remarkRehypeOptions?: Readonly<RemarkRehypeOptions> | null;
72
+ skipHtml?: boolean | null;
73
+ unwrapDisallowed?: boolean | null;
74
+ urlTransform?: UrlTransform | null;
75
+ }
76
+
77
+ const deprecations: ReadonlyArray<Readonly<Deprecation>> = [
78
+ { from: "astPlugins", id: "remove-buggy-html-in-markdown-parser" },
79
+ { from: "allowDangerousHtml", id: "remove-buggy-html-in-markdown-parser" },
80
+ {
81
+ from: "allowNode",
82
+ id: "replace-allownode-allowedtypes-and-disallowedtypes",
83
+ to: "allowElement",
84
+ },
85
+ {
86
+ from: "allowedTypes",
87
+ id: "replace-allownode-allowedtypes-and-disallowedtypes",
88
+ to: "allowedElements",
89
+ },
90
+ {
91
+ from: "disallowedTypes",
92
+ id: "replace-allownode-allowedtypes-and-disallowedtypes",
93
+ to: "disallowedElements",
94
+ },
95
+ { from: "escapeHtml", id: "remove-buggy-html-in-markdown-parser" },
96
+ { from: "includeElementIndex", id: "#remove-includeelementindex" },
97
+ {
98
+ from: "includeNodeIndex",
99
+ id: "change-includenodeindex-to-includeelementindex",
100
+ },
101
+ { from: "linkTarget", id: "remove-linktarget" },
102
+ {
103
+ from: "plugins",
104
+ id: "change-plugins-to-remarkplugins",
105
+ to: "remarkPlugins",
106
+ },
107
+ { from: "rawSourcePos", id: "#remove-rawsourcepos" },
108
+ { from: "renderers", id: "change-renderers-to-components", to: "components" },
109
+ { from: "source", id: "change-source-to-children", to: "children" },
110
+ { from: "sourcePos", id: "#remove-sourcepos" },
111
+ { from: "transformImageUri", id: "#add-urltransform", to: "urlTransform" },
112
+ { from: "transformLinkUri", id: "#add-urltransform", to: "urlTransform" },
113
+ ];
114
+
115
+ export function ReactMarkdown(options: Readonly<Options>): ReactElement {
116
+ const allowedElements = options.allowedElements;
117
+ const allowElement = options.allowElement;
118
+ const children = options.children || "";
119
+ const className = options.className;
120
+ const components = options.components;
121
+ const disallowedElements = options.disallowedElements;
122
+ const rehypePlugins = options.rehypePlugins || emptyPlugins;
123
+ const remarkPlugins = options.remarkPlugins || emptyPlugins;
124
+ const remarkRehypeOptions = options.remarkRehypeOptions
125
+ ? { ...options.remarkRehypeOptions, ...emptyRemarkRehypeOptions }
126
+ : emptyRemarkRehypeOptions;
127
+ const skipHtml = options.skipHtml;
128
+ const unwrapDisallowed = options.unwrapDisallowed;
129
+ const urlTransform = options.urlTransform || defaultUrlTransform;
130
+
131
+ const processor = unified()
132
+ .use(remarkParse)
133
+ .use(remarkPlugins)
134
+ .use(remarkRehype, remarkRehypeOptions)
135
+ .use(rehypePlugins);
136
+
137
+ const file = new VFile();
138
+
139
+ if (typeof children === "string") {
140
+ file.value = children;
141
+ } else {
142
+ unreachable(
143
+ `Unexpected value '${children}' for 'children' prop, expected 'string'`,
144
+ );
145
+ }
146
+
147
+ if (allowedElements && disallowedElements) {
148
+ unreachable(
149
+ "Unexpected combined `allowedElements` and `disallowedElements`, expected one or the other",
150
+ );
151
+ }
152
+
153
+ for (const deprecation of deprecations) {
154
+ if (Object.prototype.hasOwnProperty.call(options, deprecation.from)) {
155
+ unreachable(
156
+ `Unexpected '${deprecation.from}' prop, ` +
157
+ (deprecation.to ? `use '${deprecation.to}' instead` : "remove it") +
158
+ ` (see <${changelog}#${deprecation.id}> for more info)`,
159
+ );
160
+ }
161
+ }
162
+
163
+ const mdastTree = processor.parse(file);
164
+ let hastTree: Nodes = processor.runSync(mdastTree, file);
165
+
166
+ if (className) {
167
+ hastTree = {
168
+ type: "element",
169
+ tagName: "div",
170
+ properties: { className },
171
+ children:
172
+ hastTree.type === "root"
173
+ ? (hastTree.children as ElementContent[])
174
+ : [hastTree],
175
+ };
176
+ }
177
+
178
+ // Nodes type is slightly off, different versions of `hast` have different types
179
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
180
+ // @ts-ignore
181
+ visit(hastTree, transform);
182
+
183
+ return toJsxRuntime(hastTree, {
184
+ Fragment,
185
+ components,
186
+ ignoreInvalidStyle: true,
187
+ jsx,
188
+ jsxs,
189
+ passKeys: true,
190
+ passNode: true,
191
+ });
192
+
193
+ function transform(
194
+ node: Nodes,
195
+ index: number | null,
196
+ parent: Parents | undefined,
197
+ ): number | void {
198
+ if (node.type === "raw" && parent && typeof index === "number") {
199
+ if (skipHtml) {
200
+ parent.children.splice(index, 1);
201
+ } else {
202
+ parent.children[index] = { type: "text", value: node.value };
203
+ }
204
+ return index;
205
+ }
206
+
207
+ if (node.type === "element") {
208
+ for (const key in urlAttributes) {
209
+ if (
210
+ Object.prototype.hasOwnProperty.call(urlAttributes, key) &&
211
+ Object.prototype.hasOwnProperty.call(node.properties, key)
212
+ ) {
213
+ const value = node.properties[key];
214
+ const test = urlAttributes[key];
215
+ if (
216
+ test === null ||
217
+ test === undefined ||
218
+ test.includes(node.tagName)
219
+ ) {
220
+ node.properties[key] = urlTransform(String(value || ""), key, node);
221
+ }
222
+ }
223
+ }
224
+
225
+ let remove = allowedElements
226
+ ? !allowedElements.includes(node.tagName)
227
+ : disallowedElements
228
+ ? disallowedElements.includes(node.tagName)
229
+ : false;
230
+
231
+ if (!remove && allowElement && typeof index === "number") {
232
+ remove = !allowElement(node, index, parent);
233
+ }
234
+
235
+ if (remove && parent && typeof index === "number") {
236
+ if (unwrapDisallowed && node.children) {
237
+ parent.children.splice(index, 1, ...node.children);
238
+ } else {
239
+ parent.children.splice(index, 1);
240
+ }
241
+ return index;
242
+ }
243
+ }
244
+ }
245
+ }
246
+
247
+ function defaultUrlTransform(value: string): string {
248
+ const colon = value.indexOf(":");
249
+ const questionMark = value.indexOf("?");
250
+ const numberSign = value.indexOf("#");
251
+ const slash = value.indexOf("/");
252
+
253
+ if (
254
+ colon < 0 ||
255
+ (slash > -1 && colon > slash) ||
256
+ (questionMark > -1 && colon > questionMark) ||
257
+ (numberSign > -1 && colon > numberSign) ||
258
+ safeProtocol.test(value.slice(0, colon))
259
+ ) {
260
+ return value;
261
+ }
262
+
263
+ return "";
264
+ }
@@ -3,7 +3,7 @@ import { Suspense, useCallback, useEffect, useState } from "react";
3
3
  import { isSearchPlugin } from "../core/plugins.js";
4
4
  import { useZudoku } from "./context/ZudokuContext.js";
5
5
 
6
- export const Search = () => {
6
+ export const Search = ({ className }: { className?: string }) => {
7
7
  const ctx = useZudoku();
8
8
  const [isOpen, setIsOpen] = useState(false);
9
9
 
@@ -35,7 +35,7 @@ export const Search = () => {
35
35
  }
36
36
 
37
37
  return (
38
- <>
38
+ <div className={className}>
39
39
  <button
40
40
  type="button"
41
41
  onClick={() => setIsOpen(true)}
@@ -55,6 +55,6 @@ export const Search = () => {
55
55
  onClose,
56
56
  })}
57
57
  </Suspense>
58
- </>
58
+ </div>
59
59
  );
60
60
  };
@@ -13,12 +13,8 @@ void import("prismjs/components/prism-bash.min.js");
13
13
  // @ts-expect-error This is untyped
14
14
  void import("prismjs/components/prism-ruby.min.js");
15
15
  // @ts-expect-error This is untyped
16
- void import("prismjs/components/prism-markup-templating.js");
17
- // @ts-expect-error This is untyped
18
16
  void import("prismjs/components/prism-markup.js");
19
17
  // @ts-expect-error This is untyped
20
- void import("prismjs/components/prism-php.min.js");
21
- // @ts-expect-error This is untyped
22
18
  void import("prismjs/components/prism-json.min.js");
23
19
  // @ts-expect-error This is untyped
24
20
  void import("prismjs/components/prism-java.min.js");
@@ -1,7 +1,7 @@
1
1
  import { cx } from "class-variance-authority";
2
2
  import { Suspense } from "react";
3
3
  import { NavLink, useNavigation } from "react-router-dom";
4
- import { TopNavigationItem } from "../../config/validators/validate.js";
4
+ import { TopNavigationItem } from "../../config/validators/common.js";
5
5
  import { useAuth } from "../authentication/hook.js";
6
6
  import { ZudokuError } from "../util/invariant.js";
7
7
  import { joinPath } from "../util/joinPath.js";
@@ -7,7 +7,11 @@ import { Slotlet } from "../SlotletProvider.js";
7
7
  import { SidebarItem } from "./SidebarItem.js";
8
8
  import { SidebarWrapper } from "./SidebarWrapper.js";
9
9
 
10
- export const Sidebar = () => {
10
+ export const Sidebar = ({
11
+ onRequestClose,
12
+ }: {
13
+ onRequestClose?: () => void;
14
+ }) => {
11
15
  const navRef = useRef<HTMLDivElement | null>(null);
12
16
  const navigation = useCurrentNavigation();
13
17
 
@@ -24,15 +28,21 @@ export const Sidebar = () => {
24
28
  <Slotlet name="zudoku-after-navigation" />
25
29
  </SidebarWrapper>
26
30
  <DrawerContent
27
- className="lg:hidden h-screen left-0 p-6 w-[320px] rounded-none overflow-auto"
31
+ className="lg:hidden h-[100dvh] left-0 w-[320px] rounded-none"
28
32
  aria-describedby={undefined}
29
33
  >
30
- <VisuallyHidden>
31
- <DrawerTitle>Sidebar</DrawerTitle>
32
- </VisuallyHidden>
33
- {navigation.sidebar.map((item) => (
34
- <SidebarItem key={item.label} item={item} />
35
- ))}
34
+ <div className="p-6 overflow-y-auto overscroll-none">
35
+ <VisuallyHidden>
36
+ <DrawerTitle>Sidebar</DrawerTitle>
37
+ </VisuallyHidden>
38
+ {navigation.sidebar.map((item) => (
39
+ <SidebarItem
40
+ key={item.label}
41
+ item={item}
42
+ onRequestClose={onRequestClose}
43
+ />
44
+ ))}
45
+ </div>
36
46
  </DrawerContent>
37
47
  </>
38
48
  );
@@ -10,10 +10,10 @@ import { useIsCategoryOpen } from "./utils.js";
10
10
 
11
11
  export const SidebarCategory = ({
12
12
  category,
13
- level,
13
+ onRequestClose,
14
14
  }: {
15
15
  category: SidebarItemCategory;
16
- level: number;
16
+ onRequestClose?: () => void;
17
17
  }) => {
18
18
  const isCategoryOpen = useIsCategoryOpen(category);
19
19
  const [hasInteracted, setHasInteracted] = useState(false);
@@ -65,7 +65,6 @@ export const SidebarCategory = ({
65
65
  onClick={() => setHasInteracted(true)}
66
66
  className={navigationListItem({
67
67
  isActive: false,
68
- isTopLevel: level === 0,
69
68
  className: [
70
69
  "text-start",
71
70
  isCollapsible
@@ -77,10 +76,7 @@ export const SidebarCategory = ({
77
76
  {category.icon && (
78
77
  <category.icon
79
78
  size={16}
80
- className={cn(
81
- "align-[-0.125em] -translate-x-1",
82
- isActive && "text-primary",
83
- )}
79
+ className={cn("align-[-0.125em] ", isActive && "text-primary")}
84
80
  />
85
81
  )}
86
82
  {category.link?.type === "doc" ? (
@@ -116,9 +112,14 @@ export const SidebarCategory = ({
116
112
  className={cn(
117
113
  // CollapsibleContent class is used to animate and it should only be applied when the user has triggered the toggle
118
114
  hasInteracted && "CollapsibleContent",
115
+ "ms-6 my-1",
119
116
  )}
120
117
  >
121
- <ul className="mt-1 border-l ms-0.5">
118
+ <ul
119
+ className={
120
+ "relative after:absolute after:-left-[--padding-nav-item] after:translate-x-[1.5px] after:top-0 after:bottom-0 after:w-px after:bg-border"
121
+ }
122
+ >
122
123
  {category.items.map((item) => (
123
124
  <SidebarItem
124
125
  key={
@@ -126,7 +127,7 @@ export const SidebarCategory = ({
126
127
  ("href" in item ? item.href : "") +
127
128
  item.label
128
129
  }
129
- level={level + 1}
130
+ onRequestClose={onRequestClose}
130
131
  item={item}
131
132
  />
132
133
  ))}
@@ -13,10 +13,6 @@ export const navigationListItem = cva(
13
13
  "flex items-center gap-2 px-[--padding-nav-item] py-1.5 rounded-lg hover:bg-accent transition-colors duration-300",
14
14
  {
15
15
  variants: {
16
- isTopLevel: {
17
- true: "font-medium -mx-[--padding-nav-item]",
18
- false: "-mr-[--padding-nav-item] ml-[--padding-nav-item]",
19
- },
20
16
  isActive: {
21
17
  true: "text-primary font-medium",
22
18
  false: "text-foreground/80",
@@ -36,25 +32,25 @@ export const DATA_ANCHOR_ATTR = "data-anchor";
36
32
 
37
33
  export const SidebarItem = ({
38
34
  item,
39
- level = 0,
35
+ onRequestClose,
40
36
  }: {
41
37
  item: SidebarItemType;
42
- basePath?: string;
43
- level?: number;
38
+ onRequestClose?: () => void;
44
39
  }) => {
45
40
  const { activeAnchor } = useViewportAnchor();
46
41
  const [searchParams] = useSearchParams();
47
42
 
48
43
  switch (item.type) {
49
44
  case "category":
50
- return <SidebarCategory category={item} level={level} />;
45
+ return (
46
+ <SidebarCategory category={item} onRequestClose={onRequestClose} />
47
+ );
51
48
  case "doc":
52
49
  return (
53
50
  <NavLink
54
- className={({ isActive }) =>
55
- navigationListItem({ isActive, isTopLevel: level === 0 })
56
- }
51
+ className={({ isActive }) => navigationListItem({ isActive })}
57
52
  to={joinPath(item.id)}
53
+ onClick={onRequestClose}
58
54
  >
59
55
  {item.icon && <item.icon size={16} className="align-[-0.125em]" />}
60
56
  {item.badge ? (
@@ -76,9 +72,9 @@ export const SidebarItem = ({
76
72
  {...{ [DATA_ANCHOR_ATTR]: item.href.slice(1) }}
77
73
  className={navigationListItem({
78
74
  isActive: item.href.slice(1) === activeAnchor,
79
- isTopLevel: level === 0,
80
75
  className: item.badge?.placement !== "start" && "justify-between",
81
76
  })}
77
+ onClick={onRequestClose}
82
78
  >
83
79
  {item.badge ? (
84
80
  <>
@@ -111,10 +107,11 @@ export const SidebarItem = ({
111
107
  </NavLink>
112
108
  ) : (
113
109
  <a
114
- className={navigationListItem({ isTopLevel: level === 0 })}
110
+ className={navigationListItem()}
115
111
  href={item.href}
116
112
  target="_blank"
117
113
  rel="noopener noreferrer"
114
+ onClick={onRequestClose}
118
115
  >
119
116
  <span className="whitespace-normal">{item.label}</span>
120
117
  {/* This prevents that the icon would be positioned in its own line if the text fills a line entirely */}
@@ -13,7 +13,7 @@ export const SidebarWrapper = forwardRef<
13
13
  data-navigation={String(pushMainContent)}
14
14
  className={cn(
15
15
  "scrollbar peer hidden lg:flex flex-col fixed text-sm overflow-y-auto shrink-0",
16
- "px-[--padding-nav-item] -mx-[--padding-nav-item] pb-20 mt-[--padding-content-top]",
16
+ "-mx-[--padding-nav-item] pb-20 mt-[--padding-content-top]",
17
17
  "w-[--side-nav-width] h-[calc(100%-var(--header-height))] scroll-pt-2 gap-2",
18
18
  className,
19
19
  )}
@@ -1,6 +1,6 @@
1
1
  import { ReactNode } from "react";
2
+ import { TopNavigationItem } from "../../config/validators/common.js";
2
3
  import type { SidebarConfig } from "../../config/validators/SidebarSchema.js";
3
- import { TopNavigationItem } from "../../config/validators/validate.js";
4
4
  import { type AuthenticationProvider } from "../authentication/authentication.js";
5
5
  import type { ComponentsContextType } from "../components/context/ComponentsContext.js";
6
6
  import { Slotlets } from "../components/SlotletProvider.js";
@@ -390,6 +390,10 @@ const Schema = builder.objectRef<OpenAPIDocument>("Schema").implement({
390
390
  resolve: (root) => root.info.description,
391
391
  nullable: true,
392
392
  }),
393
+ summary: t.string({
394
+ resolve: (root) => root.info.summary,
395
+ nullable: true,
396
+ }),
393
397
  paths: t.field({
394
398
  type: [PathItem],
395
399
  resolve: (root) =>
@@ -439,7 +443,6 @@ const SchemaSource = builder.enumType("SchemaType", {
439
443
 
440
444
  builder.queryType({
441
445
  fields: (t) => ({
442
- // https://tan-cow-main-bce8a06.d2.zuplo.dev/openapi
443
446
  schema: t.field({
444
447
  type: Schema,
445
448
  args: {