@xyd-js/cli 0.1.0-xyd.18 → 0.1.0-xyd.2
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/dist/index.d.ts +1 -0
- package/.cli/dist/index.js +12417 -0
- package/.cli/host/.react-router/types/app/+types/root.ts +40 -0
- package/.cli/host/app/root.tsx +23 -0
- package/.cli/host/app/routes.ts +5 -0
- package/.cli/host/node_modules/.vite/deps/@mdx-js_mdx.js +81 -0
- package/.cli/host/node_modules/.vite/deps/@mdx-js_mdx.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/@mdx-js_rollup.js +4003 -0
- package/.cli/host/node_modules/.vite/deps/@mdx-js_rollup.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/@radix-ui_react-icons.js +7531 -0
- package/.cli/host/node_modules/.vite/deps/@radix-ui_react-icons.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/@radix-ui_react-tabs.js +917 -0
- package/.cli/host/node_modules/.vite/deps/@radix-ui_react-tabs.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/_metadata.json +157 -0
- package/.cli/host/node_modules/.vite/deps/chunk-2TUXWMP5.js +46 -0
- package/.cli/host/node_modules/.vite/deps/chunk-2TUXWMP5.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/chunk-DNIFH2K7.js +3461 -0
- package/.cli/host/node_modules/.vite/deps/chunk-DNIFH2K7.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/chunk-ERHH4CDL.js +23875 -0
- package/.cli/host/node_modules/.vite/deps/chunk-ERHH4CDL.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/chunk-ETJV5QNK.js +27 -0
- package/.cli/host/node_modules/.vite/deps/chunk-ETJV5QNK.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/chunk-GPEJJ3KZ.js +1906 -0
- package/.cli/host/node_modules/.vite/deps/chunk-GPEJJ3KZ.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/chunk-IVP26VTC.js +21 -0
- package/.cli/host/node_modules/.vite/deps/chunk-IVP26VTC.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/chunk-MJUUSK53.js +894 -0
- package/.cli/host/node_modules/.vite/deps/chunk-MJUUSK53.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/chunk-NHN7DW4J.js +928 -0
- package/.cli/host/node_modules/.vite/deps/chunk-NHN7DW4J.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/chunk-OO6QDGMA.js +10609 -0
- package/.cli/host/node_modules/.vite/deps/chunk-OO6QDGMA.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/chunk-OUN4SSIE.js +205 -0
- package/.cli/host/node_modules/.vite/deps/chunk-OUN4SSIE.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/chunk-TKNG6GUJ.js +894 -0
- package/.cli/host/node_modules/.vite/deps/chunk-TKNG6GUJ.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/chunk-TM4FKLNO.js +21628 -0
- package/.cli/host/node_modules/.vite/deps/chunk-TM4FKLNO.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/chunk-V2IF7L2E.js +12 -0
- package/.cli/host/node_modules/.vite/deps/chunk-V2IF7L2E.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/gray-matter.js +3492 -0
- package/.cli/host/node_modules/.vite/deps/gray-matter.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/lucide-react.js +34742 -0
- package/.cli/host/node_modules/.vite/deps/lucide-react.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/package.json +3 -0
- package/.cli/host/node_modules/.vite/deps/react-dom.js +7 -0
- package/.cli/host/node_modules/.vite/deps/react-dom.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/react-dom_client.js +39 -0
- package/.cli/host/node_modules/.vite/deps/react-dom_client.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/react-router.js +243 -0
- package/.cli/host/node_modules/.vite/deps/react-router.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/react-router_dom.js +212 -0
- package/.cli/host/node_modules/.vite/deps/react-router_dom.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/react.js +6 -0
- package/.cli/host/node_modules/.vite/deps/react.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/react_jsx-dev-runtime.js +913 -0
- package/.cli/host/node_modules/.vite/deps/react_jsx-dev-runtime.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/react_jsx-runtime.js +7 -0
- package/.cli/host/node_modules/.vite/deps/react_jsx-runtime.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/remark-frontmatter.js +428 -0
- package/.cli/host/node_modules/.vite/deps/remark-frontmatter.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/remark-gfm.js +3122 -0
- package/.cli/host/node_modules/.vite/deps/remark-gfm.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/remark-mdx-frontmatter.js +10482 -0
- package/.cli/host/node_modules/.vite/deps/remark-mdx-frontmatter.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/unist-util-visit.js +14 -0
- package/.cli/host/node_modules/.vite/deps/unist-util-visit.js.map +7 -0
- package/.cli/host/node_modules/.vite/deps/vfile.js +8 -0
- package/.cli/host/node_modules/.vite/deps/vfile.js.map +7 -0
- package/.cli/host/package.json +43 -0
- package/.cli/host/postcss.config.cjs +5 -0
- package/.cli/host/react-router.config.ts +8 -0
- package/.cli/host/tsconfig.json +22 -0
- package/.cli/host/vite.config.ts +9 -0
- package/.cli/plugins/xyd-plugin-zero/src/pages/api-reference.tsx +406 -0
- package/.cli/plugins/xyd-plugin-zero/src/pages/docs.tsx +166 -0
- package/.cli/plugins/xyd-plugin-zero/src/pages/root.tsx +37 -0
- package/bin.js +3 -0
- package/package.json +15 -13
- package/postinstall.js +0 -15
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"private": true,
|
|
3
|
+
"name": "@xyd-js/documan-host",
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {},
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"@xyd-js/atlas": "workspace:*",
|
|
9
|
+
"@xyd-js/core": "workspace:*",
|
|
10
|
+
"@xyd-js/content": "workspace:*",
|
|
11
|
+
"@xyd-js/framework": "workspace:*",
|
|
12
|
+
"@xyd-js/gql": "workspace:*",
|
|
13
|
+
"@xyd-js/openapi": "workspace:*",
|
|
14
|
+
"@xyd-js/uniform": "workspace:*",
|
|
15
|
+
"@xyd-js/theme-gusto": "workspace:*",
|
|
16
|
+
"@react-router/node": "^7.1.1",
|
|
17
|
+
"@react-router/serve": "^7.1.1",
|
|
18
|
+
"codehike": "^1.0.3",
|
|
19
|
+
"express": "^4.21.1",
|
|
20
|
+
"isbot": "^5.1.17",
|
|
21
|
+
"react": "^18.3.1",
|
|
22
|
+
"react-dom": "^18.3.1",
|
|
23
|
+
"react-router": "^7.1.1",
|
|
24
|
+
"remark-frontmatter": "^5.0.0",
|
|
25
|
+
"remark-gfm": "^4.0.0",
|
|
26
|
+
"remark-mdx-frontmatter": "^5.0.0",
|
|
27
|
+
"typescript": "^5.6.3",
|
|
28
|
+
"vfile": "^6.0.3",
|
|
29
|
+
"yaml": "^2.6.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/node": "^22.7.5",
|
|
33
|
+
"@types/react-dom": "^18.3.1",
|
|
34
|
+
"@mdx-js/rollup": "^3.1.0",
|
|
35
|
+
"@types/react": "^18.3.9",
|
|
36
|
+
"@vitejs/plugin-react": "^4.3.2",
|
|
37
|
+
"autoprefixer": "^10.4.20",
|
|
38
|
+
"postcss": "^8.4.47",
|
|
39
|
+
"typescript": "^5.6.2",
|
|
40
|
+
"vite": "^5.4.9",
|
|
41
|
+
"vite-tsconfig-paths": "^5.0.1"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"lib": [
|
|
7
|
+
"ES2020",
|
|
8
|
+
"DOM",
|
|
9
|
+
"DOM.Iterable"
|
|
10
|
+
],
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"moduleResolution": "bundler",
|
|
13
|
+
"resolveJsonModule": true,
|
|
14
|
+
"isolatedModules": true,
|
|
15
|
+
"noEmit": false,
|
|
16
|
+
"strict": true,
|
|
17
|
+
"noUnusedLocals": true,
|
|
18
|
+
"noUnusedParameters": true,
|
|
19
|
+
"noFallthroughCasesInSwitch": true,
|
|
20
|
+
"jsx": "react-jsx"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import {promises as fs} from "fs";
|
|
3
|
+
|
|
4
|
+
import React, {useContext} from "react";
|
|
5
|
+
import {redirect, UNSAFE_DataRouterStateContext} from "react-router";
|
|
6
|
+
import remarkFrontmatter from "remark-frontmatter";
|
|
7
|
+
import remarkMdxFrontmatter from "remark-mdx-frontmatter";
|
|
8
|
+
import remarkGfm from "remark-gfm";
|
|
9
|
+
import {parse} from "codehike";
|
|
10
|
+
import {visit} from "unist-util-visit";
|
|
11
|
+
import {recmaCodeHike, remarkCodeHike} from "codehike/mdx";
|
|
12
|
+
import {compile as mdxCompile} from "@mdx-js/mdx";
|
|
13
|
+
|
|
14
|
+
import {PageFrontMatter} from "@xyd-js/core";
|
|
15
|
+
import {renderoll} from "@xyd-js/foo/renderoll";
|
|
16
|
+
import {
|
|
17
|
+
AtlasLazy
|
|
18
|
+
} from "@xyd-js/atlas";
|
|
19
|
+
import getContentComponents from "@xyd-js/components/content";
|
|
20
|
+
import {mapSettingsToProps} from "@xyd-js/framework/hydration";
|
|
21
|
+
import {Framework} from "@xyd-js/framework/react";
|
|
22
|
+
import type {FwSidebarGroupProps} from "@xyd-js/framework/react";
|
|
23
|
+
|
|
24
|
+
import Theme from "virtual:xyd-theme" // TODO: for some reasons this cannot be hydrated by react-router
|
|
25
|
+
import settings from 'virtual:xyd-settings';
|
|
26
|
+
|
|
27
|
+
import "virtual:xyd-theme/index.css"
|
|
28
|
+
import "virtual:xyd-theme-override/index.css"
|
|
29
|
+
|
|
30
|
+
const contentComponents = getContentComponents()
|
|
31
|
+
const ComponentContent = contentComponents.Content
|
|
32
|
+
|
|
33
|
+
// since unist does not support heading level > 6, we need to normalize them
|
|
34
|
+
function normalizeCustomHeadings() {
|
|
35
|
+
return (tree: any) => {
|
|
36
|
+
visit(tree, 'paragraph', (node, index, parent) => {
|
|
37
|
+
if (!node.children[0].value) {
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
const match = node.children[0] && node.children[0].value.match(/^(#+)\s+(.*)/);
|
|
41
|
+
if (match) {
|
|
42
|
+
const level = match[1].length;
|
|
43
|
+
const text = match[2];
|
|
44
|
+
if (level > 6) {
|
|
45
|
+
// Create a new heading node with depth 6
|
|
46
|
+
const headingNode = {
|
|
47
|
+
type: 'heading',
|
|
48
|
+
depth: level,
|
|
49
|
+
children: [{type: 'text', value: text}]
|
|
50
|
+
};
|
|
51
|
+
// Replace the paragraph node with the new heading node
|
|
52
|
+
//@ts-ignore
|
|
53
|
+
parent.children[index] = headingNode;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const codeHikeOptions = {
|
|
61
|
+
lineNumbers: true,
|
|
62
|
+
showCopyButton: true,
|
|
63
|
+
autoImport: true,
|
|
64
|
+
components: {},
|
|
65
|
+
// syntaxHighlighting: { // TODO: !!! FROM SETTINGS !!! wait for rr7 rsc ??
|
|
66
|
+
// theme: "github-dark",
|
|
67
|
+
// },
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// TODO: map every file and merge them or load via client-side ?
|
|
71
|
+
async function compileBySlug(slug: string) {
|
|
72
|
+
// TODO: cwd ?
|
|
73
|
+
let filePath = path.join(process.cwd(), `${slug}.md`)
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
await fs.access(filePath)
|
|
77
|
+
} catch (_) {
|
|
78
|
+
filePath = path.join(process.cwd(), `${slug}.mdx`)
|
|
79
|
+
|
|
80
|
+
await fs.access(filePath)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
84
|
+
|
|
85
|
+
return await compile(content)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async function compile(content: string): Promise<string> {
|
|
89
|
+
const compiled = await mdxCompile(content, {
|
|
90
|
+
remarkPlugins: [
|
|
91
|
+
normalizeCustomHeadings,
|
|
92
|
+
[remarkCodeHike, codeHikeOptions],
|
|
93
|
+
remarkFrontmatter,
|
|
94
|
+
remarkMdxFrontmatter,
|
|
95
|
+
remarkGfm
|
|
96
|
+
],
|
|
97
|
+
rehypePlugins: [],
|
|
98
|
+
recmaPlugins: [
|
|
99
|
+
[recmaCodeHike, codeHikeOptions]
|
|
100
|
+
],
|
|
101
|
+
outputFormat: 'function-body',
|
|
102
|
+
development: false,
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
return String(compiled)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
interface loaderData {
|
|
109
|
+
sidebarGroups: FwSidebarGroupProps[]
|
|
110
|
+
toc: PageFrontMatter
|
|
111
|
+
slug: string
|
|
112
|
+
code: string
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function getPathname(url: string) {
|
|
116
|
+
const parsedUrl = new URL(url);
|
|
117
|
+
return parsedUrl.pathname.replace(/^\//, '');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// TODO: fix any
|
|
121
|
+
function findFirstUrl(items: any): string {
|
|
122
|
+
const queue = [...items];
|
|
123
|
+
|
|
124
|
+
while (queue.length > 0) {
|
|
125
|
+
const item = queue.shift();
|
|
126
|
+
|
|
127
|
+
if (item.href) {
|
|
128
|
+
return item.href;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (item.items) {
|
|
132
|
+
queue.push(...item.items);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return "";
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// TODO: fix any
|
|
140
|
+
export async function loader({request}: { request: any }) {
|
|
141
|
+
const slug = getPathname(request.url)
|
|
142
|
+
|
|
143
|
+
let code = ""
|
|
144
|
+
let error: any
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
code = await compileBySlug(slug)
|
|
148
|
+
} catch (e) {
|
|
149
|
+
error = e
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const {groups: sidebarGroups} = await mapSettingsToProps(
|
|
153
|
+
settings,
|
|
154
|
+
slug
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
// TODO: dry with docs.tsx - resolver?
|
|
158
|
+
if (error) {
|
|
159
|
+
if (sidebarGroups && error.code === "ENOENT") {
|
|
160
|
+
const firstItem = findFirstUrl(sidebarGroups?.[0]?.items)
|
|
161
|
+
|
|
162
|
+
if (firstItem) {
|
|
163
|
+
return redirect(firstItem)
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
console.error(error)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
sidebarGroups,
|
|
172
|
+
slug,
|
|
173
|
+
code
|
|
174
|
+
} as loaderData
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function mdxExport(code: string) {
|
|
178
|
+
const scope = {
|
|
179
|
+
Fragment: React.Fragment,
|
|
180
|
+
jsxs: React.createElement,
|
|
181
|
+
jsx: React.createElement,
|
|
182
|
+
jsxDEV: React.createElement,
|
|
183
|
+
}
|
|
184
|
+
const fn = new Function(...Object.keys(scope), code)
|
|
185
|
+
return fn(scope)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function renderollAsyncClient(routeId: string, slug: string) {
|
|
189
|
+
return async () => {
|
|
190
|
+
let mod;
|
|
191
|
+
let urlPrefix;
|
|
192
|
+
let data;
|
|
193
|
+
|
|
194
|
+
// TODO: fix any
|
|
195
|
+
function moduleData(mods: any, id: string) {
|
|
196
|
+
mod = mods.default[id]
|
|
197
|
+
if (!mod) {
|
|
198
|
+
throw new Error(`Unknown openapi id: ${id}`)
|
|
199
|
+
}
|
|
200
|
+
urlPrefix = mod.urlPrefix
|
|
201
|
+
data = mod.data
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
switch (routeId) {
|
|
205
|
+
case "xyd-plugin-zero/graphql": {
|
|
206
|
+
// @ts-ignore
|
|
207
|
+
mod = await import("virtual:xyd-plugin-zero/graphql");
|
|
208
|
+
urlPrefix = "/docs/api/graphql" // TODO: dynamic urlPreifx
|
|
209
|
+
data = mod.default.data
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
case "xyd-plugin-zero/openapi": {
|
|
213
|
+
// @ts-ignore
|
|
214
|
+
mod = await import("virtual:xyd-plugin-zero/openapi");
|
|
215
|
+
urlPrefix = "/docs/api/openapi" // TODO: dynamic urlPrefix
|
|
216
|
+
data = mod.default.data
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
default: {
|
|
220
|
+
if (routeId.includes("xyd-plugin-zero/openapi")) {
|
|
221
|
+
const [_, id] = routeId.split("xyd-plugin-zero/openapi-")
|
|
222
|
+
// @ts-ignore
|
|
223
|
+
const mods = await import("virtual:xyd-plugin-zero/openapi")
|
|
224
|
+
moduleData(mods, id)
|
|
225
|
+
break;
|
|
226
|
+
}
|
|
227
|
+
if (routeId.includes("xyd-plugin-zero/graphql")) {
|
|
228
|
+
const [_, id] = routeId.split("xyd-plugin-zero/graphql-")
|
|
229
|
+
// @ts-ignore
|
|
230
|
+
const mods = await import("virtual:xyd-plugin-zero/graphql")
|
|
231
|
+
moduleData(mods, id)
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
throw new Error(`Unknown routeId: ${routeId}`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (!Array.isArray(data)) {
|
|
240
|
+
console.warn(`mod.default is not an array, current type is: ${typeof mod.default}`)
|
|
241
|
+
|
|
242
|
+
return
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// TODO: in the future custom position
|
|
246
|
+
const prevRefs = []
|
|
247
|
+
const nextRefs = []
|
|
248
|
+
const mdxComponentsPrev: any[] = []
|
|
249
|
+
const mdxComponentsNext: any[] = []
|
|
250
|
+
|
|
251
|
+
let pos = 0;
|
|
252
|
+
|
|
253
|
+
for (const chunk of data) {
|
|
254
|
+
if (!chunk) {
|
|
255
|
+
continue
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (chunk.slug === slug) {
|
|
259
|
+
pos = 1
|
|
260
|
+
continue
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const references = pos === 0 ? prevRefs : nextRefs
|
|
264
|
+
|
|
265
|
+
const code = await compile(chunk.content) // TODO: do we need real path?
|
|
266
|
+
const mdx = mdxExport(code)
|
|
267
|
+
const Content = mdx.default
|
|
268
|
+
const content = Content ? parse(Content, {
|
|
269
|
+
components: contentComponents
|
|
270
|
+
}) : null
|
|
271
|
+
|
|
272
|
+
// TODO: support non-fererence pages
|
|
273
|
+
if (content.references) {
|
|
274
|
+
references.push(...(content?.references || []) as [])
|
|
275
|
+
} else {
|
|
276
|
+
const mdxComponents = pos === 0 ? mdxComponentsPrev : mdxComponentsNext
|
|
277
|
+
|
|
278
|
+
mdxComponents.push(<div data-slug={`/${chunk.slug}`}>
|
|
279
|
+
<ComponentContent>
|
|
280
|
+
{content}
|
|
281
|
+
</ComponentContent>
|
|
282
|
+
</div>)
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return [
|
|
287
|
+
({onLoaded}) => <>
|
|
288
|
+
<ComponentContent>
|
|
289
|
+
{mdxComponentsPrev}
|
|
290
|
+
</ComponentContent>
|
|
291
|
+
|
|
292
|
+
{
|
|
293
|
+
prevRefs.length ? <div>
|
|
294
|
+
<AtlasLazy
|
|
295
|
+
references={prevRefs}
|
|
296
|
+
urlPrefix={urlPrefix}
|
|
297
|
+
slug={slug}
|
|
298
|
+
onLoaded={onLoaded}
|
|
299
|
+
/>
|
|
300
|
+
</div> : null
|
|
301
|
+
}
|
|
302
|
+
</>,
|
|
303
|
+
|
|
304
|
+
({onLoaded}) => <>
|
|
305
|
+
<ComponentContent>
|
|
306
|
+
{mdxComponentsNext}
|
|
307
|
+
</ComponentContent>
|
|
308
|
+
|
|
309
|
+
{
|
|
310
|
+
nextRefs.length ? <div>
|
|
311
|
+
<AtlasLazy
|
|
312
|
+
references={nextRefs}
|
|
313
|
+
urlPrefix={urlPrefix}
|
|
314
|
+
slug={slug}
|
|
315
|
+
onLoaded={onLoaded}
|
|
316
|
+
/>
|
|
317
|
+
</div> : null
|
|
318
|
+
}
|
|
319
|
+
</>
|
|
320
|
+
]
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function getRouteId() {
|
|
325
|
+
const routerState = useContext(UNSAFE_DataRouterStateContext)
|
|
326
|
+
let routeId: string = ""
|
|
327
|
+
|
|
328
|
+
routerState?.matches?.forEach(match => {
|
|
329
|
+
const loader = routerState?.loaderData[match?.route?.id]
|
|
330
|
+
|
|
331
|
+
if (loader) {
|
|
332
|
+
routeId = match?.route?.id
|
|
333
|
+
}
|
|
334
|
+
})
|
|
335
|
+
|
|
336
|
+
return routeId
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function MemoMDXComponent(codeComponent: any) {
|
|
340
|
+
return React.useMemo(
|
|
341
|
+
() => codeComponent ? codeComponent : null,
|
|
342
|
+
[codeComponent]
|
|
343
|
+
)
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// // TODO: move to content?
|
|
347
|
+
function mdxContent(code: string) {
|
|
348
|
+
const content = mdxExport(code) // TODO: fix any
|
|
349
|
+
if (!mdxExport) {
|
|
350
|
+
return {}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return {
|
|
354
|
+
component: content?.default,
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// TODO: in the future more smoother loader - first fast server render then move to ideal position of client and then replace and 3 items at start
|
|
359
|
+
export default function APIReference({loaderData}: { loaderData: loaderData }) {
|
|
360
|
+
const content = mdxContent(loaderData.code)
|
|
361
|
+
const serverComponent = content ? parse(content.component, {
|
|
362
|
+
components: contentComponents
|
|
363
|
+
}) : null
|
|
364
|
+
|
|
365
|
+
const memoizedServerComponent = MemoMDXComponent(serverComponent)
|
|
366
|
+
|
|
367
|
+
const serverAtlasOrMDX = memoizedServerComponent?.references ?
|
|
368
|
+
<AtlasLazy
|
|
369
|
+
references={memoizedServerComponent?.references || []}
|
|
370
|
+
slug={loaderData.slug.startsWith("/") ? loaderData.slug : `/${loaderData.slug}`}
|
|
371
|
+
urlPrefix="/"
|
|
372
|
+
/> :
|
|
373
|
+
<ComponentContent>
|
|
374
|
+
{memoizedServerComponent}
|
|
375
|
+
</ComponentContent>
|
|
376
|
+
|
|
377
|
+
const routeId = getRouteId()
|
|
378
|
+
|
|
379
|
+
const RenderollContent = renderoll(
|
|
380
|
+
renderollAsyncClient(routeId, loaderData.slug),
|
|
381
|
+
{
|
|
382
|
+
decorator: ({children}) => <ComponentContent>
|
|
383
|
+
{children}
|
|
384
|
+
</ComponentContent>
|
|
385
|
+
}
|
|
386
|
+
)
|
|
387
|
+
|
|
388
|
+
return <Framework
|
|
389
|
+
settings={settings}
|
|
390
|
+
sidebarGroups={loaderData.sidebarGroups}
|
|
391
|
+
>
|
|
392
|
+
<Theme
|
|
393
|
+
themeSettings={{
|
|
394
|
+
hideToc: true,
|
|
395
|
+
bigArticle: true,
|
|
396
|
+
sidebar: {
|
|
397
|
+
clientSideRouting: true
|
|
398
|
+
}
|
|
399
|
+
}}
|
|
400
|
+
>
|
|
401
|
+
<RenderollContent>
|
|
402
|
+
{serverAtlasOrMDX}
|
|
403
|
+
</RenderollContent>
|
|
404
|
+
</Theme>
|
|
405
|
+
</Framework>
|
|
406
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
|
|
3
|
+
import React from "react";
|
|
4
|
+
import {redirect} from "react-router";
|
|
5
|
+
|
|
6
|
+
import {PageFrontMatter} from "@xyd-js/core"
|
|
7
|
+
import {compileBySlug} from "@xyd-js/content"
|
|
8
|
+
import getContentComponents from "@xyd-js/components/content";
|
|
9
|
+
import {HomePage} from "@xyd-js/components/pages";
|
|
10
|
+
import type {IBreadcrumb, INavLinks} from "@xyd-js/ui";
|
|
11
|
+
import {mapSettingsToProps} from "@xyd-js/framework/hydration";
|
|
12
|
+
import {Framework, FwNav} from "@xyd-js/framework/react";
|
|
13
|
+
import type {FwSidebarGroupProps} from "@xyd-js/framework/react";
|
|
14
|
+
|
|
15
|
+
import settings from 'virtual:xyd-settings';
|
|
16
|
+
import Theme from "virtual:xyd-theme";
|
|
17
|
+
|
|
18
|
+
import "virtual:xyd-theme/index.css"
|
|
19
|
+
import "virtual:xyd-theme-override/index.css"
|
|
20
|
+
|
|
21
|
+
interface loaderData {
|
|
22
|
+
sidebarGroups: FwSidebarGroupProps[]
|
|
23
|
+
breadcrumbs: IBreadcrumb[],
|
|
24
|
+
navlinks?: INavLinks,
|
|
25
|
+
toc: PageFrontMatter
|
|
26
|
+
slug: string
|
|
27
|
+
code: string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const contentComponents = getContentComponents()
|
|
31
|
+
|
|
32
|
+
const supportedExtensions = {
|
|
33
|
+
".mdx": true,
|
|
34
|
+
".md": true,
|
|
35
|
+
"": true,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function getPathname(url: string) {
|
|
39
|
+
const parsedUrl = new URL(url);
|
|
40
|
+
return parsedUrl.pathname.replace(/^\//, '');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function loader({request}: { request: any }) {
|
|
44
|
+
const slug = getPathname(request.url || "index") || "index"
|
|
45
|
+
const ext = path.extname(slug)
|
|
46
|
+
|
|
47
|
+
if (!supportedExtensions[ext]) {
|
|
48
|
+
return {}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
let code = ""
|
|
52
|
+
let error: any
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
code = await compileBySlug(slug, true)
|
|
56
|
+
} catch (e) {
|
|
57
|
+
error = e
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (error?.code === "ENOENT") {
|
|
61
|
+
try {
|
|
62
|
+
// TODO: better index algorithm
|
|
63
|
+
code = await compileBySlug(slug + "/index", true)
|
|
64
|
+
} catch (e) {
|
|
65
|
+
error = e
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const {
|
|
70
|
+
groups: sidebarGroups,
|
|
71
|
+
breadcrumbs,
|
|
72
|
+
navlinks,
|
|
73
|
+
} = await mapSettingsToProps(
|
|
74
|
+
settings,
|
|
75
|
+
slug
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
if (error) {
|
|
79
|
+
if (sidebarGroups && error.code === "ENOENT") {
|
|
80
|
+
const firstItem = sidebarGroups?.[0]?.items?.[0]
|
|
81
|
+
|
|
82
|
+
if (firstItem) {
|
|
83
|
+
return redirect(firstItem.href)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
console.error(error)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
sidebarGroups,
|
|
92
|
+
breadcrumbs,
|
|
93
|
+
navlinks,
|
|
94
|
+
slug,
|
|
95
|
+
code,
|
|
96
|
+
} as loaderData
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// TODO: move to content?
|
|
100
|
+
function mdxExport(code: string) {
|
|
101
|
+
const scope = {
|
|
102
|
+
Fragment: React.Fragment,
|
|
103
|
+
jsxs: React.createElement,
|
|
104
|
+
jsx: React.createElement,
|
|
105
|
+
jsxDEV: React.createElement,
|
|
106
|
+
}
|
|
107
|
+
const fn = new Function(...Object.keys(scope), code)
|
|
108
|
+
return fn(scope)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// // TODO: move to content?
|
|
112
|
+
function mdxContent(code: string) {
|
|
113
|
+
const content = mdxExport(code) // TODO: fix any
|
|
114
|
+
if (!mdxExport) {
|
|
115
|
+
return {}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
component: content?.default,
|
|
120
|
+
toc: content?.toc,
|
|
121
|
+
frontmatter: content?.frontmatter,
|
|
122
|
+
themeSettings: content?.themeSettings || {},
|
|
123
|
+
page: content?.page || false,
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function MemoMDXComponent(codeComponent: any) {
|
|
128
|
+
return React.useMemo(
|
|
129
|
+
() => codeComponent ? codeComponent : null,
|
|
130
|
+
[codeComponent]
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export default function CustomPage({loaderData, ...rest}: { loaderData: loaderData }) {
|
|
135
|
+
const content = mdxContent(loaderData.code)
|
|
136
|
+
const Component = MemoMDXComponent(content.component)
|
|
137
|
+
|
|
138
|
+
return <Framework
|
|
139
|
+
settings={settings}
|
|
140
|
+
sidebarGroups={loaderData.sidebarGroups || []}
|
|
141
|
+
toc={content.toc || []}
|
|
142
|
+
breadcrumbs={loaderData.breadcrumbs || []}
|
|
143
|
+
navlinks={loaderData.navlinks}
|
|
144
|
+
>
|
|
145
|
+
{content?.page ? <Component components={{
|
|
146
|
+
...contentComponents,
|
|
147
|
+
// TODO: another page components
|
|
148
|
+
HomePage: (props) => <HomePage
|
|
149
|
+
{...props}
|
|
150
|
+
// TODO: get props from theme about nav (middle etc)
|
|
151
|
+
// TODO: footer
|
|
152
|
+
// TODO: style
|
|
153
|
+
header={<div style={{marginLeft: "var(--xyd-global-page-gutter)"}}>
|
|
154
|
+
<FwNav kind="middle"/>
|
|
155
|
+
</div>}
|
|
156
|
+
|
|
157
|
+
>
|
|
158
|
+
{props.children}
|
|
159
|
+
</HomePage>,
|
|
160
|
+
}}/> : <Theme
|
|
161
|
+
themeSettings={content.themeSettings}
|
|
162
|
+
>
|
|
163
|
+
{Component ? <Component components={contentComponents}/> : <></>}
|
|
164
|
+
</Theme>}
|
|
165
|
+
</Framework>
|
|
166
|
+
}
|