reroute-js 0.19.0 → 0.19.1

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.
Files changed (149) hide show
  1. package/README.md +241 -2
  2. package/cli/bin.d.ts +1 -1
  3. package/cli/bin.js +28 -23
  4. package/cli/bin.js.map +9 -9
  5. package/cli/index.d.ts +1 -1
  6. package/cli/index.js +11 -11
  7. package/cli/index.js.map +3 -3
  8. package/cli/src/cli.d.ts +1 -1
  9. package/cli/src/commands/analyze.d.ts +1 -1
  10. package/cli/src/commands/build.d.ts +1 -1
  11. package/cli/src/commands/dev.d.ts +1 -1
  12. package/cli/src/commands/gen.d.ts +1 -1
  13. package/cli/src/commands/gen.d.ts.map +1 -1
  14. package/cli/src/commands/index.d.ts +1 -1
  15. package/cli/src/commands/init.d.ts +1 -1
  16. package/cli/src/commands/lib/command.d.ts +1 -1
  17. package/cli/src/commands/lib/env.d.ts +1 -1
  18. package/cli/src/commands/lib/index.d.ts +1 -1
  19. package/cli/src/commands/lib/log.d.ts +1 -1
  20. package/cli/src/commands/lib/markdown/availability.d.ts +1 -1
  21. package/cli/src/commands/lib/markdown/index.d.ts +1 -1
  22. package/cli/src/commands/lib/markdown/processor.d.ts +1 -1
  23. package/cli/src/commands/lib/markdown/processor.d.ts.map +1 -1
  24. package/cli/src/commands/lib/production.d.ts +1 -1
  25. package/cli/src/commands/lib/server.d.ts +1 -1
  26. package/cli/src/commands/lib/streaming/analyzer.d.ts +1 -1
  27. package/cli/src/commands/lib/streaming/suspense.d.ts +1 -1
  28. package/cli/src/commands/lib/tailwind.d.ts +1 -1
  29. package/cli/src/commands/lib/version.d.ts +1 -1
  30. package/cli/src/commands/og.d.ts +1 -1
  31. package/cli/src/commands/start.d.ts +1 -1
  32. package/cli/src/index.d.ts +1 -1
  33. package/core/index.d.ts +1 -1
  34. package/core/index.js +14 -10
  35. package/core/index.js.map +7 -7
  36. package/core/src/bundler/hash.d.ts +1 -1
  37. package/core/src/bundler/index.d.ts +1 -1
  38. package/core/src/config.d.ts +1 -1
  39. package/core/src/content/discovery.d.ts +1 -1
  40. package/core/src/content/index.d.ts +1 -1
  41. package/core/src/content/metadata.d.ts +1 -1
  42. package/core/src/index.d.ts +1 -1
  43. package/core/src/llms/extractor.d.ts +1 -1
  44. package/core/src/llms/formatter.d.ts +1 -1
  45. package/core/src/llms/full-generator.d.ts +1 -1
  46. package/core/src/llms/index-generator.d.ts +1 -1
  47. package/core/src/llms/index.d.ts +1 -1
  48. package/core/src/og/discovery.d.ts +1 -1
  49. package/core/src/og/index.d.ts +1 -1
  50. package/core/src/og/meta.d.ts +1 -1
  51. package/core/src/og/render.d.ts +1 -1
  52. package/core/src/og/types.d.ts +1 -1
  53. package/core/src/robots/discovery.d.ts +1 -1
  54. package/core/src/robots/generator.d.ts +1 -1
  55. package/core/src/robots/index.d.ts +1 -1
  56. package/core/src/robots/policies.d.ts +1 -1
  57. package/core/src/rss/discovery.d.ts +1 -1
  58. package/core/src/rss/generator.d.ts +1 -1
  59. package/core/src/rss/index.d.ts +1 -1
  60. package/core/src/sitemap/discovery.d.ts +1 -1
  61. package/core/src/sitemap/generator.d.ts +1 -1
  62. package/core/src/sitemap/index.d.ts +1 -1
  63. package/core/src/ssr/index.d.ts +1 -1
  64. package/core/src/ssr/lib/cache.d.ts +1 -1
  65. package/core/src/ssr/lib/collections.d.ts +1 -1
  66. package/core/src/ssr/lib/compression.d.ts +1 -1
  67. package/core/src/ssr/lib/compute.d.ts +1 -1
  68. package/core/src/ssr/lib/data.d.ts +1 -1
  69. package/core/src/ssr/lib/html.d.ts +1 -1
  70. package/core/src/ssr/lib/index.d.ts +1 -1
  71. package/core/src/ssr/lib/metadata.d.ts +1 -1
  72. package/core/src/ssr/lib/mime.d.ts +1 -1
  73. package/core/src/ssr/lib/modules.d.ts +1 -1
  74. package/core/src/ssr/lib/modules.d.ts.map +1 -1
  75. package/core/src/ssr/lib/path.d.ts +1 -1
  76. package/core/src/ssr/lib/preload.d.ts +1 -1
  77. package/core/src/ssr/lib/scripts.d.ts +1 -1
  78. package/core/src/ssr/lib/seed.d.ts +1 -1
  79. package/core/src/ssr/lib/seed.d.ts.map +1 -1
  80. package/core/src/ssr/lib/styles.d.ts +1 -1
  81. package/core/src/ssr/lib/template.d.ts +1 -1
  82. package/core/src/ssr/lib/types.d.ts +1 -1
  83. package/core/src/ssr/render.d.ts +1 -1
  84. package/core/src/ssr/render.d.ts.map +1 -1
  85. package/core/src/ssr/stream.d.ts +1 -1
  86. package/core/src/ssr/stream.d.ts.map +1 -1
  87. package/elysia/index.d.ts +1 -1
  88. package/elysia/index.js +21 -12
  89. package/elysia/index.js.map +8 -8
  90. package/elysia/src/index.d.ts +1 -1
  91. package/elysia/src/libs/cache.d.ts +1 -1
  92. package/elysia/src/libs/http.d.ts +1 -1
  93. package/elysia/src/libs/image.d.ts +1 -1
  94. package/elysia/src/plugin.d.ts +1 -1
  95. package/elysia/src/routes/artifacts.d.ts +1 -1
  96. package/elysia/src/routes/content.d.ts +1 -1
  97. package/elysia/src/routes/image.d.ts +1 -1
  98. package/elysia/src/routes/internal.d.ts +1 -1
  99. package/elysia/src/routes/llms.d.ts +1 -1
  100. package/elysia/src/routes/og.d.ts +1 -1
  101. package/elysia/src/routes/redirects.d.ts +1 -1
  102. package/elysia/src/routes/robots.d.ts +1 -1
  103. package/elysia/src/routes/rss.d.ts +1 -1
  104. package/elysia/src/routes/search.d.ts +1 -1
  105. package/elysia/src/routes/search.d.ts.map +1 -1
  106. package/elysia/src/routes/sitemap.d.ts +1 -1
  107. package/elysia/src/routes/ssr.d.ts +1 -1
  108. package/elysia/src/routes/static.d.ts +1 -1
  109. package/elysia/src/types.d.ts +1 -1
  110. package/package.json +1 -1
  111. package/react/index.d.ts +1 -1
  112. package/react/index.js +28 -27
  113. package/react/index.js.map +4 -4
  114. package/react/src/components/ClientOnly.d.ts +1 -1
  115. package/react/src/components/ContentRoute.d.ts +1 -1
  116. package/react/src/components/Image.d.ts +1 -1
  117. package/react/src/components/LazyRoute.d.ts +1 -1
  118. package/react/src/components/Link.d.ts +1 -1
  119. package/react/src/components/Markdown.d.ts +1 -1
  120. package/react/src/components/Outlet.d.ts +1 -1
  121. package/react/src/components/index.d.ts +1 -1
  122. package/react/src/hooks/index.d.ts +1 -1
  123. package/react/src/hooks/useContent.d.ts +1 -1
  124. package/react/src/hooks/useData.d.ts +1 -1
  125. package/react/src/hooks/useFeed.d.ts +1 -1
  126. package/react/src/hooks/useLayoutData.d.ts +1 -1
  127. package/react/src/hooks/useLlms.d.ts +1 -1
  128. package/react/src/hooks/useNavigate.d.ts +1 -1
  129. package/react/src/hooks/useParams.d.ts +1 -1
  130. package/react/src/hooks/useRouter.d.ts +1 -1
  131. package/react/src/hooks/useSearch.d.ts +8 -1
  132. package/react/src/hooks/useSearch.d.ts.map +1 -1
  133. package/react/src/hooks/useSearchParams.d.ts +1 -1
  134. package/react/src/hooks/useToc.d.ts +1 -1
  135. package/react/src/index.d.ts +1 -1
  136. package/react/src/lib/collection.d.ts +1 -1
  137. package/react/src/lib/content.d.ts +1 -1
  138. package/react/src/lib/head.d.ts +1 -1
  139. package/react/src/lib/index.d.ts +1 -1
  140. package/react/src/lib/lazy-route.d.ts +1 -1
  141. package/react/src/lib/route-loader.d.ts +1 -1
  142. package/react/src/providers/ContentProvider.d.ts +1 -1
  143. package/react/src/providers/RerouteProvider.d.ts +1 -1
  144. package/react/src/providers/RouterProvider.d.ts +2 -1
  145. package/react/src/providers/RouterProvider.d.ts.map +1 -1
  146. package/react/src/providers/index.d.ts +1 -1
  147. package/react/src/types/any.d.ts +1 -1
  148. package/react/src/types/index.d.ts +1 -1
  149. package/react/src/types/router.d.ts +1 -1
