reroute-js 0.4.4 → 0.6.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.
Files changed (92) hide show
  1. package/README.md +141 -0
  2. package/cli/bin.d.ts +1 -1
  3. package/cli/bin.js +513 -66
  4. package/cli/bin.js.map +6 -4
  5. package/cli/index.d.ts +1 -1
  6. package/cli/index.js +378 -16
  7. package/cli/index.js.map +5 -3
  8. package/cli/src/cli.d.ts +1 -1
  9. package/cli/src/commands/boot.d.ts +1 -1
  10. package/cli/src/commands/gen.d.ts +1 -1
  11. package/cli/src/commands/gen.d.ts.map +1 -1
  12. package/cli/src/commands/init.d.ts +1 -1
  13. package/cli/src/libs/index.d.ts +3 -1
  14. package/cli/src/libs/index.d.ts.map +1 -1
  15. package/cli/src/libs/markdown-processor.d.ts +59 -0
  16. package/cli/src/libs/markdown-processor.d.ts.map +1 -0
  17. package/cli/src/libs/markdown.d.ts +33 -0
  18. package/cli/src/libs/markdown.d.ts.map +1 -0
  19. package/cli/src/libs/tailwind.d.ts +1 -1
  20. package/cli/src/libs/version.d.ts +1 -1
  21. package/core/index.d.ts +1 -1
  22. package/core/index.js +3 -3
  23. package/core/index.js.map +2 -2
  24. package/core/src/bundler/hash.d.ts +1 -1
  25. package/core/src/bundler/index.d.ts +1 -1
  26. package/core/src/bundler/transpile.d.ts +1 -1
  27. package/core/src/content/discovery.d.ts +1 -1
  28. package/core/src/content/index.d.ts +1 -1
  29. package/core/src/content/metadata.d.ts +1 -1
  30. package/core/src/content/registry.d.ts +1 -1
  31. package/core/src/index.d.ts +1 -1
  32. package/core/src/ssr/data.d.ts +1 -1
  33. package/core/src/ssr/index.d.ts +1 -1
  34. package/core/src/ssr/modules.d.ts +1 -1
  35. package/core/src/ssr/render.d.ts +1 -1
  36. package/core/src/ssr/seed.d.ts +1 -1
  37. package/core/src/template/html.d.ts +1 -1
  38. package/core/src/template/index.d.ts +1 -1
  39. package/core/src/types.d.ts +1 -1
  40. package/core/src/utils/cache.d.ts +1 -1
  41. package/core/src/utils/compression.d.ts +1 -1
  42. package/core/src/utils/index.d.ts +1 -1
  43. package/core/src/utils/mime.d.ts +1 -1
  44. package/core/src/utils/path.d.ts +1 -1
  45. package/elysia/index.d.ts +1 -1
  46. package/elysia/index.js +3 -3
  47. package/elysia/index.js.map +2 -2
  48. package/elysia/src/index.d.ts +1 -1
  49. package/elysia/src/libs/http.d.ts +1 -1
  50. package/elysia/src/libs/image.d.ts +1 -1
  51. package/elysia/src/plugin.d.ts +1 -1
  52. package/elysia/src/routes/artifacts.d.ts +1 -1
  53. package/elysia/src/routes/content.d.ts +1 -1
  54. package/elysia/src/routes/dev.d.ts +1 -1
  55. package/elysia/src/routes/image.d.ts +1 -1
  56. package/elysia/src/routes/ssr.d.ts +1 -1
  57. package/elysia/src/routes/static.d.ts +1 -1
  58. package/elysia/src/types.d.ts +1 -1
  59. package/package.json +17 -9
  60. package/react/index.d.ts +1 -1
  61. package/react/index.js +163 -66
  62. package/react/index.js.map +7 -5
  63. package/react/src/components/ClientOnly.d.ts +31 -0
  64. package/react/src/components/ClientOnly.d.ts.map +1 -0
  65. package/react/src/components/ContentRoute.d.ts +1 -1
  66. package/react/src/components/ContentRoute.d.ts.map +1 -1
  67. package/react/src/components/Image.d.ts +1 -1
  68. package/react/src/components/Link.d.ts +1 -1
  69. package/react/src/components/Link.d.ts.map +1 -1
  70. package/react/src/components/Markdown.d.ts +89 -0
  71. package/react/src/components/Markdown.d.ts.map +1 -0
  72. package/react/src/components/Outlet.d.ts +1 -1
  73. package/react/src/components/index.d.ts +3 -1
  74. package/react/src/components/index.d.ts.map +1 -1
  75. package/react/src/hooks/index.d.ts +1 -1
  76. package/react/src/hooks/useContent.d.ts +1 -1
  77. package/react/src/hooks/useData.d.ts +1 -1
  78. package/react/src/hooks/useNavigate.d.ts +1 -1
  79. package/react/src/hooks/useParams.d.ts +1 -1
  80. package/react/src/hooks/useRouter.d.ts +1 -1
  81. package/react/src/hooks/useSearchParams.d.ts +1 -1
  82. package/react/src/index.d.ts +1 -1
  83. package/react/src/providers/ContentProvider.d.ts +1 -1
  84. package/react/src/providers/RerouteProvider.d.ts +1 -1
  85. package/react/src/providers/RouterProvider.d.ts +1 -1
  86. package/react/src/providers/index.d.ts +1 -1
  87. package/react/src/types/any.d.ts +1 -1
  88. package/react/src/types/index.d.ts +1 -1
  89. package/react/src/types/router.d.ts +1 -1
  90. package/react/src/utils/content.d.ts +1 -1
  91. package/react/src/utils/head.d.ts +1 -1
  92. package/react/src/utils/index.d.ts +1 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * reroute-js v0.4.4
