zudoku 0.0.0-eb5886a → 0.0.0-f114fe8
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/cli.js +2 -2
- package/dist/app/entry.client.js +2 -2
- package/dist/app/entry.client.js.map +1 -1
- package/dist/app/entry.server.js +0 -3
- package/dist/app/entry.server.js.map +1 -1
- package/dist/app/main.d.ts +0 -1
- package/dist/app/main.js +21 -6
- package/dist/app/main.js.map +1 -1
- package/dist/app/standalone.js.map +1 -1
- package/dist/cli/common/machine-id/lib.js.map +1 -1
- package/dist/cli/common/outdated.js.map +1 -1
- package/dist/cli/common/utils/box.js.map +1 -1
- package/dist/config/config.d.ts +1 -1
- package/dist/config/validators/SidebarSchema.d.ts +1 -1
- package/dist/config/validators/SidebarSchema.js +9 -5
- package/dist/config/validators/SidebarSchema.js.map +1 -1
- package/dist/config/validators/validate.d.ts +48 -62
- package/dist/config/validators/validate.js +5 -6
- package/dist/config/validators/validate.js.map +1 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/components/Header.js +1 -5
- package/dist/lib/components/Header.js.map +1 -1
- package/dist/lib/components/TopNavigation.js +4 -28
- package/dist/lib/components/TopNavigation.js.map +1 -1
- package/dist/lib/components/context/ZudokuContext.d.ts +12 -5
- package/dist/lib/components/context/ZudokuContext.js +20 -26
- package/dist/lib/components/context/ZudokuContext.js.map +1 -1
- package/dist/lib/components/index.d.ts +1 -1
- package/dist/lib/components/navigation/Sidebar.js +3 -3
- package/dist/lib/components/navigation/Sidebar.js.map +1 -1
- package/dist/lib/components/navigation/SidebarCategory.js +3 -1
- package/dist/lib/components/navigation/SidebarCategory.js.map +1 -1
- package/dist/lib/components/navigation/SidebarItem.js +3 -1
- package/dist/lib/components/navigation/SidebarItem.js.map +1 -1
- package/dist/lib/components/navigation/utils.js +14 -10
- package/dist/lib/components/navigation/utils.js.map +1 -1
- package/dist/lib/core/DevPortalContext.d.ts +6 -3
- package/dist/lib/core/DevPortalContext.js.map +1 -1
- package/dist/lib/core/plugins.d.ts +0 -1
- package/dist/lib/core/plugins.js.map +1 -1
- package/dist/lib/plugins/markdown/generateRoutes.d.ts +3 -0
- package/dist/lib/plugins/markdown/generateRoutes.js +21 -0
- package/dist/lib/plugins/markdown/generateRoutes.js.map +1 -0
- package/dist/lib/plugins/markdown/index.d.ts +6 -5
- package/dist/lib/plugins/markdown/index.js +3 -31
- package/dist/lib/plugins/markdown/index.js.map +1 -1
- package/dist/lib/plugins/openapi/Endpoint.js.map +1 -1
- package/dist/lib/plugins/openapi/RequestBodySidecarBox.js.map +1 -1
- package/dist/lib/plugins/openapi/Sidecar.js.map +1 -1
- package/dist/lib/plugins/openapi/client/worker.js.map +1 -1
- package/dist/lib/plugins/openapi/index.js.map +1 -1
- package/dist/lib/ui/Button.d.ts +1 -1
- package/dist/lib/util/MdxComponents.d.ts +1 -1
- package/dist/lib/util/useScrollToAnchor.js.map +1 -1
- package/dist/vite/plugin-config-reload.js.map +1 -1
- package/dist/vite/plugin-docs.js +13 -19
- package/dist/vite/plugin-docs.js.map +1 -1
- package/dist/vite/plugin-sidebar.js +2 -5
- package/dist/vite/plugin-sidebar.js.map +1 -1
- package/lib/{AuthenticationPlugin-BFO0iXPa.js → AuthenticationPlugin-Bx9FK124.js} +2 -2
- package/lib/{AuthenticationPlugin-BFO0iXPa.js.map → AuthenticationPlugin-Bx9FK124.js.map} +1 -1
- package/lib/{Input-B2qMWklW.js → Input-CtVUl3eT.js} +3 -3
- package/lib/{Input-B2qMWklW.js.map → Input-CtVUl3eT.js.map} +1 -1
- package/lib/{MdxPage-aE7f-Uli.js → MdxPage-BqBWsXZ1.js} +24 -25
- package/lib/{MdxPage-aE7f-Uli.js.map → MdxPage-BqBWsXZ1.js.map} +1 -1
- package/lib/{OperationList-BcfWM4ir.js → OperationList-CYrmxPa8.js} +4 -4
- package/lib/OperationList-CYrmxPa8.js.map +1 -0
- package/lib/{Route-DzTbXYJ8.js → Route-Q5mqNQrv.js} +2 -2
- package/lib/{Route-DzTbXYJ8.js.map → Route-Q5mqNQrv.js.map} +1 -1
- package/lib/{SidebarBadge-1Mv5r_Vo.js → SidebarBadge-Dx7jtnoA.js} +2 -2
- package/lib/{SidebarBadge-1Mv5r_Vo.js.map → SidebarBadge-Dx7jtnoA.js.map} +1 -1
- package/lib/ZudokuContext-cr-pTRY1.js +1084 -0
- package/lib/ZudokuContext-cr-pTRY1.js.map +1 -0
- package/lib/assets/worker-Bcj4NA2p.js.map +1 -1
- package/lib/{index-DrrYONSc.js → index-BlJ2rj99.js} +419 -416
- package/lib/index-BlJ2rj99.js.map +1 -0
- package/lib/{index-Bwy2Len1.js → index-BngPzhKn.js} +3 -3
- package/lib/{index-Bwy2Len1.js.map → index-BngPzhKn.js.map} +1 -1
- package/lib/{index-DtahPCcC.js → index-Dolisrci.js} +2 -2
- package/lib/{index-DtahPCcC.js.map → index-Dolisrci.js.map} +1 -1
- package/lib/joinPath-B7kNnUX4.js +8 -0
- package/lib/joinPath-B7kNnUX4.js.map +1 -0
- package/lib/{AnchorLink-CnXSVkGB.js → utils-ByIc_KIM.js} +275 -231
- package/lib/utils-ByIc_KIM.js.map +1 -0
- package/lib/zudoku.auth-clerk.js +1 -1
- package/lib/zudoku.auth-openid.js +1 -1
- package/lib/zudoku.components.js +735 -745
- package/lib/zudoku.components.js.map +1 -1
- package/lib/zudoku.plugin-api-keys.js +3 -3
- package/lib/zudoku.plugin-markdown.js +27 -93
- package/lib/zudoku.plugin-markdown.js.map +1 -1
- package/lib/zudoku.plugin-openapi.js +5 -4
- package/lib/zudoku.plugin-openapi.js.map +1 -1
- package/package.json +1 -1
- package/src/app/entry.client.tsx +2 -4
- package/src/app/entry.server.tsx +0 -4
- package/src/app/main.tsx +25 -9
- package/src/app/standalone.tsx +1 -1
- package/src/lib/components/Header.tsx +2 -10
- package/src/lib/components/TopNavigation.tsx +15 -47
- package/src/lib/components/context/ZudokuContext.ts +20 -34
- package/src/lib/components/navigation/Sidebar.tsx +5 -5
- package/src/lib/components/navigation/SidebarCategory.tsx +3 -1
- package/src/lib/components/navigation/SidebarItem.tsx +3 -1
- package/src/lib/components/navigation/utils.ts +16 -11
- package/src/lib/core/DevPortalContext.ts +2 -3
- package/src/lib/core/plugins.ts +0 -2
- package/src/lib/plugins/markdown/generateRoutes.tsx +38 -0
- package/src/lib/plugins/markdown/index.tsx +12 -49
- package/src/lib/plugins/openapi/Endpoint.tsx +2 -2
- package/src/lib/plugins/openapi/RequestBodySidecarBox.tsx +1 -1
- package/src/lib/plugins/openapi/Sidecar.tsx +1 -1
- package/src/lib/plugins/openapi/client/worker.ts +2 -2
- package/src/lib/plugins/openapi/index.tsx +1 -1
- package/src/lib/util/useScrollToAnchor.ts +1 -1
- package/dist/lib/plugins/markdown/resolver.d.ts +0 -38
- package/dist/lib/plugins/markdown/resolver.js +0 -75
- package/dist/lib/plugins/markdown/resolver.js.map +0 -1
- package/dist/vite/debug.d.ts +0 -1
- package/dist/vite/debug.js +0 -10
- package/dist/vite/debug.js.map +0 -1
- package/lib/AnchorLink-CnXSVkGB.js.map +0 -1
- package/lib/OperationList-BcfWM4ir.js.map +0 -1
- package/lib/ZudokuContext-CSrx4lfi.js +0 -1134
- package/lib/ZudokuContext-CSrx4lfi.js.map +0 -1
- package/lib/__vite-browser-external-BYRIRx8p.js +0 -9
- package/lib/__vite-browser-external-BYRIRx8p.js.map +0 -1
- package/lib/index-DrrYONSc.js.map +0 -1
- package/src/lib/plugins/markdown/resolver.ts +0 -92
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { j as e } from "./jsx-runtime-B6kdoens.js";
|
|
2
2
|
import { S as x, R as f } from "./SlotletProvider-D3UD5Go3.js";
|
|
3
|
-
import { u as g, a as d, I as j, S as v, b as w, c as b, d as k, e as K, f as m } from "./Input-
|
|
3
|
+
import { u as g, a as d, I as j, S as v, b as w, c as b, d as k, e as K, f as m } from "./Input-CtVUl3eT.js";
|
|
4
4
|
import { a as N, L as u, O as I } from "./index-BG0g4WW0.js";
|
|
5
|
-
import {
|
|
6
|
-
import { B as l, m as A } from "./index-
|
|
5
|
+
import { u as h, a as E, b as S } from "./ZudokuContext-cr-pTRY1.js";
|
|
6
|
+
import { B as l, m as A } from "./index-Dolisrci.js";
|
|
7
7
|
import { D as C } from "./DeveloperHint-YeWHKvyr.js";
|
|
8
8
|
import { RotateCwIcon as P, TrashIcon as D, EyeOffIcon as R, EyeIcon as q, CheckIcon as O, CopyIcon as z } from "lucide-react";
|
|
9
9
|
import { useState as p } from "react";
|
|
@@ -1,98 +1,32 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Resolves the first matching file system path for a given docId
|
|
20
|
-
* @param docId - The docId to resolve
|
|
21
|
-
* @returns
|
|
22
|
-
*/
|
|
23
|
-
resolveFilePath(t) {
|
|
24
|
-
const o = this.getDocsConfigs();
|
|
25
|
-
let s;
|
|
26
|
-
return o.forEach(({ files: i }) => {
|
|
27
|
-
if (s)
|
|
28
|
-
return;
|
|
29
|
-
const e = c.getRootDir(i);
|
|
30
|
-
for (const a of D) {
|
|
31
|
-
if (s)
|
|
32
|
-
return;
|
|
33
|
-
const r = u.join(e, `${t}${a}`);
|
|
34
|
-
u.existsSync(r) && (s = r);
|
|
35
|
-
}
|
|
36
|
-
}), s;
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Gets the root directory from a files glob
|
|
40
|
-
*/
|
|
41
|
-
static getRootDir(t) {
|
|
42
|
-
let o = t.split("**")[0];
|
|
43
|
-
if (!o)
|
|
44
|
-
throw new Error("Invalid files glob. Must have '**' in the path.");
|
|
45
|
-
return o = o.replace("/**", "/"), o;
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Resolves the route path for a given file system path
|
|
49
|
-
* @param options - The options to resolve the route path
|
|
50
|
-
* @returns The string route path
|
|
51
|
-
*/
|
|
52
|
-
static resolveRoutePath({
|
|
53
|
-
filesGlob: t,
|
|
54
|
-
fsPath: o
|
|
55
|
-
}) {
|
|
56
|
-
const s = this.getRootDir(t), i = new RegExp(`^${s}(.*).mdx?`), e = o.match(i);
|
|
57
|
-
return e == null ? void 0 : e.at(1);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
const C = (n) => ({
|
|
61
|
-
getRoutes: () => {
|
|
62
|
-
const t = /* @__PURE__ */ new Map();
|
|
63
|
-
return n.forEach(
|
|
64
|
-
({ fileImports: o, files: s, defaultOptions: i }) => Object.entries(o).flatMap(([e, a]) => {
|
|
65
|
-
const r = c.resolveRoutePath({
|
|
66
|
-
filesGlob: s,
|
|
67
|
-
fsPath: e
|
|
68
|
-
});
|
|
69
|
-
if (!r) return [];
|
|
70
|
-
if (t.has(r))
|
|
71
|
-
return console.warn(
|
|
72
|
-
`Duplicate route path found for ${r}. Skipping file at '${e}'.`
|
|
73
|
-
), [];
|
|
74
|
-
const h = {
|
|
75
|
-
path: r,
|
|
76
|
-
lazy: async () => {
|
|
77
|
-
const { MdxPage: l } = await import("./MdxPage-aE7f-Uli.js"), { default: p, ...g } = await a();
|
|
78
|
-
return {
|
|
79
|
-
element: /* @__PURE__ */ P.jsx(
|
|
80
|
-
l,
|
|
81
|
-
{
|
|
82
|
-
mdxComponent: p,
|
|
83
|
-
...g,
|
|
84
|
-
defaultOptions: i
|
|
85
|
-
}
|
|
86
|
-
)
|
|
87
|
-
};
|
|
1
|
+
import { j as u } from "./jsx-runtime-B6kdoens.js";
|
|
2
|
+
const x = (t, e, n) => Object.entries(t).flatMap(([a, p]) => {
|
|
3
|
+
let o = e.split("**")[0];
|
|
4
|
+
o = o.replace("/**", "/");
|
|
5
|
+
const c = new RegExp(`^${o}(.*).mdx?`), r = a.match(c), s = r == null ? void 0 : r.at(1);
|
|
6
|
+
return s ? {
|
|
7
|
+
path: s,
|
|
8
|
+
lazy: async () => {
|
|
9
|
+
const { MdxPage: i } = await import("./MdxPage-BqBWsXZ1.js"), { default: m, ...l } = await p();
|
|
10
|
+
return {
|
|
11
|
+
element: /* @__PURE__ */ u.jsx(
|
|
12
|
+
i,
|
|
13
|
+
{
|
|
14
|
+
mdxComponent: m,
|
|
15
|
+
...l,
|
|
16
|
+
defaultOptions: n
|
|
88
17
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
18
|
+
)
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
} : [];
|
|
22
|
+
}), f = ({
|
|
23
|
+
markdownFiles: t,
|
|
24
|
+
defaultOptions: e,
|
|
25
|
+
filesPath: n
|
|
26
|
+
}) => ({
|
|
27
|
+
getRoutes: () => x(t, n, e)
|
|
94
28
|
});
|
|
95
29
|
export {
|
|
96
|
-
|
|
30
|
+
f as markdownPlugin
|
|
97
31
|
};
|
|
98
32
|
//# sourceMappingURL=zudoku.plugin-markdown.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zudoku.plugin-markdown.js","sources":["../src/lib/plugins/markdown/
|
|
1
|
+
{"version":3,"file":"zudoku.plugin-markdown.js","sources":["../src/lib/plugins/markdown/generateRoutes.tsx","../src/lib/plugins/markdown/index.tsx"],"sourcesContent":["import { type RouteObject } from \"react-router-dom\";\n\nimport {\n MarkdownPluginDefaultOptions,\n MarkdownPluginOptions,\n} from \"./index.js\";\n\nexport const generateRoutes = (\n markdownFiles: MarkdownPluginOptions[\"markdownFiles\"],\n filesPath: string,\n defaultOptions?: MarkdownPluginDefaultOptions,\n): RouteObject[] =>\n Object.entries(markdownFiles).flatMap(([file, importPromise]) => {\n let rootDir = filesPath.split(\"**\")[0];\n rootDir = rootDir.replace(\"/**\", \"/\");\n const re = new RegExp(`^${rootDir}(.*).mdx?`);\n const match = file.match(re);\n const fsPath = match?.at(1);\n\n if (!fsPath) return [];\n\n return {\n path: fsPath,\n lazy: async () => {\n const { MdxPage } = await import(\"./MdxPage.js\");\n const { default: Component, ...props } = await importPromise();\n return {\n element: (\n <MdxPage\n mdxComponent={Component}\n {...props}\n defaultOptions={defaultOptions}\n />\n ),\n };\n },\n } satisfies RouteObject;\n });\n","import type { Toc } from \"@stefanprobst/rehype-extract-toc\";\nimport type { MDXProps } from \"mdx/types.js\";\nimport type { DevPortalPlugin } from \"../../core/plugins.js\";\nimport { generateRoutes } from \"./generateRoutes.js\";\n\nexport type MarkdownPluginOptions = {\n markdownFiles: Record<string, () => Promise<MDXImport>>;\n defaultOptions?: MarkdownPluginDefaultOptions;\n filesPath: string;\n};\nexport type MarkdownPluginDefaultOptions = Pick<\n Frontmatter,\n \"toc\" | \"disablePager\"\n>;\n\nexport type Frontmatter = {\n title?: string;\n description?: string;\n category?: string;\n toc?: boolean;\n disablePager?: boolean;\n};\n\nexport type MDXImport = {\n tableOfContents: Toc;\n frontmatter: Frontmatter;\n default: (props: MDXProps) => JSX.Element;\n};\n\nexport const markdownPlugin = ({\n markdownFiles,\n defaultOptions,\n filesPath,\n}: MarkdownPluginOptions): DevPortalPlugin => ({\n getRoutes: () => generateRoutes(markdownFiles, filesPath, defaultOptions),\n});\n"],"names":["generateRoutes","markdownFiles","filesPath","defaultOptions","file","importPromise","rootDir","re","match","fsPath","MdxPage","Component","props","jsx","markdownPlugin"],"mappings":";AAOO,MAAMA,IAAiB,CAC5BC,GACAC,GACAC,MAEA,OAAO,QAAQF,CAAa,EAAE,QAAQ,CAAC,CAACG,GAAMC,CAAa,MAAM;AAC/D,MAAIC,IAAUJ,EAAU,MAAM,IAAI,EAAE,CAAC;AAC3B,EAAAI,IAAAA,EAAQ,QAAQ,OAAO,GAAG;AACpC,QAAMC,IAAK,IAAI,OAAO,IAAID,CAAO,WAAW,GACtCE,IAAQJ,EAAK,MAAMG,CAAE,GACrBE,IAASD,KAAA,gBAAAA,EAAO,GAAG;AAErB,SAACC,IAEE;AAAA,IACL,MAAMA;AAAA,IACN,MAAM,YAAY;AAChB,YAAM,EAAE,SAAAC,EAAA,IAAY,MAAM,OAAO,uBAAc,GACzC,EAAE,SAASC,GAAW,GAAGC,EAAM,IAAI,MAAMP;AACxC,aAAA;AAAA,QACL,SACEQ,gBAAAA,EAAA;AAAA,UAACH;AAAA,UAAA;AAAA,YACC,cAAcC;AAAA,YACb,GAAGC;AAAA,YACJ,gBAAAT;AAAA,UAAA;AAAA,QACF;AAAA,MAAA;AAAA,IAGN;AAAA,EAAA,IAhBkB;AAkBtB,CAAC,GCRUW,IAAiB,CAAC;AAAA,EAC7B,eAAAb;AAAA,EACA,gBAAAE;AAAA,EACA,WAAAD;AACF,OAA+C;AAAA,EAC7C,WAAW,MAAMF,EAAeC,GAAeC,GAAWC,CAAc;AAC1E;"}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import "./jsx-runtime-B6kdoens.js";
|
|
2
|
-
import { o as
|
|
2
|
+
import { o as u } from "./index-BlJ2rj99.js";
|
|
3
3
|
import "./urql-YhcsXYy8.js";
|
|
4
|
-
import "./ZudokuContext-
|
|
4
|
+
import "./ZudokuContext-cr-pTRY1.js";
|
|
5
5
|
import "lucide-react";
|
|
6
6
|
import "zudoku/openapi-worker";
|
|
7
|
-
import "./index-
|
|
7
|
+
import "./index-Dolisrci.js";
|
|
8
8
|
import "./ErrorPage-CsZAN_za.js";
|
|
9
9
|
import "./Markdown-DapSf3wG.js";
|
|
10
|
+
import "./joinPath-B7kNnUX4.js";
|
|
10
11
|
import "./router-D2p7Olpn.js";
|
|
11
12
|
import "./index-BG0g4WW0.js";
|
|
12
13
|
export {
|
|
13
|
-
|
|
14
|
+
u as openApiPlugin
|
|
14
15
|
};
|
|
15
16
|
//# sourceMappingURL=zudoku.plugin-openapi.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zudoku.plugin-openapi.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"zudoku.plugin-openapi.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;"}
|
package/package.json
CHANGED
package/src/app/entry.client.tsx
CHANGED
|
@@ -20,10 +20,8 @@ if (root.childElementCount > 0) {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
async function hydrateLazyRoutes(routes: RouteObject[]) {
|
|
23
|
-
const path = window.location.pathname;
|
|
24
|
-
const lazyMatches = matchRoutes(routes, path
|
|
25
|
-
(m) => m.route.lazy,
|
|
26
|
-
);
|
|
23
|
+
const path = window.location.pathname.slice(config.basePath?.length ?? 0);
|
|
24
|
+
const lazyMatches = matchRoutes(routes, path)?.filter((m) => m.route.lazy);
|
|
27
25
|
|
|
28
26
|
if (lazyMatches?.length) {
|
|
29
27
|
await Promise.all(
|
package/src/app/entry.server.tsx
CHANGED
|
@@ -96,10 +96,6 @@ export const render = async ({
|
|
|
96
96
|
|
|
97
97
|
const [htmlStart, htmlEnd] = template.split("<!--app-html-->");
|
|
98
98
|
|
|
99
|
-
if (!htmlStart) {
|
|
100
|
-
throw new Error("No <!--app-html--> found in template");
|
|
101
|
-
}
|
|
102
|
-
|
|
103
99
|
response.write(
|
|
104
100
|
htmlStart.replace(
|
|
105
101
|
"<!--app-helmet-->",
|
package/src/app/main.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type RouteObject } from "react-router-dom";
|
|
1
|
+
import { redirect, type RouteObject } from "react-router-dom";
|
|
2
2
|
import { configuredApiKeysPlugin } from "virtual:zudoku-api-keys-plugin";
|
|
3
3
|
import { configuredApiPlugins } from "virtual:zudoku-api-plugins";
|
|
4
4
|
import { configuredAuthProvider } from "virtual:zudoku-auth";
|
|
@@ -11,7 +11,9 @@ import { isNavigationPlugin } from "zudoku/internal";
|
|
|
11
11
|
import { customPagePlugin } from "zudoku/plugins/custom-page";
|
|
12
12
|
import { inkeepSearchPlugin } from "zudoku/plugins/search-inkeep";
|
|
13
13
|
import type { ZudokuConfig } from "../config/config.js";
|
|
14
|
+
import { traverseSidebar } from "../lib/components/navigation/utils.js";
|
|
14
15
|
import type { ZudokuContextOptions } from "../lib/core/DevPortalContext.js";
|
|
16
|
+
import { joinPath } from "../lib/util/joinPath.js";
|
|
15
17
|
|
|
16
18
|
export const convertZudokuConfigToOptions = (
|
|
17
19
|
config: ZudokuConfig,
|
|
@@ -67,7 +69,9 @@ export const convertZudokuConfigToOptions = (
|
|
|
67
69
|
};
|
|
68
70
|
};
|
|
69
71
|
|
|
70
|
-
export const
|
|
72
|
+
export const getRoutesByConfig = (config: ZudokuConfig): RouteObject[] => {
|
|
73
|
+
const options = convertZudokuConfigToOptions(config);
|
|
74
|
+
|
|
71
75
|
const allPlugins = [
|
|
72
76
|
...(options.plugins ? options.plugins : []),
|
|
73
77
|
...(options.authentication?.getAuthenticationPlugin
|
|
@@ -75,8 +79,27 @@ export const getRoutesByOptions = (options: ZudokuContextOptions) => {
|
|
|
75
79
|
: []),
|
|
76
80
|
];
|
|
77
81
|
|
|
82
|
+
const topNavRedirects =
|
|
83
|
+
options.topNavigation?.flatMap((topNavItem) => {
|
|
84
|
+
if (!options.sidebars?.[topNavItem.id]) return [];
|
|
85
|
+
|
|
86
|
+
const first =
|
|
87
|
+
topNavItem.default ??
|
|
88
|
+
traverseSidebar(options.sidebars[topNavItem.id], (item) => {
|
|
89
|
+
if (item.type === "doc") return joinPath(topNavItem.id, item.id);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
if (!first) return [];
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
path: topNavItem.id,
|
|
96
|
+
loader: () => redirect(joinPath(first)),
|
|
97
|
+
} satisfies RouteObject;
|
|
98
|
+
}) ?? [];
|
|
99
|
+
|
|
78
100
|
const routes = allPlugins
|
|
79
101
|
.flatMap((plugin) => (isNavigationPlugin(plugin) ? plugin.getRoutes() : []))
|
|
102
|
+
.concat(topNavRedirects)
|
|
80
103
|
.concat({
|
|
81
104
|
path: "*",
|
|
82
105
|
loader: () => {
|
|
@@ -84,13 +107,6 @@ export const getRoutesByOptions = (options: ZudokuContextOptions) => {
|
|
|
84
107
|
},
|
|
85
108
|
});
|
|
86
109
|
|
|
87
|
-
return routes;
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
export const getRoutesByConfig = (config: ZudokuConfig): RouteObject[] => {
|
|
91
|
-
const options = convertZudokuConfigToOptions(config);
|
|
92
|
-
const routes = getRoutesByOptions(options);
|
|
93
|
-
|
|
94
110
|
return [
|
|
95
111
|
{
|
|
96
112
|
element: (
|
package/src/app/standalone.tsx
CHANGED
|
@@ -16,7 +16,7 @@ if (!root) {
|
|
|
16
16
|
themeToggle();
|
|
17
17
|
|
|
18
18
|
const apiUrl = root.getAttribute("data-api-url");
|
|
19
|
-
const pageTitle = document.getElementsByTagName("title")[0]
|
|
19
|
+
const pageTitle = document.getElementsByTagName("title")[0].innerText;
|
|
20
20
|
const logoUrl = root.getAttribute("data-logo-url");
|
|
21
21
|
|
|
22
22
|
// IMPORTANT: This component must not contain tailwind classes
|
|
@@ -70,22 +70,14 @@ export const Header = memo(function HeaderInner() {
|
|
|
70
70
|
{page?.logo && (
|
|
71
71
|
<>
|
|
72
72
|
<img
|
|
73
|
-
src={
|
|
74
|
-
/https?:\/\//.test(page.logo.src.light)
|
|
75
|
-
? page.logo.src.light
|
|
76
|
-
: import.meta.env.BASE_URL + page.logo.src.light
|
|
77
|
-
}
|
|
73
|
+
src={page.logo.src.light}
|
|
78
74
|
alt={page.logo.alt ?? page.pageTitle}
|
|
79
75
|
style={{ width: page.logo.width }}
|
|
80
76
|
className={cn("h-10", isDark && "hidden")}
|
|
81
77
|
loading="lazy"
|
|
82
78
|
/>
|
|
83
79
|
<img
|
|
84
|
-
src={
|
|
85
|
-
/https?:\/\//.test(page.logo.src.dark)
|
|
86
|
-
? page.logo.src.dark
|
|
87
|
-
: import.meta.env.BASE_URL + page.logo.src.dark
|
|
88
|
-
}
|
|
80
|
+
src={page.logo.src.dark}
|
|
89
81
|
alt={page.logo.alt ?? page.pageTitle}
|
|
90
82
|
style={{ width: page.logo.width }}
|
|
91
83
|
className={cn("h-10", !isDark && "hidden")}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { cx } from "class-variance-authority";
|
|
2
2
|
import { NavLink } from "react-router-dom";
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import { joinPath } from "../util/joinPath.js";
|
|
6
|
-
import { useCurrentNavigation, useZudoku } from "./context/ZudokuContext.js";
|
|
7
|
-
import { traverseSidebar } from "./navigation/utils.js";
|
|
4
|
+
import { useZudoku } from "./context/ZudokuContext.js";
|
|
8
5
|
|
|
9
6
|
export const TopNavigation = () => {
|
|
10
7
|
const { topNavigation } = useZudoku();
|
|
@@ -18,52 +15,23 @@ export const TopNavigation = () => {
|
|
|
18
15
|
<nav className="hidden lg:block border-b text-sm px-12 h-[--top-nav-height]">
|
|
19
16
|
<ul className="flex flex-row items-center gap-8">
|
|
20
17
|
{topNavigation.map((item) => (
|
|
21
|
-
<li key={item.
|
|
22
|
-
<
|
|
18
|
+
<li key={item.label}>
|
|
19
|
+
<NavLink
|
|
20
|
+
className={({ isActive }) =>
|
|
21
|
+
cx(
|
|
22
|
+
"block py-3.5 font-medium -mb-px border-b-2",
|
|
23
|
+
isActive
|
|
24
|
+
? "border-primary text-foreground"
|
|
25
|
+
: "border-transparent text-foreground/75 hover:text-foreground hover:border-accent-foreground/25",
|
|
26
|
+
)
|
|
27
|
+
}
|
|
28
|
+
to={item.id}
|
|
29
|
+
>
|
|
30
|
+
{item.label}
|
|
31
|
+
</NavLink>
|
|
23
32
|
</li>
|
|
24
33
|
))}
|
|
25
34
|
</ul>
|
|
26
35
|
</nav>
|
|
27
36
|
);
|
|
28
37
|
};
|
|
29
|
-
|
|
30
|
-
const TopNavItem = ({ id, label, default: defaultLink }: TopNavigationItem) => {
|
|
31
|
-
const { sidebars } = useZudoku();
|
|
32
|
-
const nav = useCurrentNavigation();
|
|
33
|
-
const currentSidebar = sidebars[id];
|
|
34
|
-
|
|
35
|
-
// TODO: This is a bit of a hack to get the first link in the sidebar
|
|
36
|
-
// We should really process this when we load the config so we can validate
|
|
37
|
-
// that the sidebar is actually set. In this case we just fall back to linking
|
|
38
|
-
// to the id if we can't resolve a sidebar.
|
|
39
|
-
const first =
|
|
40
|
-
defaultLink ??
|
|
41
|
-
(currentSidebar
|
|
42
|
-
? traverseSidebar(currentSidebar, (item) => {
|
|
43
|
-
if (item.type === "doc") return joinPath(item.id);
|
|
44
|
-
})
|
|
45
|
-
: joinPath(id));
|
|
46
|
-
|
|
47
|
-
if (!first) {
|
|
48
|
-
throw new Error(
|
|
49
|
-
`No links found in top navigation for top navigation '${id}'. Check that the sidebar isn't empty or that a default link set.`,
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Manually set the active sidebar based on our logic of what is active
|
|
54
|
-
const isActive = nav.data.topNavItem?.id === id;
|
|
55
|
-
|
|
56
|
-
return (
|
|
57
|
-
<NavLink
|
|
58
|
-
className={cx(
|
|
59
|
-
"block py-3.5 font-medium -mb-px border-b-2",
|
|
60
|
-
isActive
|
|
61
|
-
? "border-primary text-foreground"
|
|
62
|
-
: "border-transparent text-foreground/75 hover:text-foreground hover:border-accent-foreground/25",
|
|
63
|
-
)}
|
|
64
|
-
to={first}
|
|
65
|
-
>
|
|
66
|
-
{label}
|
|
67
|
-
</NavLink>
|
|
68
|
-
);
|
|
69
|
-
};
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { useQuery, useSuspenseQuery } from "@tanstack/react-query";
|
|
2
2
|
import { createContext, useContext } from "react";
|
|
3
3
|
import { useLocation } from "react-router-dom";
|
|
4
|
-
import { SidebarItem } from "../../../config/validators/SidebarSchema.js";
|
|
5
|
-
import { TopNavigationItem } from "../../../config/validators/validate.js";
|
|
6
4
|
import { DevPortalContext } from "../../core/DevPortalContext.js";
|
|
7
|
-
import { joinPath } from "../../util/joinPath.js";
|
|
8
|
-
import { traverseSidebar } from "../navigation/utils.js";
|
|
9
5
|
|
|
10
6
|
export const ZudokuReactContext = createContext<DevPortalContext | undefined>(
|
|
11
7
|
undefined,
|
|
@@ -29,44 +25,34 @@ export const useApiIdentities = () => {
|
|
|
29
25
|
});
|
|
30
26
|
};
|
|
31
27
|
|
|
32
|
-
export const
|
|
33
|
-
const {
|
|
28
|
+
export const useTopNavigationItem = () => {
|
|
29
|
+
const { topNavigation } = useZudoku();
|
|
34
30
|
const location = useLocation();
|
|
35
31
|
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
const itemId =
|
|
39
|
-
item.type === "doc"
|
|
40
|
-
? joinPath(item.id)
|
|
41
|
-
: item.type === "category" && item.link
|
|
42
|
-
? joinPath(item.link.id)
|
|
43
|
-
: undefined;
|
|
32
|
+
const firstPart = location.pathname.split("/").at(1);
|
|
33
|
+
if (!firstPart) return;
|
|
44
34
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
});
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
);
|
|
35
|
+
return topNavigation.find((item) => item.id === firstPart);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const useNavigation = () => {
|
|
39
|
+
const { getPluginSidebar, sidebars } = useZudoku();
|
|
40
|
+
const navItem = useTopNavigationItem();
|
|
41
|
+
const path = navItem?.id;
|
|
42
|
+
const currentSidebar = path ? (sidebars[path] ?? []) : [];
|
|
43
|
+
const location = useLocation();
|
|
53
44
|
|
|
54
45
|
return useSuspenseQuery({
|
|
55
46
|
queryFn: async () => {
|
|
56
|
-
const pluginSidebar =
|
|
47
|
+
const pluginSidebar = path
|
|
48
|
+
? await getPluginSidebar(path)
|
|
49
|
+
: await getPluginSidebar(location.pathname);
|
|
57
50
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
} = {
|
|
62
|
-
sidebar: [
|
|
63
|
-
...(currentSidebarItem ? currentSidebarItem[1] : []),
|
|
64
|
-
...pluginSidebar,
|
|
65
|
-
],
|
|
66
|
-
topNavItem: currentTopNavItem,
|
|
51
|
+
return {
|
|
52
|
+
items: [...currentSidebar, ...pluginSidebar],
|
|
53
|
+
currentTopNavItem: navItem,
|
|
67
54
|
};
|
|
68
|
-
return result;
|
|
69
55
|
},
|
|
70
|
-
queryKey: ["navigation",
|
|
56
|
+
queryKey: ["navigation", path],
|
|
71
57
|
});
|
|
72
58
|
};
|
|
@@ -2,23 +2,23 @@ import { useRef } from "react";
|
|
|
2
2
|
|
|
3
3
|
import { VisuallyHidden } from "@radix-ui/react-visually-hidden";
|
|
4
4
|
import { DrawerContent, DrawerTitle } from "../../ui/Drawer.js";
|
|
5
|
-
import {
|
|
5
|
+
import { useNavigation } from "../context/ZudokuContext.js";
|
|
6
6
|
import { Slotlet } from "../SlotletProvider.js";
|
|
7
7
|
import { SidebarItem } from "./SidebarItem.js";
|
|
8
8
|
import { SidebarWrapper } from "./SidebarWrapper.js";
|
|
9
9
|
|
|
10
10
|
export const Sidebar = () => {
|
|
11
11
|
const navRef = useRef<HTMLDivElement | null>(null);
|
|
12
|
-
const navigation =
|
|
12
|
+
const navigation = useNavigation();
|
|
13
13
|
|
|
14
14
|
return (
|
|
15
15
|
<>
|
|
16
16
|
<SidebarWrapper
|
|
17
17
|
ref={navRef}
|
|
18
|
-
pushMainContent={navigation.data.
|
|
18
|
+
pushMainContent={navigation.data.items.length > 0}
|
|
19
19
|
>
|
|
20
20
|
<Slotlet name="zudoku-before-navigation" />
|
|
21
|
-
{navigation.data.
|
|
21
|
+
{navigation.data.items.map((item) => (
|
|
22
22
|
<SidebarItem key={item.label} item={item} />
|
|
23
23
|
))}
|
|
24
24
|
<Slotlet name="zudoku-after-navigation" />
|
|
@@ -30,7 +30,7 @@ export const Sidebar = () => {
|
|
|
30
30
|
<VisuallyHidden>
|
|
31
31
|
<DrawerTitle>Sidebar</DrawerTitle>
|
|
32
32
|
</VisuallyHidden>
|
|
33
|
-
{navigation.data.
|
|
33
|
+
{navigation.data.items.map((item) => (
|
|
34
34
|
<SidebarItem key={item.label} item={item} />
|
|
35
35
|
))}
|
|
36
36
|
</DrawerContent>
|
|
@@ -5,6 +5,7 @@ import { NavLink } from "react-router-dom";
|
|
|
5
5
|
import type { SidebarItemCategory } from "../../../config/validators/SidebarSchema.js";
|
|
6
6
|
import { cn } from "../../util/cn.js";
|
|
7
7
|
import { joinPath } from "../../util/joinPath.js";
|
|
8
|
+
import { useTopNavigationItem } from "../context/ZudokuContext.js";
|
|
8
9
|
import { navigationListItem, SidebarItem } from "./SidebarItem.js";
|
|
9
10
|
import { useIsCategoryOpen } from "./utils.js";
|
|
10
11
|
|
|
@@ -15,6 +16,7 @@ export const SidebarCategory = ({
|
|
|
15
16
|
category: SidebarItemCategory;
|
|
16
17
|
level: number;
|
|
17
18
|
}) => {
|
|
19
|
+
const topNavItem = useTopNavigationItem();
|
|
18
20
|
const isCategoryOpen = useIsCategoryOpen(category);
|
|
19
21
|
const [hasInteracted, setHasInteracted] = useState(false);
|
|
20
22
|
|
|
@@ -77,7 +79,7 @@ export const SidebarCategory = ({
|
|
|
77
79
|
)}
|
|
78
80
|
{category.link?.type === "doc" ? (
|
|
79
81
|
<NavLink
|
|
80
|
-
to={joinPath(category.link.id)}
|
|
82
|
+
to={joinPath(topNavItem?.id, category.link.id)}
|
|
81
83
|
className="flex-1"
|
|
82
84
|
onClick={() => setHasInteracted(true)}
|
|
83
85
|
>
|
|
@@ -7,6 +7,7 @@ import { cn } from "../../util/cn.js";
|
|
|
7
7
|
import { joinPath } from "../../util/joinPath.js";
|
|
8
8
|
import { AnchorLink } from "../AnchorLink.js";
|
|
9
9
|
import { useViewportAnchor } from "../context/ViewportAnchorContext.js";
|
|
10
|
+
import { useTopNavigationItem } from "../context/ZudokuContext.js";
|
|
10
11
|
import { SidebarBadge } from "./SidebarBadge.js";
|
|
11
12
|
import { SidebarCategory } from "./SidebarCategory.js";
|
|
12
13
|
|
|
@@ -39,6 +40,7 @@ export const SidebarItem = ({
|
|
|
39
40
|
basePath?: string;
|
|
40
41
|
level?: number;
|
|
41
42
|
}) => {
|
|
43
|
+
const topNavItem = useTopNavigationItem();
|
|
42
44
|
const { activeAnchor } = useViewportAnchor();
|
|
43
45
|
const [searchParams] = useSearchParams();
|
|
44
46
|
|
|
@@ -51,7 +53,7 @@ export const SidebarItem = ({
|
|
|
51
53
|
className={({ isActive }) =>
|
|
52
54
|
navigationListItem({ isActive, isTopLevel: level === 0 })
|
|
53
55
|
}
|
|
54
|
-
to={joinPath(item.id)}
|
|
56
|
+
to={joinPath(topNavItem?.id, item.id)}
|
|
55
57
|
>
|
|
56
58
|
{item.icon && <item.icon size={16} className="align-[-0.125em]" />}
|
|
57
59
|
{item.badge ? (
|