rasengan 1.1.2 → 1.2.0-beta.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.
- package/CHANGELOG.md +10 -0
- package/lib/esm/cli/index.js +2 -2
- package/lib/esm/core/config/vite/defaults.js +1 -17
- package/lib/esm/core/dynamic/index.js +32 -0
- package/lib/esm/core/plugins/index.js +1 -1
- package/lib/esm/entries/client/render.js +45 -16
- package/lib/esm/entries/server/entry.server.js +1 -0
- package/lib/esm/entries/server/index.js +3 -3
- package/lib/esm/routing/components/fallback.js +8 -0
- package/lib/esm/routing/components/index.js +97 -6
- package/lib/esm/routing/components/template.js +8 -7
- package/lib/esm/routing/index.js +3 -3
- package/lib/esm/routing/providers/metadata.js +23 -13
- package/lib/esm/routing/utils/define-router.js +10 -6
- package/lib/esm/routing/utils/flat-routes.js +50 -78
- package/lib/esm/routing/utils/generate-routes.js +279 -178
- package/lib/esm/server/build/manifest.js +19 -7
- package/lib/esm/server/dev/handlers.js +16 -1
- package/lib/esm/server/dev/server.js +19 -1
- package/lib/esm/server/node/index.js +8 -2
- package/lib/tsconfig.esm.tsbuildinfo +1 -1
- package/lib/tsconfig.types.tsbuildinfo +1 -1
- package/lib/types/core/dynamic/index.d.ts +15 -0
- package/lib/types/core/types.d.ts +1 -1
- package/lib/types/entries/client/render.d.ts +3 -2
- package/lib/types/routing/components/fallback.d.ts +5 -0
- package/lib/types/routing/components/index.d.ts +11 -0
- package/lib/types/routing/components/template.d.ts +1 -1
- package/lib/types/routing/index.d.ts +3 -3
- package/lib/types/routing/interfaces.d.ts +5 -4
- package/lib/types/routing/providers/metadata.d.ts +1 -3
- package/lib/types/routing/types.d.ts +21 -3
- package/lib/types/routing/utils/define-routes-group.d.ts +1 -1
- package/lib/types/routing/utils/flat-routes.d.ts +21 -3
- package/lib/types/routing/utils/generate-routes.d.ts +6 -6
- package/lib/types/server/build/manifest.d.ts +4 -4
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
package/lib/esm/cli/index.js
CHANGED
|
@@ -8,9 +8,9 @@ program
|
|
|
8
8
|
// Handle the dev command
|
|
9
9
|
program
|
|
10
10
|
.command('dev')
|
|
11
|
-
.option('-p <port>')
|
|
11
|
+
.option('-p, --port <port>', 'Port number')
|
|
12
12
|
.description('Start development server')
|
|
13
|
-
.action(async ({
|
|
13
|
+
.action(async ({ port }) => {
|
|
14
14
|
const convertedPort = Number(port);
|
|
15
15
|
// Checking port
|
|
16
16
|
if (port &&
|
|
@@ -1,15 +1,8 @@
|
|
|
1
1
|
// core/config/defaults.ts
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
// Define core external packages
|
|
4
|
-
const CORE_EXTERNALS = [
|
|
5
|
-
// '@rasenganjs/mdx',
|
|
6
|
-
// '@rasenganjs/vercel',
|
|
7
|
-
// '@rasenganjs/netlify',
|
|
8
|
-
];
|
|
9
3
|
export const createDefaultViteConfig = (rootPath, __dirname, mode, config) => {
|
|
10
4
|
// Combine core externals with user-defined externals
|
|
11
5
|
const externals = [
|
|
12
|
-
...CORE_EXTERNALS,
|
|
13
6
|
...(Array.isArray(config.vite?.build?.external)
|
|
14
7
|
? config.vite.build.external
|
|
15
8
|
: []),
|
|
@@ -28,21 +21,12 @@ export const createDefaultViteConfig = (rootPath, __dirname, mode, config) => {
|
|
|
28
21
|
return 'vendor';
|
|
29
22
|
if (id.includes('src/components'))
|
|
30
23
|
return 'shared-components';
|
|
31
|
-
if (config.ssr) {
|
|
32
|
-
if (id.includes('src/app') && id.includes('.page.')) {
|
|
33
|
-
const parts = id.split('src/app')[1]?.split('/');
|
|
34
|
-
if (parts?.length) {
|
|
35
|
-
const pageName = parts.pop()?.split('.')[0];
|
|
36
|
-
return pageName ? `page-${pageName}` : undefined;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
24
|
return undefined;
|
|
41
25
|
},
|
|
42
26
|
},
|
|
43
27
|
},
|
|
44
28
|
outDir: 'dist',
|
|
45
|
-
chunkSizeWarningLimit:
|
|
29
|
+
chunkSizeWarningLimit: 2000,
|
|
46
30
|
},
|
|
47
31
|
environments: {
|
|
48
32
|
client: {
|
|
@@ -19,3 +19,35 @@ export function dynamicLoad(load, fallback = _jsx(_Fragment, {}) // Default pend
|
|
|
19
19
|
throw new Error(error);
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* It allows you to defer loading of page components,
|
|
24
|
+
* and only include them in the client bundle when they're needed
|
|
25
|
+
* @param filePath Path to the page component we want to load lazily
|
|
26
|
+
* @returns
|
|
27
|
+
*/
|
|
28
|
+
export function lazyLoadPage(routePath, filePath) {
|
|
29
|
+
// use import.meta.glob with a fixed pattern that covers your pages
|
|
30
|
+
const modules = import.meta.glob('/src/app/**/*.{js,ts,jsx,tsx,md,mdx}');
|
|
31
|
+
// if started with ./ then removed it
|
|
32
|
+
const normalizePath = filePath.startsWith('./')
|
|
33
|
+
? filePath.slice(2)
|
|
34
|
+
: filePath;
|
|
35
|
+
// Get the full path from the modules object
|
|
36
|
+
const fullPath = Object.keys(modules).find((key) => key.endsWith(normalizePath));
|
|
37
|
+
if (!fullPath) {
|
|
38
|
+
throw new Error(`[rasengan lazyLoad]: No module found for path "${filePath}". Did you include it in the glob?`);
|
|
39
|
+
}
|
|
40
|
+
const loader = modules[fullPath];
|
|
41
|
+
if (!loader) {
|
|
42
|
+
throw new Error(`[rasengan lazyLoad]: No module found for path "${filePath}". Did you include it in the glob?`);
|
|
43
|
+
}
|
|
44
|
+
const page = {
|
|
45
|
+
path: routePath,
|
|
46
|
+
fullPath,
|
|
47
|
+
segment: routePath, // TODO: Handle segments
|
|
48
|
+
module: loader,
|
|
49
|
+
source: filePath,
|
|
50
|
+
isLayout: false,
|
|
51
|
+
};
|
|
52
|
+
return page;
|
|
53
|
+
}
|
|
@@ -2,27 +2,56 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { hydrateRoot, createRoot } from 'react-dom/client';
|
|
3
3
|
import { StrictMode } from 'react';
|
|
4
4
|
import { RootComponent } from '../../routing/components/template.js';
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
import { generateRoutes, preloadMatches, } from '../../routing/utils/generate-routes.js';
|
|
6
|
+
import { createBrowserRouter, RouterProvider } from 'react-router';
|
|
7
|
+
const isSpaMode = Boolean(window.__RASENGAN_SPA_MODE__);
|
|
8
|
+
export default async function renderApp(App, AppRouter, options) {
|
|
9
|
+
// Get root element
|
|
10
|
+
// We need to get the root element to render the app - (SPA mode)
|
|
11
|
+
// or to hydrate the app - (SSR mode)
|
|
7
12
|
const root = document.getElementById('root');
|
|
8
13
|
if (!root) {
|
|
9
|
-
throw new Error('
|
|
14
|
+
throw new Error('#root element not found in the DOM');
|
|
10
15
|
}
|
|
11
|
-
//
|
|
16
|
+
// Resolve app router
|
|
17
|
+
const RasenganRouter = await AppRouter;
|
|
18
|
+
// Generate routes for the browser routing
|
|
19
|
+
const routes = generateRoutes(RasenganRouter);
|
|
20
|
+
// Preload lazy routes
|
|
21
|
+
// We have to only preload the routes that are matched for the current URL
|
|
22
|
+
// The remaining routing will be lazy loaded on the client after routes change
|
|
23
|
+
await preloadMatches(window.location, routes);
|
|
24
|
+
// Create router
|
|
25
|
+
let router = createBrowserRouter(routes, {
|
|
26
|
+
hydrationData: window.__staticRouterHydrationData,
|
|
27
|
+
});
|
|
28
|
+
// Generate client router
|
|
29
|
+
const ClientRouter = () => _jsx(RouterProvider, { router: router });
|
|
30
|
+
// Generate app tree
|
|
31
|
+
const appTree = options.reactStrictMode ? (_jsx(StrictMode, { children: _jsx(App, { Component: (props) => (_jsx(RootComponent, { ...props, Router: ClientRouter })) }) })) : (_jsx(App, { Component: (props) => _jsx(RootComponent, { ...props, Router: ClientRouter }) }));
|
|
32
|
+
// Render app
|
|
12
33
|
if (isSpaMode) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
hydrateRoot(root, _jsx(StrictMode, { children: _jsx(App, { Component: RootComponent }) }));
|
|
34
|
+
// No SSR markup, so start fresh
|
|
35
|
+
createRoot(root, {
|
|
36
|
+
onCaughtError: (error) => {
|
|
37
|
+
console.error(error);
|
|
38
|
+
},
|
|
39
|
+
onRecoverableError(error, errorInfo) {
|
|
40
|
+
console.error(error);
|
|
41
|
+
console.error(errorInfo);
|
|
42
|
+
},
|
|
43
|
+
}).render(appTree);
|
|
24
44
|
}
|
|
25
45
|
else {
|
|
26
|
-
|
|
46
|
+
// SSR markup present, hydrate instead of re-rendering
|
|
47
|
+
hydrateRoot(root, appTree, {
|
|
48
|
+
onCaughtError: (error) => {
|
|
49
|
+
console.error(error);
|
|
50
|
+
},
|
|
51
|
+
onRecoverableError(error, errorInfo) {
|
|
52
|
+
console.error(error);
|
|
53
|
+
console.error(errorInfo);
|
|
54
|
+
},
|
|
55
|
+
});
|
|
27
56
|
}
|
|
28
57
|
}
|
|
@@ -16,6 +16,7 @@ export const render = async (StaticRouterComponent, res, options) => {
|
|
|
16
16
|
const rootPath = process.cwd();
|
|
17
17
|
let App;
|
|
18
18
|
let Template;
|
|
19
|
+
// If build options are provided, that means we are in production mode
|
|
19
20
|
if (buildOptions) {
|
|
20
21
|
App = (await loadModuleSSR(posix.join(buildOptions.buildDirectory, buildOptions.serverPathDirectory, 'main.js'))).default;
|
|
21
22
|
Template = (await loadModuleSSR(join(buildOptions.buildDirectory, buildOptions.serverPathDirectory, 'template.js'))).default;
|
|
@@ -19,13 +19,13 @@ export const TemplateLayout = ({ StaticRouterComponent, metadata, assets, App, T
|
|
|
19
19
|
}
|
|
20
20
|
if (isSpaMode) {
|
|
21
21
|
otherScripts = (_jsxs(React.Fragment, { children: [_jsx("script", { type: "module", dangerouslySetInnerHTML: {
|
|
22
|
-
__html: `window.__RASENGAN_SPA_MODE__
|
|
22
|
+
__html: `window.__RASENGAN_SPA_MODE__=true;`,
|
|
23
23
|
} }), !assets && (_jsx("script", { type: "module", src: "/src/index", async: true }))] }));
|
|
24
24
|
}
|
|
25
25
|
else {
|
|
26
26
|
otherScripts = (_jsx(React.Fragment, { children: _jsx("script", { type: "module", dangerouslySetInnerHTML: {
|
|
27
|
-
__html: `window.__RASENGAN_SPA_MODE__
|
|
27
|
+
__html: `window.__RASENGAN_SPA_MODE__=false;`,
|
|
28
28
|
} }) }));
|
|
29
29
|
}
|
|
30
|
-
return (_jsx(Template, { Head: ({ children }) => (_jsxs(HeadComponent, { metadata: metadata, assets: assets, children: [viteScripts, otherScripts, children] })), Body: ({ children }) => (_jsx(BodyComponent, { asChild: App ? true : false, AppContent: App && _jsx(App, { Component: RootComponent, children: StaticRouterComponent }), children: children })), Script: ({ children }) => _jsx(ScriptComponent, { children: children }) }));
|
|
30
|
+
return (_jsx(Template, { Head: ({ children }) => (_jsxs(HeadComponent, { metadata: metadata, assets: assets, children: [viteScripts, otherScripts, children] })), Body: ({ children }) => (_jsx(BodyComponent, { asChild: App ? true : false, AppContent: App && (_jsx(App, { Component: (props) => _jsx(RootComponent, { ...props }), children: StaticRouterComponent })), children: children })), Script: ({ children }) => _jsx(ScriptComponent, { children: children }) }));
|
|
31
31
|
};
|
|
@@ -1,12 +1,40 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs
|
|
2
|
-
import { isRouteErrorResponse, Link, useParams, useRouteError, } from 'react-router';
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { isRouteErrorResponse, Link, useLocation, useParams, useRouteError, } from 'react-router';
|
|
3
|
+
import { useEffect, useRef } from 'react';
|
|
4
|
+
// Extract the environment variables
|
|
5
|
+
const extractEnv = () => {
|
|
6
|
+
try {
|
|
7
|
+
const env = import.meta.env;
|
|
8
|
+
// If not env, use process.env on the server only
|
|
9
|
+
if (!env) {
|
|
10
|
+
const serverEnv = process.env;
|
|
11
|
+
return {
|
|
12
|
+
DEV: serverEnv.NODE_ENV === 'development',
|
|
13
|
+
PROD: serverEnv.NODE_ENV === 'production',
|
|
14
|
+
TEST: serverEnv.NODE_ENV === 'test',
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
DEV: env.DEV,
|
|
19
|
+
PROD: env.PROD,
|
|
20
|
+
TEST: env.TEST,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
console.error(error);
|
|
25
|
+
return {
|
|
26
|
+
DEV: false,
|
|
27
|
+
PROD: true,
|
|
28
|
+
TEST: false,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
};
|
|
3
32
|
/**
|
|
4
33
|
* Error boundary component that will be displayed if an error occurs during a routing
|
|
5
34
|
* @returns
|
|
6
35
|
*/
|
|
7
36
|
export function ErrorBoundary() {
|
|
8
|
-
const { DEV } =
|
|
9
|
-
console.log(import.meta.env);
|
|
37
|
+
const { DEV } = extractEnv();
|
|
10
38
|
let error = useRouteError();
|
|
11
39
|
if (!DEV)
|
|
12
40
|
return (_jsx("section", { style: {
|
|
@@ -28,10 +56,31 @@ export function ErrorBoundary() {
|
|
|
28
56
|
fontSize: '18px',
|
|
29
57
|
}, children: "Application Error" }) }));
|
|
30
58
|
if (isRouteErrorResponse(error)) {
|
|
31
|
-
return (_jsxs(
|
|
59
|
+
return (_jsxs("section", { style: {
|
|
60
|
+
position: 'fixed',
|
|
61
|
+
top: 0,
|
|
62
|
+
left: 0,
|
|
63
|
+
right: 0,
|
|
64
|
+
bottom: 0,
|
|
65
|
+
zIndex: 100,
|
|
66
|
+
display: 'flex',
|
|
67
|
+
flexDirection: 'row',
|
|
68
|
+
justifyContent: 'center',
|
|
69
|
+
alignItems: 'center',
|
|
70
|
+
height: '100vh',
|
|
71
|
+
width: '100vw',
|
|
72
|
+
gap: 10,
|
|
73
|
+
backgroundColor: '#fff',
|
|
74
|
+
}, children: [_jsx("p", { style: {
|
|
75
|
+
fontSize: '18px',
|
|
76
|
+
}, children: "Application Error" }), _jsxs("h1", { style: {
|
|
77
|
+
fontSize: '18px',
|
|
78
|
+
}, children: [error.status, " ", error.statusText] }), _jsx("p", { style: {
|
|
79
|
+
fontSize: '18px',
|
|
80
|
+
}, children: error.data })] }));
|
|
32
81
|
}
|
|
33
82
|
else if (error instanceof Error) {
|
|
34
|
-
return (_jsxs("
|
|
83
|
+
return (_jsxs("section", { style: {
|
|
35
84
|
position: 'fixed',
|
|
36
85
|
top: 0,
|
|
37
86
|
left: 0,
|
|
@@ -129,3 +178,45 @@ export const CustomLink = (props) => {
|
|
|
129
178
|
}
|
|
130
179
|
return (_jsx(Link, { to: to, ...rest, children: children }));
|
|
131
180
|
};
|
|
181
|
+
// Store scroll positions globally (per location.key)
|
|
182
|
+
const scrollPositions = {};
|
|
183
|
+
/**
|
|
184
|
+
* Scroll restoration component
|
|
185
|
+
* @param {Props} props
|
|
186
|
+
* @returns
|
|
187
|
+
*/
|
|
188
|
+
export function ScrollRestoration({ alwaysToTop = false, target }) {
|
|
189
|
+
const location = useLocation();
|
|
190
|
+
const pathnameRef = useRef(location.pathname);
|
|
191
|
+
useEffect(() => {
|
|
192
|
+
if (typeof window === 'undefined')
|
|
193
|
+
return;
|
|
194
|
+
const prevPathname = pathnameRef.current;
|
|
195
|
+
const el = target?.current; // easier to reference
|
|
196
|
+
if (alwaysToTop) {
|
|
197
|
+
if (el) {
|
|
198
|
+
el.scrollTo(0, 0);
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
window.scrollTo(0, 0);
|
|
202
|
+
}
|
|
203
|
+
pathnameRef.current = location.pathname;
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
// Save scroll position of the previous page
|
|
207
|
+
if (prevPathname) {
|
|
208
|
+
scrollPositions[prevPathname] = el ? el.scrollTop : window.scrollY;
|
|
209
|
+
}
|
|
210
|
+
// Restore scroll position of the new page (default to 0 if not stored)
|
|
211
|
+
const storedY = scrollPositions[location.pathname] ?? 0;
|
|
212
|
+
if (el) {
|
|
213
|
+
el.scrollTo(0, storedY);
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
window.scrollTo(0, storedY);
|
|
217
|
+
}
|
|
218
|
+
// Update ref
|
|
219
|
+
pathnameRef.current = location.pathname;
|
|
220
|
+
}, [location.pathname, target?.current]); // depend on target.current
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import React, {
|
|
3
|
-
import { generateMetadata
|
|
2
|
+
import React, { useMemo } from 'react';
|
|
3
|
+
import { generateMetadata } from '../utils/index.js';
|
|
4
4
|
import { Outlet } from 'react-router';
|
|
5
5
|
/**
|
|
6
6
|
* App component that represent the entry point of the application
|
|
7
7
|
*/
|
|
8
|
-
export const RootComponent = ({
|
|
8
|
+
export const RootComponent = ({ Router, // Client Router
|
|
9
|
+
children = undefined, // Static Router for SSR when provided
|
|
10
|
+
}) => {
|
|
9
11
|
// Return children if they exist
|
|
10
12
|
if (children)
|
|
11
|
-
return children;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
let Router = getRouter(AppRouter);
|
|
13
|
+
return children; // For the SSR
|
|
14
|
+
if (!Router)
|
|
15
|
+
return null;
|
|
15
16
|
return _jsx(Router, {});
|
|
16
17
|
};
|
|
17
18
|
/**
|
package/lib/esm/routing/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { CustomLink } from './components/index.js';
|
|
1
|
+
import { CustomLink, ScrollRestoration } from './components/index.js';
|
|
2
2
|
export { defineRouter, defineRoutesGroup, flatRoutes } from './utils/index.js';
|
|
3
3
|
export { RouterComponent } from './interfaces.js';
|
|
4
|
-
export { Outlet,
|
|
5
|
-
export { CustomLink as Link };
|
|
4
|
+
export { Outlet, useLocation, useNavigate, useNavigation, useParams, useSearchParams, useFetcher, useMatch, useRoutes, useResolvedPath, matchRoutes, generatePath, matchPath, createRoutesFromChildren, Navigate, NavLink, } from 'react-router';
|
|
5
|
+
export { CustomLink as Link, ScrollRestoration };
|
|
@@ -1,22 +1,30 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useLocation } from 'react-router';
|
|
2
|
+
import { useLocation, useMatches } from 'react-router';
|
|
3
3
|
import { useEffect } from 'react';
|
|
4
4
|
import { generateMetadata } from '../utils/generate-metadata.js';
|
|
5
5
|
import ReactDOMServer from 'react-dom/server';
|
|
6
|
-
export default function MetadataProvider({ children,
|
|
7
|
-
const
|
|
6
|
+
export default function MetadataProvider({ children, }) {
|
|
7
|
+
const location = useLocation();
|
|
8
|
+
const routes = useMatches();
|
|
8
9
|
useEffect(() => {
|
|
9
|
-
|
|
10
|
-
if (!metadata)
|
|
11
|
-
return;
|
|
12
|
-
handleInjectMetadata(metadata);
|
|
13
|
-
}, [pathname]);
|
|
14
|
-
const handleInjectMetadata = (metadata) => {
|
|
15
|
-
if (!metadata)
|
|
10
|
+
if (typeof window === 'undefined')
|
|
16
11
|
return;
|
|
12
|
+
(async () => {
|
|
13
|
+
const loadersData = routes.map((route) => route.loaderData);
|
|
14
|
+
await handleApplyMetadata(loadersData);
|
|
15
|
+
})();
|
|
16
|
+
}, [location]);
|
|
17
|
+
const handleApplyMetadata = async (loadersData) => {
|
|
18
|
+
// We generate the metadata
|
|
19
|
+
const metadatas = generateMetadata(loadersData.map((item) => item.meta));
|
|
20
|
+
// We get the last metadata
|
|
21
|
+
// This is the metadata of the page
|
|
22
|
+
const leafMetadata = loadersData.at(-1)?.meta;
|
|
23
|
+
handleInjectMetadata(metadatas, leafMetadata);
|
|
24
|
+
};
|
|
25
|
+
const handleInjectMetadata = (metaTags, leafMetadata) => {
|
|
17
26
|
// Check if we are on the browser
|
|
18
27
|
if (typeof window !== 'undefined') {
|
|
19
|
-
const metaTags = generateMetadata([metadata]);
|
|
20
28
|
// Find all meta tags with data-rg attribute and remove them
|
|
21
29
|
const metaTagsToRemove = document.querySelectorAll('meta[data-rg="true"]');
|
|
22
30
|
metaTagsToRemove.forEach((metaTag) => {
|
|
@@ -28,12 +36,14 @@ export default function MetadataProvider({ children, metadataMapping, }) {
|
|
|
28
36
|
const metaTagString = ReactDOMServer.renderToStaticMarkup(metaTag);
|
|
29
37
|
document.head.insertAdjacentHTML('beforeend', metaTagString);
|
|
30
38
|
});
|
|
39
|
+
if (!leafMetadata)
|
|
40
|
+
return;
|
|
31
41
|
// Change the title of the page
|
|
32
|
-
document.title =
|
|
42
|
+
document.title = leafMetadata.title;
|
|
33
43
|
// Change the description of the page
|
|
34
44
|
const metaDescription = document.createElement('meta');
|
|
35
45
|
metaDescription.setAttribute('name', 'description');
|
|
36
|
-
metaDescription.setAttribute('content',
|
|
46
|
+
metaDescription.setAttribute('content', leafMetadata.description);
|
|
37
47
|
metaDescription.setAttribute('data-rg', 'true');
|
|
38
48
|
document.head.appendChild(metaDescription);
|
|
39
49
|
}
|
|
@@ -8,11 +8,6 @@ import { DefaultLayout } from '../components/template.js';
|
|
|
8
8
|
export const defineRouter = (option) => {
|
|
9
9
|
const { imports, layout, pages, loaderComponent, notFoundComponent, useParentLayout, } = option;
|
|
10
10
|
return async (Router) => {
|
|
11
|
-
// Handle errors
|
|
12
|
-
// if (!option.pages)
|
|
13
|
-
// throw new Error(
|
|
14
|
-
// 'You must provide a list of pages in the router option object'
|
|
15
|
-
// );
|
|
16
11
|
// Create router
|
|
17
12
|
const router = new Router();
|
|
18
13
|
// List of pages component
|
|
@@ -21,6 +16,10 @@ export const defineRouter = (option) => {
|
|
|
21
16
|
// Check if p is an array
|
|
22
17
|
if (Array.isArray(p)) {
|
|
23
18
|
for (let page of p) {
|
|
19
|
+
if ('source' in page) {
|
|
20
|
+
pageComponentList.push(page);
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
24
23
|
if (isMDXPage(page)) {
|
|
25
24
|
const Page = await convertMDXPageToPageComponent(page);
|
|
26
25
|
pageComponentList.push(Page);
|
|
@@ -31,6 +30,10 @@ export const defineRouter = (option) => {
|
|
|
31
30
|
}
|
|
32
31
|
continue;
|
|
33
32
|
}
|
|
33
|
+
if ('source' in p) {
|
|
34
|
+
pageComponentList.push(p);
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
34
37
|
// When p is a MDXPageComponent
|
|
35
38
|
if (isMDXPage(p)) {
|
|
36
39
|
const Page = await convertMDXPageToPageComponent(p);
|
|
@@ -75,6 +78,7 @@ const loadMDXRenderer = async () => {
|
|
|
75
78
|
return MDXRenderer;
|
|
76
79
|
}
|
|
77
80
|
catch (e) {
|
|
78
|
-
|
|
81
|
+
console.error(e);
|
|
82
|
+
throw e;
|
|
79
83
|
}
|
|
80
84
|
};
|