2
+ * reroute-js v0.6.0
3
3
  *
4
4
  * @license MIT
5
5
  * @copyright 2025 stewones <hi@stewan.io>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reroute-js",
3
- "version": "0.4.4",
3
+ "version": "0.6.0",
4
4
  "type": "module",
5
5
  "author": "stewones <hi@stewan.io>",
6
6
  "scripts": {
@@ -70,30 +70,38 @@
70
70
  "CHANGELOG.md"
71
71
  ],
72
72
  "devDependencies": {
73
- "@biomejs/biome": "^2.3.3",
73
+ "@biomejs/biome": "^2.3.4",
74
74
  "@semantic-release/changelog": "^6.0.3",
75
75
  "@semantic-release/exec": "^6.0.3",
76
76
  "@semantic-release/git": "^10.0.1",
77
77
  "@semantic-release/github": "^12.0.1",
78
78
  "@tailwindcss/cli": "^4.1.16",
79
79
  "@types/bun": "latest",
80
+ "@types/node": "^24.10.0",
81
+ "@types/react": "^19.2.2",
80
82
  "@types/react-dom": "^19.2.2",
81
83
  "@vitest/coverage-v8": "^3.2.4",
82
84
  "conventional-changelog-conventionalcommits": "^9.1.0",
83
85
  "dedent": "^1.7.0",
84
- "knip": "^5.66.3",
85
- "react": "^19.2.0",
86
- "react-dom": "^19.2.0",
86
+ "knip": "^5.68.0",
87
87
  "semantic-release": "^24.2.8",
88
88
  "vite-tsconfig-paths": "^5.1.4",
89
89
  "vitest": "^3.2.4"
90
90
  },
91
91
  "peerDependencies": {
92
- "typescript": "^5",
93
- "tailwindcss": "^4.1.16",
92
+ "@mdx-js/mdx": "^3.1.0",
93
+ "@shikijs/rehype": "^1.0.0",
94
94
  "elysia": "^1.4.12",
95
95
  "react": "^19.2.0",
96
96
  "react-dom": "^19.2.0",
97
- "sharp": "^0.34.4"
98
- }
97
+ "react-markdown": "^10.1.0",
98
+ "remark-gfm": "^4.0.0",
99
+ "sharp": "^0.34.4",
100
+ "tailwindcss": "^4.1.16",
101
+ "typescript": "^5"
102
+ },
103
+ "workspaces": [
104
+ "packages/*",
105
+ "examples/*"
106
+ ]
99
107
  }
package/react/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * reroute-js v0.4.4
2
+ * reroute-js v0.6.0
3
3
  *
4
4
  * @license MIT
5
5
  * @copyright 2025 stewones <hi@stewan.io>
package/react/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * reroute-js v0.4.4
2
+ * reroute-js v0.6.0
3
3
  *
4
4
  * @license MIT
