prev-cli 0.16.3 → 0.16.4
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/dist/cli.js +22 -0
- package/package.json +1 -1
- package/src/theme/Preview.tsx +2 -2
- package/src/theme/Toolbar.tsx +4 -2
- package/src/theme/entry.tsx +30 -3
package/dist/cli.js
CHANGED
|
@@ -859,6 +859,28 @@ async function createViteConfig(options) {
|
|
|
859
859
|
});
|
|
860
860
|
}
|
|
861
861
|
},
|
|
862
|
+
{
|
|
863
|
+
name: "prev-spa-fallback",
|
|
864
|
+
configureServer(server) {
|
|
865
|
+
return () => {
|
|
866
|
+
server.middlewares.use((req, res, next) => {
|
|
867
|
+
const urlPath = req.url?.split("?")[0] || "";
|
|
868
|
+
if (urlPath.startsWith("/__") || urlPath.startsWith("/@") || urlPath.startsWith("/node_modules") || urlPath.includes(".")) {
|
|
869
|
+
return next();
|
|
870
|
+
}
|
|
871
|
+
const indexPath = path7.join(srcRoot2, "theme/index.html");
|
|
872
|
+
if (existsSync5(indexPath)) {
|
|
873
|
+
server.transformIndexHtml(req.url, readFileSync4(indexPath, "utf-8")).then((html) => {
|
|
874
|
+
res.setHeader("Content-Type", "text/html");
|
|
875
|
+
res.end(html);
|
|
876
|
+
}).catch(next);
|
|
877
|
+
return;
|
|
878
|
+
}
|
|
879
|
+
next();
|
|
880
|
+
});
|
|
881
|
+
};
|
|
882
|
+
}
|
|
883
|
+
},
|
|
862
884
|
{
|
|
863
885
|
name: "prev-preview-server",
|
|
864
886
|
resolveId(id) {
|
package/package.json
CHANGED
package/src/theme/Preview.tsx
CHANGED
|
@@ -32,8 +32,8 @@ export function Preview({ src, height = 400, title, mode = 'wasm', showHeader =
|
|
|
32
32
|
|
|
33
33
|
const iframeRef = useRef<HTMLIFrameElement>(null)
|
|
34
34
|
|
|
35
|
-
// URL depends on mode
|
|
36
|
-
const previewUrl = mode === 'wasm' ?
|
|
35
|
+
// URL depends on mode - wasm mode needs src param
|
|
36
|
+
const previewUrl = mode === 'wasm' ? `/_preview-runtime?src=${src}` : `/_preview/${src}`
|
|
37
37
|
const displayTitle = title || src
|
|
38
38
|
|
|
39
39
|
// Calculate current width
|
package/src/theme/Toolbar.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useState, useRef, useEffect } from 'react'
|
|
2
|
-
import { Link } from '@tanstack/react-router'
|
|
2
|
+
import { Link, useLocation } from '@tanstack/react-router'
|
|
3
3
|
import type { PageTree } from 'fumadocs-core/server'
|
|
4
4
|
import { previews } from 'virtual:prev-previews'
|
|
5
5
|
import { IconMenu2, IconLayoutGrid, IconSun, IconMoon, IconArrowsMaximize, IconArrowsMinimize } from '@tabler/icons-react'
|
|
@@ -20,6 +20,8 @@ export function Toolbar({ tree, onThemeToggle, onWidthToggle, isDark, isFullWidt
|
|
|
20
20
|
const [dragging, setDragging] = useState(false)
|
|
21
21
|
const dragStart = useRef({ x: 0, y: 0 })
|
|
22
22
|
const toolbarRef = useRef<HTMLDivElement>(null)
|
|
23
|
+
const location = useLocation()
|
|
24
|
+
const isOnPreviews = location.pathname.startsWith('/previews')
|
|
23
25
|
|
|
24
26
|
const handleMouseDown = (e: React.MouseEvent) => {
|
|
25
27
|
if ((e.target as HTMLElement).closest('button, a')) return
|
|
@@ -63,7 +65,7 @@ export function Toolbar({ tree, onThemeToggle, onWidthToggle, isDark, isFullWidt
|
|
|
63
65
|
</button>
|
|
64
66
|
|
|
65
67
|
{previews && previews.length > 0 && (
|
|
66
|
-
<Link to="/previews" className=
|
|
68
|
+
<Link to="/previews" className={`toolbar-btn ${isOnPreviews ? 'active' : ''}`} title="Previews">
|
|
67
69
|
<IconLayoutGrid size={18} />
|
|
68
70
|
</Link>
|
|
69
71
|
)}
|
package/src/theme/entry.tsx
CHANGED
|
@@ -6,6 +6,8 @@ import {
|
|
|
6
6
|
createRootRoute,
|
|
7
7
|
createRoute,
|
|
8
8
|
Outlet,
|
|
9
|
+
redirect,
|
|
10
|
+
Navigate,
|
|
9
11
|
} from '@tanstack/react-router'
|
|
10
12
|
import { MDXProvider } from '@mdx-js/react'
|
|
11
13
|
import { pages, sidebar } from 'virtual:prev-pages'
|
|
@@ -257,6 +259,10 @@ const previewDetailRoute = createRoute({
|
|
|
257
259
|
component: PreviewPage,
|
|
258
260
|
})
|
|
259
261
|
|
|
262
|
+
// Check if we have an index page (route '/')
|
|
263
|
+
const hasIndexPage = pages.some((page: { route: string }) => page.route === '/')
|
|
264
|
+
const firstPage = pages[0] as { route: string; file: string; title?: string; description?: string; frontmatter?: Record<string, unknown> } | undefined
|
|
265
|
+
|
|
260
266
|
// Create routes from pages
|
|
261
267
|
const pageRoutes = pages.map((page: { route: string; file: string; title?: string; description?: string; frontmatter?: Record<string, unknown> }) => {
|
|
262
268
|
const Component = getPageComponent(page.file)
|
|
@@ -272,9 +278,30 @@ const pageRoutes = pages.map((page: { route: string; file: string; title?: strin
|
|
|
272
278
|
})
|
|
273
279
|
})
|
|
274
280
|
|
|
275
|
-
//
|
|
276
|
-
const
|
|
277
|
-
|
|
281
|
+
// If no index page exists, create a redirect from '/' to the first page
|
|
282
|
+
const indexRedirectRoute = !hasIndexPage && firstPage ? createRoute({
|
|
283
|
+
getParentRoute: () => rootRoute,
|
|
284
|
+
path: '/',
|
|
285
|
+
component: () => <Navigate to={firstPage.route} />,
|
|
286
|
+
}) : null
|
|
287
|
+
|
|
288
|
+
// Not found component - redirect to first page or index
|
|
289
|
+
function NotFoundPage() {
|
|
290
|
+
const targetRoute = firstPage?.route || '/'
|
|
291
|
+
return <Navigate to={targetRoute} />
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Create router with notFoundRoute
|
|
295
|
+
const routeTree = rootRoute.addChildren([
|
|
296
|
+
previewsRoute,
|
|
297
|
+
previewDetailRoute,
|
|
298
|
+
...(indexRedirectRoute ? [indexRedirectRoute] : []),
|
|
299
|
+
...pageRoutes,
|
|
300
|
+
])
|
|
301
|
+
const router = createRouter({
|
|
302
|
+
routeTree,
|
|
303
|
+
defaultNotFoundComponent: NotFoundPage,
|
|
304
|
+
})
|
|
278
305
|
|
|
279
306
|
// Mount app - RouterProvider must be outermost so TanStack Router context is available
|
|
280
307
|
const container = document.getElementById('root')
|