prev-cli 0.16.2 → 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 +29 -2
- package/dist/config/schema.d.ts +1 -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
|
@@ -647,7 +647,8 @@ var defaultConfig = {
|
|
|
647
647
|
theme: "system",
|
|
648
648
|
contentWidth: "constrained",
|
|
649
649
|
hidden: [],
|
|
650
|
-
order: {}
|
|
650
|
+
order: {},
|
|
651
|
+
port: undefined
|
|
651
652
|
};
|
|
652
653
|
function validateConfig(raw) {
|
|
653
654
|
const config = { ...defaultConfig };
|
|
@@ -670,6 +671,9 @@ function validateConfig(raw) {
|
|
|
670
671
|
}
|
|
671
672
|
}
|
|
672
673
|
}
|
|
674
|
+
if (typeof obj.port === "number" && obj.port > 0 && obj.port < 65536) {
|
|
675
|
+
config.port = obj.port;
|
|
676
|
+
}
|
|
673
677
|
}
|
|
674
678
|
return config;
|
|
675
679
|
}
|
|
@@ -855,6 +859,28 @@ async function createViteConfig(options) {
|
|
|
855
859
|
});
|
|
856
860
|
}
|
|
857
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
|
+
},
|
|
858
884
|
{
|
|
859
885
|
name: "prev-preview-server",
|
|
860
886
|
resolveId(id) {
|
|
@@ -1467,7 +1493,8 @@ async function main() {
|
|
|
1467
1493
|
printHelp();
|
|
1468
1494
|
process.exit(0);
|
|
1469
1495
|
}
|
|
1470
|
-
const
|
|
1496
|
+
const config = loadConfig(rootDir);
|
|
1497
|
+
const port = values.port ? parseInt(values.port, 10) : config.port;
|
|
1471
1498
|
const days = values.days ? parseInt(values.days, 10) : 30;
|
|
1472
1499
|
const include = values.include || [];
|
|
1473
1500
|
try {
|
package/dist/config/schema.d.ts
CHANGED
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')
|