5
5
  * @copyright 2025 stewones <hi@stewan.io>
@@ -8,16 +8,34 @@
8
8
  * Built with Bun <3
9
9
  */
10
10
 
11
+ // packages/react/src/components/ClientOnly.tsx
12
+ import { useEffect, useState } from "react";
13
+ import { jsx, Fragment } from "react/jsx-runtime";
14
+ function ClientOnly({ children, fallback = null }) {
15
+ const [mounted, setMounted] = useState(false);
16
+ useEffect(() => {
17
+ setMounted(true);
18
+ }, []);
19
+ if (!mounted) {
20
+ return /* @__PURE__ */ jsx(Fragment, {
21
+ children: fallback
22
+ });
23
+ }
24
+ return /* @__PURE__ */ jsx(Fragment, {
25
+ children
26
+ });
27
+ }
11
28
  // packages/react/src/components/ContentRoute.tsx
12
29
  import {
13
30
  isValidElement,
14
- useEffect as useEffect4,
31
+ useEffect as useEffect5,
15
32
  useMemo as useMemo5,
16
- useState as useState4
33
+ useRef,
34
+ useState as useState5
17
35
  } from "react";
18
36
 
19
37
  // packages/react/src/hooks/useContent.ts
20
- import { useCallback as useCallback2, useEffect, useMemo as useMemo2, useState as useState2 } from "react";
38
+ import { useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo2, useState as useState3 } from "react";
21
39
 
22
40
  // packages/react/src/providers/ContentProvider.tsx