package/README.md CHANGED
@@ -2,12 +2,62 @@
2
2
 
3
3
  Reroute is a dead-simple file-based routing framework for building full-stack React apps on top of Bun and Elysia.
4
4
 
5
+ ## 📚 Table of Contents
6
+
7
+ - [✨ Features](#-features)
8
+ - [🚀 Quick Start](#-quick-start)
9
+ - [🔌 External Requests SSR](#-external-requests-ssr)
10
+ - [⚡ Streaming SSR](#-streaming-ssr)
11
+ - [Quick Start](#quick-start-1)
12
+ - [How It Works](#how-it-works)
13
+ - [Custom Loading Skeletons](#custom-loading-skeletons)
14
+ - [Layout Streaming](#layout-streaming)
15
+ - [Default Skeletons](#default-skeletons)
16
+ - [Nested Suspense](#nested-suspense)
17
+ - [Performance](#performance)
18
+ - [🎭 Client-Only Rendering](#-client-only-rendering)
19
+ - [🔐 Environment Variables](#-environment-variables)
20
+ - [Usage](#usage)
21
+ - [Accessing Variables](#accessing-variables)
22
+ - [Environment Files](#environment-files)
23
+ - [Security](#security)
24
+ - [TypeScript Support](#typescript-support)
25
+ - [📝 Markdown Routes](#-markdown-routes)
26
+ - [Installation](#installation)
27
+ - [Creating Markdown Routes](#creating-markdown-routes)
28
+ - [Creating MDX Routes with Components](#creating-mdx-routes-with-components)
29
+ - [Programmatic Markdown Rendering](#programmatic-markdown-rendering)
30
+ - [🗺️ Sitemap & RSS Feed Generation](#️-sitemap--rss-feed-generation)
31
+ - [Sitemap Generation](#sitemap-generation)
32
+ - [Robots.txt Generation](#robotstxt-generation)
33
+ - [RSS Feed Generation](#rss-feed-generation)
34
+ - [LLM-Friendly Content](#llm-friendly-content)
35
+ - [🔍 Content Search](#-content-search)
36
+ - [Configuration](#configuration)
37
+ - [Client-Side Search with Pagination](#client-side-search-with-pagination)
38
+ - [SSR Search with Pagination](#ssr-search-with-pagination)
39
+ - [📑 Table of Contents](#-table-of-contents-1)
40
+ - [Basic Usage](#basic-usage)
41
+ - [Enable Anchor Scrolling](#enable-anchor-scrolling)
42
+ - [🎨 OG Image Generation](#-og-image-generation)
43
+ - [Quick Start](#quick-start)
44
+ - [File Structure](#file-structure)
45
+ - [Available Props](#available-props)
46
+ - [Styling](#styling)
47
+ - [Per-Route Customization](#per-route-customization)
48
+ - [CLI Preview](#cli-preview)
49
+ - [URLs & Meta Tags](#urls--meta-tags)
50
+ - [Default Template](#default-template)
51
+ - [📖 Learn More](#-learn-more)
52
+ - [📝 License](#-license)
53
+
5
54
  ## ✨ Features
6
55
 
7
56
  ### 🎯 Core Framework
8
57
  - ⚡ **Built on Bun** - Lightning-fast JavaScript runtime for everything
9
58
  - 🔄 **File-Based Routing** - Automatic route generation from your file structure
10
59
  - 🎨 **Server-Side Rendering (SSR)** - SEO-friendly React rendering on the server
60
+ - ⚡ **Streaming SSR** - Progressive rendering with React 19 for 50-70% faster TTFB
11
61
  - 🔥 **Live Reload** - Live reload in development mode with instant feedback
12
62
  - 📦 **Zero Config** - Works out of the box with sensible defaults
13
63
 
@@ -109,6 +159,9 @@ Reroute is a dead-simple file-based routing framework for building full-stack Re
109
159
  - ⚡ **Module Preloading** - Browser hints for critical resources
110
160
  - 🎯 **SSR Module Seeding** - Pre-populate modules for instant hydration
111
161
  - 📊 **Collection Inlining** - Inline collection data for zero-latency rendering
162
+ - 🌊 **Progressive Streaming** - Shell HTML sent immediately while data loads
163
+ - 🎭 **Automatic Suspense** - Zero-config streaming wrappers via `[skeleton].tsx` convention
164
+ - ⚡ **React 19 Streaming** - Native `renderToReadableStream` for optimal performance
112
165
 
113
166
  ### 🎨 Styling & Theming
114
167
  - 🎨 **Tailwind CSS v4 Support** - Automatic detection and compilation with CSS-first configuration
@@ -246,6 +299,194 @@ Notes:
246
299
  - Use with existing content features (useContent); both can be seeded in the same page
247
300
  - **HTTP Status Control:** Use `set.status` to set response status codes (follows Elysia's API). Non-200 responses are not cached
248
301
 
302
+ ## ⚡ Streaming SSR
303
+
304
+ Reroute supports progressive server-side rendering with React 19's streaming capabilities. Routes with async data automatically stream shell content immediately (50-70% faster TTFB), then progressively send content as it becomes ready.
305
+
306
+ ### Quick Start
307
+
308
+ Enable streaming in your config:
309
+
310
+ ```typescript
311
+ // reroute.config.ts
312
+ import { defineConfig } from 'reroute-js/core';
313
+
314
+ export default defineConfig({
315
+ options: {
316
+ app: './src/client/App',
317
+ },
318
+ streaming: {
319
+ enabled: true,
320
+ },
321
+ });
322
+ ```
323
+
324
+ Run `bun gen` and routes with `ssr.data` automatically get Suspense wrappers and streaming optimization - no code changes needed!
325
+
326
+ ### How It Works
327
+
328
+ **Without streaming (default):**
329
+ - Server waits for all data → sends complete HTML → user sees page
330
+
331
+ **With streaming:**
332
+ 1. Server sends shell HTML immediately (layouts, navigation) - **instant TTFB**
333
+ 2. Shows loading skeleton while data fetches
334
+ 3. Streams content progressively as ready
335
+ 4. User sees something immediately, perceives faster load
336
+
337
+ ### Custom Loading Skeletons
338
+
339
+ Create custom loading states using the `[skeleton].tsx` convention:
340
+
341
+ ```tsx
342
+ // routes/blog/[slug].tsx
343
+ export const ssr = {
344
+ async data({ params }) {
345
+ return { post: await fetchPost(params.slug) };
346
+ }
347
+ };
348
+
349
+ export default function BlogPost() {
350
+ const { post } = useData();
351
+ return <article>{post.title}</article>;
352
+ }
353
+ ```
354
+
355
+ ```tsx
356
+ // routes/blog/[skeleton].tsx
357
+ export default function BlogSkeleton() {
358
+ return (
359
+ <div className="animate-pulse p-8">
360
+ <div className="h-8 bg-gray-200 rounded w-3/4 mb-4" />
361
+ <div className="space-y-3">
362
+ <div className="h-4 bg-gray-200 rounded" />
363
+ <div className="h-4 bg-gray-200 rounded" />
364
+ </div>
365
+ </div>
366
+ );
367
+ }
368
+ ```
369
+
370
+ The CLI automatically detects `[skeleton].tsx` files and uses them in generated Suspense boundaries.
371
+
372
+ ### Layout Streaming
373
+
374
+ Layouts can also stream with their own data and skeletons:
375
+
376
+ ```tsx
377
+ // routes/dashboard/[layout].tsx
378
+ export const ssr = {
379
+ async data() {
380
+ return { user: await fetchUser() };
381
+ }
382
+ };
383
+
384
+ export default function DashboardLayout() {
385
+ const { user } = useLayoutData();
386
+ return (
387
+ <div>
388
+ <nav>Welcome, {user.name}</nav>
389
+ <Outlet />
390
+ </div>
391
+ );
392
+ }
393
+ ```
394
+
395
+ ```tsx
396
+ // routes/dashboard/[layout+skeleton].tsx
397
+ export default function DashboardLayoutSkeleton() {
398
+ return <div className="animate-pulse">Loading dashboard...</div>;
399
+ }
400
+ ```
401
+
402
+ **Streaming order:**
403
+ 1. Shell HTML → instant
404
+ 2. Layout skeleton → while layout data loads
405
+ 3. Layout content → when ready
406
+ 4. Route skeleton → while route data loads
407
+ 5. Route content → when ready
408
+
409
+ ### Default Skeletons
410
+
411
+ Configure app-wide default skeletons:
412
+
413
+ ```typescript
414
+ // reroute.config.ts
415
+ export default defineConfig({
416
+ streaming: {
417
+ enabled: true,
418
+ defaultSkeleton: './src/client/components/DefaultSkeleton',
419
+ defaultLayoutSkeleton: './src/client/components/LayoutSkeleton',
420
+ },
421
+ });
422
+ ```
423
+
424
+ **Priority order:**
425
+ 1. Custom `[skeleton].tsx` in route directory
426
+ 2. Configured `defaultSkeleton`
427
+ 3. Built-in generic skeleton
428
+
429
+ For layouts:
430
+ 1. Custom `[layout+skeleton].tsx`
431
+ 2. Configured `defaultLayoutSkeleton`
432
+ 3. Falls back to `defaultSkeleton`
433
+ 4. Built-in generic skeleton
434
+
435
+ ### Nested Suspense
436
+
437
+ Add your own Suspense boundaries for fine-grained streaming:
438
+
439
+ ```tsx
440
+ // routes/feed.tsx
441
+ import { Suspense } from 'react';
442
+
443
+ export const ssr = {
444
+ async data() {
445
+ return { posts: await fetchPosts() };
446
+ }
447
+ };
448
+
449
+ export default function Feed() {
450
+ const { posts } = useData();
451
+
452
+ return (
453
+ <div>
454
+ <h1>Feed</h1>
455
+ {/* Route-level Suspense added automatically by gen */}
456
+ {posts.map(post => (
457
+ <article key={post.id}>
458
+ <h2>{post.title}</h2>
459
+ {/* Component-level Suspense you can add manually */}
460
+ <Suspense fallback={<div>Loading comments...</div>}>
461
+ <Comments postId={post.id} />
462
+ </Suspense>
463
+ </article>
464
+ ))}
465
+ </div>
466
+ );
467
+ }
468
+ ```
469
+
470
+ Each Suspense boundary streams independently - shell renders first, then each boundary resolves progressively.
471
+
472
+ ### Performance
473
+
474
+ Example improvements with streaming enabled:
475
+
476
+ | Metric | Without Streaming | With Streaming | Improvement |
477
+ |--------|-------------------|----------------|-------------|
478
+ | TTFB | 400ms | 50ms | **87% faster** |
479
+ | FCP | 600ms | 150ms | **75% faster** |
480
+
481
+ ### Example
482
+
483
+ Check out `examples/streaming` for a comprehensive demo with:
484
+ - Basic streaming routes
485
+ - Custom skeletons
486
+ - Layout streaming
487
+ - Nested Suspense boundaries
488
+ - Performance comparisons
489
+
249
490
  ## 🎭 Client-Only Rendering
250
491
 
251
492
  The `ClientOnly` component prevents hydration mismatches for browser-specific code and supports layout preservation to prevent flickering:
@@ -421,8 +662,6 @@ We strive to create the best developer experience possible.
421
662
  const greeting = "Hello, World!";
422
663
  console.log(greeting);
423
664
  ```
424
-
425
- Check out our [documentation](/docs) for more info!
426
665
  ```
427
666
 
428
667
  The route will be automatically available at `/about` with:
package/cli/bin.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * reroute-js v0.19.0
2
+ * reroute-js v0.19.1
3
3
  *
4
4
  * @license MIT
5
5
  * @copyright 2025 stewones <hi@stewan.io>
package/cli/bin.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bun
2
2
  // @bun
3
3
  /**
4
- * reroute-js v0.19.0
4
+ * reroute-js v0.19.1
5
5
  *
6
6
  * @license MIT
7
7
  * @copyright 2025 stewones <hi@stewan.io>
@@ -48,7 +48,7 @@ async function getVersionString() {
48
48
  }
49
49
  async function getVersion() {
50
50
  if (true) {
51
- return "0.19.0";
51
+ return "0.19.1";
52
52
  }
53
53
  const possiblePaths = [
54
54
  path.join(import.meta.dir, "../../../../package.json"),
@@ -66,7 +66,7 @@ async function getVersion() {
66
66
  }
67
67
  async function getCommit() {
68
68
  if (true) {
69
- return "b887fc0";
69
+ return "a30c30e";
70
70
  }
71
71
  return "dev";
72
72
  }
@@ -1129,7 +1129,8 @@ import { readdir as readdir3, stat as stat3 } from "node:fs/promises";
1129
1129
  import { pathToFileURL as pathToFileURL5 } from "node:url";
1130
1130
  async function importContentModuleForPath(pathname, clientDir, cwd, isWatchMode) {
1131
1131
  try {
1132
- const parts = pathname.split("/").filter(Boolean);
1132
+ const pathOnly = pathname.split("?")[0].split("#")[0];
1133
+ const parts = pathOnly.split("/").filter(Boolean);
1133
1134
  if (parts.length < 2)
1134
1135
  return null;
1135
1136
  const collection = parts[0];
@@ -1205,7 +1206,8 @@ var init_modules = () => {};
1205
1206
  // packages/core/src/ssr/lib/seed.ts
1206
1207
  async function seedSSRModuleForPath(pathname, clientDir, cwd, isWatchMode) {
1207
1208
  try {
1208
- const parts = pathname.split("/").filter(Boolean);
1209
+ const pathOnly = pathname.split("?")[0].split("#")[0];
1210
+ const parts = pathOnly.split("/").filter(Boolean);
1209
1211
  if (parts.length < 2)
1210
1212
  return;
1211
1213
  const collection = parts[0];
@@ -1761,11 +1763,11 @@ async function preloadContentModule(pathname, clientDir, cwd, isWatchMode) {
1761
1763
  let hydrationScript = "";
1762
1764
  let statusOverride;
1763
1765
  try {
1764
- const parts = pathname.split("/").filter(Boolean);
1765
- const pathnameOnly = parts[0]?.split("?")[0];
1766
+ const pathOnly = pathname.split("?")[0].split("#")[0];
1767
+ const parts = pathOnly.split("/").filter(Boolean);
1766
1768
  if (parts.length >= 2) {
1767
- const collection = pathnameOnly || parts[0];
1768
- const name = parts[1]?.split("?")[0];
1769
+ const collection = parts[0];
1770
+ const name = parts[1];
1769
1771
  let modulePath = "";
1770
1772
  let isContentCollection = false;
1771
1773
  try {
@@ -2100,7 +2102,8 @@ async function renderSSRDocument(options2) {
2100
2102
  const __byCollectionForSSR = await loadCollections(cwd, isWatchMode);
2101
2103
  setGlobalCollections(__byCollectionForSSR);
2102
2104
  const componentWithPathname = cloneElement(rootComponent, {
2103
- pathname
2105
+ pathname,
2106
+ searchParams: options2.searchParams
2104
2107
  });
2105
2108
  const appHtml = renderToString(componentWithPathname);
2106
2109
  const baseTemplate = await loadIndexHtml(clientDir);
@@ -3906,7 +3909,8 @@ ${combinedHead}` : ""}</head><body>`;
3906
3909
  await writer.write(encoder.encode(headContent));
3907
3910
  await writer.write(encoder.encode(rootStart));
3908
3911
  const componentWithPathname = cloneElement2(rootComponent, {
3909
- pathname
3912
+ pathname,
3913
+ searchParams: options2.searchParams
3910
3914
  });
3911
3915
  let streamError = null;
3912
3916
  const streamPromise = renderToReadableStream(componentWithPathname, {
@@ -8081,19 +8085,19 @@ function extractHeadings(content2, options2 = {}) {
8081
8085
  let match = headingRegex.exec(content2);
8082
8086
  while (match !== null) {
8083
8087
  const level = match[1].length;
8084
- if (level < minLevel || level > maxLevel)
8085
- continue;
8086
- const text = match[2].trim();
8087
- const slug = text.toLowerCase().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").trim();
8088
- headings.push({ level, text, slug });
8088
+ if (level >= minLevel && level <= maxLevel) {
8089
+ const text = match[2].trim();
8090
+ const slug = text.toLowerCase().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").trim();
8091
+ headings.push({ level, text, slug });
8092
+ }
8089
8093
  match = headingRegex.exec(content2);
8090
8094
  }
8091
8095
  return headings;
8092
8096
  }
8093
8097
  function stripMarkdown(content2) {
8094
8098
  let text = content2;
8095
- text = text.replace(/```[\s\S]*?```/g, "");
8096
- text = text.replace(/`[^`]+`/g, "");
8099
+ text = text.replace(/```(?:\w+)?\n?([\s\S]*?)```/g, "$1");
8100
+ text = text.replace(/`([^`]+)`/g, "$1");
8097
8101
  text = text.replace(/<[^>]+>/g, "");
8098
8102
  text = text.replace(/!\[([^\]]*)\]\([^)]+\)/g, "$1");
8099
8103
  text = text.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1");
@@ -9164,8 +9168,9 @@ async function generate(cwd, args = [], options2 = {}) {
9164
9168
  const stepStart = performance.now();
9165
9169
  const result = await fn();
9166
9170
  if (showPerformance) {
9167
- const stepTime = ((performance.now() - stepStart) / 1000).toFixed(2);
9168
- console.log(`[reroute/gen] ├─ ${name}: ${stepTime}s`);
9171
+ const elapsedMs = performance.now() - stepStart;
9172
+ const timeStr = elapsedMs < 1000 ? `${elapsedMs.toFixed(0)}ms` : `${(elapsedMs / 1000).toFixed(2)}s`;
9173
+ console.log(`[reroute/gen] ├─ ${name}: ${timeStr}`);
9169
9174
  }
9170
9175
  return result;
9171
9176
  };
@@ -12786,7 +12791,7 @@ async function getVersionString2() {
12786
12791
  }
12787
12792
  async function getVersion2() {
12788
12793
  if (true) {
12789
- return "0.19.0";
12794
+ return "0.19.1";
12790
12795
  }
12791
12796
  const possiblePaths = [
12792
12797
  path3.join(import.meta.dir, "../../../package.json"),
@@ -12803,10 +12808,10 @@ async function getVersion2() {
12803
12808
  }
12804
12809
  async function getCommit2() {
12805
12810
  if (true) {
12806
- return "b887fc0";
12811
+ return "a30c30e";
12807
12812
  }
12808
12813
  return "dev";
12809
12814
  }
12810
12815
  main();
12811
12816
 
12812
- //# debugId=62B8EC966ED29FA464756E2164756E21
12817
+ //# debugId=82FF244554ABAB6064756E2164756E21