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 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 port = values.port ? parseInt(values.port, 10) : undefined;
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 {
@@ -3,6 +3,7 @@ export interface PrevConfig {
3
3
  contentWidth: 'constrained' | 'full';
4
4
  hidden: string[];
5
5
  order: Record<string, string[]>;
6
+ port?: number;
6
7
  }
7
8
  export declare const defaultConfig: PrevConfig;
8
9
  export declare function validateConfig(raw: unknown): PrevConfig;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prev-cli",
3
- "version": "0.16.2",
3
+ "version": "0.16.4",
4
4
  "description": "Transform MDX directories into beautiful documentation websites",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -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' ? '/_preview-runtime' : `/_preview/${src}`
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
@@ -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="toolbar-btn" title="Previews">
68
+ <Link to="/previews" className={`toolbar-btn ${isOnPreviews ? 'active' : ''}`} title="Previews">
67
69
  <IconLayoutGrid size={18} />
68
70
  </Link>
69
71
  )}
@@ -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
- // Create router
276
- const routeTree = rootRoute.addChildren([previewsRoute, previewDetailRoute, ...pageRoutes])
277
- const router = createRouter({ routeTree })
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')