23
41
  import {
@@ -25,7 +43,7 @@ import {
25
43
  useCallback,
26
44
  useContext,
27
45
  useMemo,
28
- useState
46
+ useState as useState2
29
47
  } from "react";
30
48
 
31
49
  // packages/react/src/utils/content.ts
@@ -58,7 +76,7 @@ function createResolverFromGetEntry(getEntry) {
58
76
  }
59
77
 
60
78
  // packages/react/src/providers/ContentProvider.tsx
61
- import { jsx } from "react/jsx-runtime";
79
+ import { jsx as jsx2 } from "react/jsx-runtime";
62
80
  var ContentRegistryContext = createContext(null);
63
81
  var ContentIndexContext = createContext(null);
64
82
  var ContentGetEntryContext = createContext(null);
@@ -70,7 +88,7 @@ function ContentProvider({
70
88
  byCollection,
71
89
  loadCollection
72
90
  }) {
73
- const [idx, setIdx] = useState(() => {
91
+ const [idx, setIdx] = useState2(() => {
74
92
  const seededClient = (() => {
75
93
  try {
76
94
  if (typeof window !== "undefined") {
@@ -135,13 +153,13 @@ function ContentProvider({
135
153
  return;
136
154
  }
137
155
  }, [idx, loadCollection]);
138
- return /* @__PURE__ */ jsx(ContentRegistryContext.Provider, {
156
+ return /* @__PURE__ */ jsx2(ContentRegistryContext.Provider, {
139
157
  value: resolver,
140
- children: /* @__PURE__ */ jsx(ContentIndexContext.Provider, {
158
+ children: /* @__PURE__ */ jsx2(ContentIndexContext.Provider, {
141
159
  value: idx,
142
- children: /* @__PURE__ */ jsx(ContentGetEntryContext.Provider, {
160
+ children: /* @__PURE__ */ jsx2(ContentGetEntryContext.Provider, {
143
161
  value: entryFn,
144
- children: /* @__PURE__ */ jsx(ContentLoadCollectionContext.Provider, {
162
+ children: /* @__PURE__ */ jsx2(ContentLoadCollectionContext.Provider, {
145
163
  value: ensureCollection,
146
164
  children
147
165
  })
@@ -210,8 +228,8 @@ function useContent(params) {
210
228
  } catch {}
211
229
  const index = useContentIndex();
212
230
  const loadCollection = useContentLoadCollection();
213
- const [_ready, setReady] = useState2(false);
214
- useEffect(() => {
231
+ const [_ready, setReady] = useState3(false);
232
+ useEffect2(() => {
215
233
  let cancelled = false;
216
234
  async function ensure() {
217
235
  try {
@@ -253,7 +271,7 @@ function useContent(params) {
253
271
  return { items, prefetch };
254
272
  }
255
273
  // packages/react/src/hooks/useData.ts
256
- import { useEffect as useEffect3, useMemo as useMemo4, useState as useState3 } from "react";
274
+ import { useEffect as useEffect4, useMemo as useMemo4, useState as useState4 } from "react";
257
275
 
258
276
  // packages/react/src/hooks/useRouter.tsx
259
277
  import { useContext as useContext2 } from "react";
@@ -261,7 +279,7 @@ import { useContext as useContext2 } from "react";
261
279
  import React, {
262
280
  createContext as createContext2,
263
281
  useCallback as useCallback3,
264
- useEffect as useEffect2,
282
+ useEffect as useEffect3,
265
283
  useMemo as useMemo3,
266
284
  useSyncExternalStore
267
285
  } from "react";
@@ -353,7 +371,7 @@ function applyRouteHead(head) {
353
371
  }
354
372
 
355
373
  // packages/react/src/providers/RouterProvider.tsx
356
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
374
+ import { jsx as jsx3, jsxs } from "react/jsx-runtime";
357
375
  var isBrowser2 = typeof window !== "undefined" && typeof window.document !== "undefined";
358
376
  var OutletContext = createContext2(null);
359
377
  var RouterContext = createContext2(null);
@@ -458,7 +476,7 @@ function RouterProvider({
458
476
  viewTransitions = true,
459
477
  scrollRestoration = true
460
478
  }) {
461
- useEffect2(() => {
479
+ useEffect3(() => {
462
480
  setViewTransitionsEnabled(viewTransitions);
463
481
  setScrollRestorationEnabled(scrollRestoration);
464
482
  }, [viewTransitions, scrollRestoration]);
@@ -472,7 +490,7 @@ function RouterProvider({
472
490
  }
473
491
  const getServerSnapshot = useCallback3(() => serverSnapshotRef.current, []);
474
492
  const location = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) || currentLocation;
475
- useEffect2(() => {
493
+ useEffect3(() => {
476
494
  if (!isBrowser2)
477
495
  return;
478
496
  const next = {
@@ -491,7 +509,7 @@ function RouterProvider({
491
509
  const navigate = useCallback3((to, options = {}) => {
492
510
  navigateInternal(to, options);
493
511
  }, []);
494
- useEffect2(() => {
512
+ useEffect3(() => {
495
513
  if (!isBrowser2)
496
514
  return;
497
515
  const handlePopState = () => {
@@ -574,7 +592,7 @@ function RouterProvider({
574
592
  window.addEventListener("popstate", handlePopState);
575
593
  return () => window.removeEventListener("popstate", handlePopState);
576
594
  }, [matchRoute]);
577
- useEffect2(() => {
595
+ useEffect3(() => {
578
596
  if (!isBrowser2)
579
597
  return;
580
598
  const handleClick = (e) => {
@@ -599,7 +617,7 @@ function RouterProvider({
599
617
  document.addEventListener("click", handleClick);
600
618
  return () => document.removeEventListener("click", handleClick);
601
619
  }, [navigate, matchRoute]);
602
- useEffect2(() => {
620
+ useEffect3(() => {
603
621
  const route = target?.route;
604
622
  if (!route)
605
623
  return;
@@ -667,25 +685,25 @@ function RouterProvider({
667
685
  let content;
668
686
  if (target) {
669
687
  const Component = target.route.component;
670
- let outletContent = /* @__PURE__ */ jsx2(Component, {});
688
+ let outletContent = /* @__PURE__ */ jsx3(Component, {});
671
689
  for (let i = matchingLayouts.length - 1;i >= 0; i--) {
672
690
  const Layout = matchingLayouts[i].component;
673
691
  const currentOutlet = outletContent;
674
- outletContent = /* @__PURE__ */ jsx2(OutletContext.Provider, {
692
+ outletContent = /* @__PURE__ */ jsx3(OutletContext.Provider, {
675
693
  value: currentOutlet,
676
- children: /* @__PURE__ */ jsx2(Layout, {})
694
+ children: /* @__PURE__ */ jsx3(Layout, {})
677
695
  });
678
696
  }
679
697
  content = outletContent;
680
698
  } else {
681
699
  const Fallback = notFoundResolver(location.pathname) || NotFound;
682
700
  if (Fallback) {
683
- content = /* @__PURE__ */ jsx2(Fallback, {});
701
+ content = /* @__PURE__ */ jsx3(Fallback, {});
684
702
  } else {
685
703
  content = /* @__PURE__ */ jsxs("div", {
686
704
  style: { padding: "2rem", textAlign: "center" },
687
705
  children: [
688
- /* @__PURE__ */ jsx2("h1", {
706
+ /* @__PURE__ */ jsx3("h1", {
689
707
  children: "404 - Page Not Found"
690
708
  }),
691
709
  /* @__PURE__ */ jsxs("p", {
@@ -695,7 +713,7 @@ function RouterProvider({
695
713
  " could not be found."
696
714
  ]
697
715
  }),
698
- /* @__PURE__ */ jsx2("a", {
716
+ /* @__PURE__ */ jsx3("a", {
699
717
  href: "/",
700
718
  children: "Go Home"
701
719
  })
@@ -703,14 +721,14 @@ function RouterProvider({
703
721
  });
704
722
  }
705
723
  }
706
- return /* @__PURE__ */ jsx2(RouterContext.Provider, {
724
+ return /* @__PURE__ */ jsx3(RouterContext.Provider, {
707
725
  value: contextValue,
708
726
  children: children || content
709
727
  });
710
728
  }
711
729
 
712
730
  // packages/react/src/providers/RerouteProvider.tsx
713
- import { jsx as jsx3 } from "react/jsx-runtime";
731
+ import { jsx as jsx4 } from "react/jsx-runtime";
714
732
  function RerouteProvider({
715
733
  from,
716
734
  children
@@ -729,11 +747,11 @@ function RerouteProvider({
729
747
  scrollRestoration
730
748
  } = from;
731
749
  const loader = loadContent || (contentBaseUrl ? (c) => import(`${contentBaseUrl}/${c}.js`) : undefined);
732
- return /* @__PURE__ */ jsx3(ContentProvider, {
750
+ return /* @__PURE__ */ jsx4(ContentProvider, {
733
751
  getEntry: getContentEntry,
734
752
  byCollection: byCollection || null,
735
753
  loadCollection: loader,
736
- children: /* @__PURE__ */ jsx3(RouterProvider, {
754
+ children: /* @__PURE__ */ jsx4(RouterProvider, {
737
755
  layouts,
738
756
  matchRoute,
739
757
  notFoundRoutes,
@@ -758,8 +776,8 @@ function useRouter() {
758
776
  function useData(key) {
759
777
  const { pathname } = useRouter();
760
778
  const k = key || pathname;
761
- const [_tick, setTick] = useState3(0);
762
- useEffect3(() => {
779
+ const [_tick, setTick] = useState4(0);
780
+ useEffect4(() => {
763
781
  if (typeof window === "undefined")
764
782
  return;
765
783
  const handler = (e) => {
@@ -777,7 +795,7 @@ function useData(key) {
777
795
  } catch {}
778
796
  };
779
797
  }, [k]);
780
- useEffect3(() => {
798
+ useEffect4(() => {
781
799
  if (typeof window === "undefined")
782
800
  return;
783
801
  try {
@@ -841,7 +859,7 @@ function useSearchParams() {
841
859
  return searchParams;
842
860
  }
843
861
  // packages/react/src/components/ContentRoute.tsx
844
- import { jsx as jsx4 } from "react/jsx-runtime";
862
+ import { jsx as jsx5 } from "react/jsx-runtime";
845
863
  function toComponent(x) {
846
864
  if (typeof x === "function")
847
865
  return x;
@@ -867,6 +885,7 @@ function ContentRoute({
867
885
  const key = inferredName ? `${collection}:${inferredName}` : `${collection}:`;
868
886
  const ctxGetEntry = useContentGetEntry();
869
887
  const idx = useContentIndex();
888
+ const ensureCollection = useContentLoadCollection();
870
889
  const resolveEntry = getEntry || ctxGetEntry || ((c, n) => {
871
890
  try {
872
891
  const list = idx?.[c];
@@ -902,8 +921,9 @@ function ContentRoute({
902
921
  } catch {}
903
922
  return () => null;
904
923
  }, [key, entry]);
905
- const [Comp, setComp] = useState4(() => initialComp);
906
- useEffect4(() => {
924
+ const [Comp, setComp] = useState5(() => initialComp);
925
+ const containerRef = useRef(null);
926
+ useEffect5(() => {
907
927
  let cancelled = false;
908
928
  if (entry?.module && typeof window !== "undefined") {
909
929
  import(entry.module).then((m) => {
@@ -934,21 +954,62 @@ function ContentRoute({
934
954
  applySsrHead(undefined);
935
955
  };
936
956
  }, [entry?.module, key]);
937
- useEffect4(() => {
957
+ useEffect5(() => {
958
+ if (typeof window === "undefined")
959
+ return;
960
+ if (entry || !collection)
961
+ return;
962
+ try {
963
+ if (typeof ensureCollection === "function") {
964
+ ensureCollection(collection);
965
+ }
966
+ } catch {}
967
+ }, [collection, ensureCollection, entry]);
968
+ useEffect5(() => {
938
969
  try {
939
970
  if (entry && entry.meta)
940
971
  applyPageMeta(entry.meta);
941
972
  } catch {}
942
973
  }, [entry]);
943
- return /* @__PURE__ */ jsx4(Comp, {});
974
+ useEffect5(() => {
975
+ try {
976
+ if (typeof window === "undefined")
977
+ return;
978
+ const isDev = typeof process !== "undefined" && (process.env?.NODE_ENV ?? "development") !== "production" || typeof document !== "undefined" && /^localhost|^127\.0\.0\.1/.test(window.location.hostname);
979
+ if (!isDev)
980
+ return;
981
+ const root = containerRef.current;
982
+ if (!root)
983
+ return;
984
+ const nested = root.querySelectorAll("p p");
985
+ if (!nested.length) {
986
+ return;
987
+ }
988
+ console.groupCollapsed(`[Reroute] DOM check: nested <p> found in ContentRoute (${key})`);
989
+ nested.forEach((inner, idx2) => {
990
+ const outer = inner.closest("p");
991
+ const snippet = (el) => (el?.textContent || "").replace(/\s+/g, " ").trim().slice(0, 160);
992
+ console.warn(`Case ${idx2 + 1}:`, {
993
+ outerSnippet: snippet(outer),
994
+ innerSnippet: snippet(inner)
995
+ });
996
+ });
997
+ console.groupEnd();
998
+ } catch {}
999
+ }, [key]);
1000
+ return /* @__PURE__ */ jsx5("div", {
1001
+ "data-reroute": "content",
1002
+ ref: containerRef,
1003
+ children: /* @__PURE__ */ jsx5(Comp, {})
1004
+ });
944
1005
  }
945
1006
  // packages/react/src/components/Image.tsx
946
1007
  import {
947
- useEffect as useEffect5,
948
- useRef,
949
- useState as useState5
1008
+ useEffect as useEffect6,
1009
+ useRef as useRef2,
1010
+ useState as useState6
950
1011
  } from "react";
951
- import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
1012
+ import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
952
1013
  var DEFAULT_DEVICE_SIZES = [640, 750, 828, 1080, 1200, 1920, 2048, 3840];
953
1014
  function generateSrcSet(src, width, quality, format, loader) {
954
1015
  const sizes = width ? DEFAULT_DEVICE_SIZES.filter((size) => size <= width * 2) : DEFAULT_DEVICE_SIZES;
@@ -1004,11 +1065,11 @@ function Image({
1004
1065
  className,
1005
1066
  ...props
1006
1067
  }) {
1007
- const [isLoaded, setIsLoaded] = useState5(false);
1008
- const [hasError, setHasError] = useState5(false);
1009
- const imgRef = useRef(null);
1068
+ const [isLoaded, setIsLoaded] = useState6(false);
1069
+ const [hasError, setHasError] = useState6(false);
1070
+ const imgRef = useRef2(null);
1010
1071
  const imageUrl = loader ? loader({ src, width: width || 0, quality, format }) : width ? defaultLoader({ src, width, quality, format }) : src;
1011
- useEffect5(() => {
1072
+ useEffect6(() => {
1012
1073
  const img = imgRef.current;
1013
1074
  if (img?.complete && img.naturalWidth > 0) {
1014
1075
  setIsLoaded(true);
@@ -1023,7 +1084,7 @@ function Image({
1023
1084
  setHasError(true);
1024
1085
  onErrorProp?.();
1025
1086
  };
1026
- useEffect5(() => {
1087
+ useEffect6(() => {
1027
1088
  if (priority || typeof window === "undefined") {
1028
1089
  return;
1029
1090
  }
@@ -1083,7 +1144,7 @@ function Image({
1083
1144
  height: "100%"
1084
1145
  },
1085
1146
  children: [
1086
- showSpinner && !isLoaded && !hasError && /* @__PURE__ */ jsx5("div", {
1147
+ showSpinner && !isLoaded && !hasError && /* @__PURE__ */ jsx6("div", {
1087
1148
  style: {
1088
1149
  position: "absolute",
1089
1150
  inset: 0,
@@ -1094,7 +1155,7 @@ function Image({
1094
1155
  zIndex: 1,
1095
1156
  pointerEvents: "none"
1096
1157
  },
1097
- children: spinner || /* @__PURE__ */ jsx5("div", {
1158
+ children: spinner || /* @__PURE__ */ jsx6("div", {
1098
1159
  style: {
1099
1160
  width: `${spinnerSize}px`,
1100
1161
  height: `${spinnerSize}px`,
@@ -1105,7 +1166,7 @@ function Image({
1105
1166
  }
1106
1167
  })
1107
1168
  }),
1108
- placeholder === "blur" && placeholderSrc && !isLoaded && !hasError && /* @__PURE__ */ jsx5("img", {
1169
+ placeholder === "blur" && placeholderSrc && !isLoaded && !hasError && /* @__PURE__ */ jsx6("img", {
1109
1170
  src: placeholderSrc,
1110
1171
  alt: "",
1111
1172
  "aria-hidden": "true",
@@ -1120,7 +1181,7 @@ function Image({
1120
1181
  zIndex: -1
1121
1182
  }
1122
1183
  }),
1123
- /* @__PURE__ */ jsx5("img", {
1184
+ /* @__PURE__ */ jsx6("img", {
1124
1185
  ref: imgRef,
1125
1186
  src: priority || supportsNativeLazyLoading() ? imageUrl : undefined,
1126
1187
  "data-src": !priority && !supportsNativeLazyLoading() ? imageUrl : undefined,
@@ -1138,7 +1199,7 @@ function Image({
1138
1199
  className,
1139
1200
  ...props
1140
1201
  }),
1141
- showSpinner && !isLoaded && /* @__PURE__ */ jsx5("style", {
1202
+ showSpinner && !isLoaded && /* @__PURE__ */ jsx6("style", {
1142
1203
  children: `
1143
1204
  @keyframes reroute-spin {
1144
1205
  0% { transform: rotate(0deg); }
@@ -1150,8 +1211,8 @@ function Image({
1150
1211
  });
1151
1212
  }
1152
1213
  // packages/react/src/components/Link.tsx
1153
- import { useCallback as useCallback4, useMemo as useMemo6 } from "react";
1154
- import { jsx as jsx6 } from "react/jsx-runtime";
1214
+ import { useCallback as useCallback4, useContext as useContext3, useMemo as useMemo6 } from "react";
1215
+ import { jsx as jsx7 } from "react/jsx-runtime";
1155
1216
  function Link({
1156
1217
  to,
1157
1218
  replace,
@@ -1163,15 +1224,24 @@ function Link({
1163
1224
  onFocus,
1164
1225
  ...props
1165
1226
  }) {
1166
- const { navigate, matchRoute } = useRouter();
1227
+ const routerContext = useContext3(RouterContext);
1228
+ const router = useRouter();
1167
1229
  const resolver = useContentResolver();
1168
1230
  const contentIndex = useContentIndex();
1169
1231
  const ensureCollection = useContentLoadCollection();
1232
+ const hasRouter = !!routerContext;
1233
+ const { navigate, matchRoute } = router || {
1234
+ navigate: () => {},
1235
+ matchRoute: () => null
1236
+ };
1170
1237
  const inferred = useMemo6(() => resolver ? resolver(String(to)) : undefined, [resolver, to]);
1171
1238
  const handleClick = useCallback4(async (e) => {
1172
1239
  if (onClick) {
1173
1240
  onClick(e);
1174
1241
  }
1242
+ if (!hasRouter) {
1243
+ return;
1244
+ }
1175
1245
  if (e.defaultPrevented || e.button !== 0 || e.ctrlKey || e.metaKey || e.shiftKey || e.altKey || props.target === "_blank") {
1176
1246
  return;
1177
1247
  }
@@ -1224,7 +1294,8 @@ function Link({
1224
1294
  prefetch,
1225
1295
  inferred,
1226
1296
  matchRoute,
1227
- fragment
1297
+ fragment,
1298
+ hasRouter
1228
1299
  ]);
1229
1300
  const handleMouseEnter = useCallback4((e) => {
1230
1301
  if (prefetch && inferred && inferred.module)
@@ -1241,7 +1312,7 @@ function Link({
1241
1312
  (async () => {
1242
1313
  try {
1243
1314
  const items = await ensureCollection(inferred.collection);
1244
- const found = (items || []).find((e2) => e2?.name === inferred.name);
1315
+ const found = (items || []).find((item) => item?.name === inferred.name);
1245
1316
  const mod = found?.module;
1246
1317
  if (mod)
1247
1318
  prefetchContent({ ...inferred, module: mod });
@@ -1295,7 +1366,7 @@ function Link({
1295
1366
  (async () => {
1296
1367
  try {
1297
1368
  const items = await ensureCollection(inferred.collection);
1298
- const found = (items || []).find((e2) => e2?.name === inferred.name);
1369
+ const found = (items || []).find((item) => item?.name === inferred.name);
1299
1370
  const mod = found?.module;
1300
1371
  if (mod)
1301
1372
  prefetchContent({ ...inferred, module: mod });
@@ -1335,7 +1406,7 @@ function Link({
1335
1406
  matchRoute
1336
1407
  ]);
1337
1408
  const href = fragment ? `${to}#${fragment}` : to;
1338
- return /* @__PURE__ */ jsx6("a", {
1409
+ return /* @__PURE__ */ jsx7("a", {
1339
1410
  href,
1340
1411
  onClick: handleClick,
1341
1412
  onMouseEnter: handleMouseEnter,
@@ -1343,12 +1414,36 @@ function Link({
1343
1414
  ...props
1344
1415
  });
1345
1416
  }
1417
+ // packages/react/src/components/Markdown.tsx
1418
+ import ReactMarkdownLib from "react-markdown";
1419
+ import { jsx as jsx8 } from "react/jsx-runtime";
1420
+ function Markdown({
1421
+ children,
1422
+ className,
1423
+ skipHtml = false,
1424
+ components,
1425
+ remarkPlugins = [],
1426
+ rehypePlugins = []
1427
+ }) {
1428
+ const finalRemarkPlugins = [...remarkPlugins];
1429
+ const finalRehypePlugins = [...rehypePlugins];
1430
+ return /* @__PURE__ */ jsx8("div", {
1431
+ className,
1432
+ children: /* @__PURE__ */ jsx8(ReactMarkdownLib, {
1433
+ remarkPlugins: finalRemarkPlugins,
1434
+ rehypePlugins: finalRehypePlugins,
1435
+ skipHtml,
1436
+ components,
1437
+ children
1438
+ })
1439
+ });
1440
+ }
1346
1441
  // packages/react/src/components/Outlet.tsx
1347
- import { useContext as useContext3 } from "react";
1348
- import { jsx as jsx7, Fragment } from "react/jsx-runtime";
1442
+ import { useContext as useContext4 } from "react";
1443
+ import { jsx as jsx9, Fragment as Fragment2 } from "react/jsx-runtime";
1349
1444
  function Outlet() {
1350
- const outletContent = useContext3(OutletContext);
1351
- return /* @__PURE__ */ jsx7(Fragment, {
1445
+ const outletContent = useContext4(OutletContext);
1446
+ return /* @__PURE__ */ jsx9(Fragment2, {
1352
1447
  children: outletContent
1353
1448
  });
1354
1449
  }
@@ -1375,10 +1470,12 @@ export {
1375
1470
  RerouteProvider,
1376
1471
  OutletContext,
1377
1472
  Outlet,
1473
+ Markdown,
1378
1474
  Link,
1379
1475
  Image,
1380
1476
  ContentRoute,
1381
- ContentProvider
1477
+ ContentProvider,
1478
+ ClientOnly
1382
1479
  };
1383
1480
 
1384
- //# debugId=74621835C22C5A1764756E2164756E21
1481
+ //# debugId=CB077059E687760364756E2164756E21