olova 2.0.18 → 2.0.19

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/Link.js CHANGED
@@ -1,8 +1,7 @@
1
1
  import {
2
2
  Link,
3
3
  Link_default
4
- } from "./chunk-WNRULQF5.js";
5
- import "./chunk-TFRUFD5A.js";
4
+ } from "./chunk-CYX762OE.js";
6
5
  export {
7
6
  Link,
8
7
  Link_default as default
package/dist/Router.js CHANGED
@@ -2,9 +2,8 @@ import {
2
2
  Router,
3
3
  loadRoute,
4
4
  matchRoute
5
- } from "./chunk-4CH3KNWP.js";
6
- import "./chunk-7BXNTMPM.js";
7
- import "./chunk-TFRUFD5A.js";
5
+ } from "./chunk-Y3CEUWVD.js";
6
+ import "./chunk-LOK5UEME.js";
8
7
  export {
9
8
  Router,
10
9
  loadRoute,
@@ -0,0 +1,21 @@
1
+ // Link.tsx
2
+ import { jsx } from "react/jsx-runtime";
3
+ function Link({ href, children, ...props }) {
4
+ const handleClick = (e) => {
5
+ if (e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
6
+ if (href.startsWith("http") || href.startsWith("//")) return;
7
+ e.preventDefault();
8
+ const currentUrl = window.location.pathname + window.location.search;
9
+ const targetUrl = href.startsWith("/") ? href : "/" + href;
10
+ if (currentUrl === targetUrl) return;
11
+ window.history.pushState({}, "", href);
12
+ window.dispatchEvent(new Event("pushstate"));
13
+ };
14
+ return /* @__PURE__ */ jsx("a", { href, onClick: handleClick, ...props, children });
15
+ }
16
+ var Link_default = Link;
17
+
18
+ export {
19
+ Link,
20
+ Link_default
21
+ };
@@ -0,0 +1,19 @@
1
+ import {
2
+ RouterContext
3
+ } from "./chunk-LOK5UEME.js";
4
+
5
+ // useParams.ts
6
+ import { useContext } from "react";
7
+ function useParams() {
8
+ return useContext(RouterContext).params;
9
+ }
10
+ function usePath() {
11
+ return useContext(RouterContext).path;
12
+ }
13
+ var useParams_default = useParams;
14
+
15
+ export {
16
+ useParams,
17
+ usePath,
18
+ useParams_default
19
+ };
@@ -0,0 +1,7 @@
1
+ // context.ts
2
+ import { createContext } from "react";
3
+ var RouterContext = createContext({ params: {}, path: "/" });
4
+
5
+ export {
6
+ RouterContext
7
+ };
@@ -1,16 +1,11 @@
1
- import {
2
- __toESM,
3
- require_react
4
- } from "./chunk-TFRUFD5A.js";
5
-
6
1
  // useSearchParams.ts
7
- var import_react = __toESM(require_react(), 1);
2
+ import { useState, useEffect } from "react";
8
3
  function useSearchParams() {
9
- const [searchParams, setSearchParams] = (0, import_react.useState)(() => {
4
+ const [searchParams, setSearchParams] = useState(() => {
10
5
  if (typeof window === "undefined") return new URLSearchParams();
11
6
  return new URLSearchParams(window.location.search);
12
7
  });
13
- (0, import_react.useEffect)(() => {
8
+ useEffect(() => {
14
9
  if (typeof window === "undefined") return;
15
10
  const handleNavigation = () => {
16
11
  setSearchParams(new URLSearchParams(window.location.search));
@@ -1,16 +1,11 @@
1
- import {
2
- __toESM,
3
- require_react
4
- } from "./chunk-TFRUFD5A.js";
5
-
6
1
  // usePathname.ts
7
- var import_react = __toESM(require_react(), 1);
2
+ import { useState, useEffect } from "react";
8
3
  function usePathname() {
9
- const [pathname, setPathname] = (0, import_react.useState)(() => {
4
+ const [pathname, setPathname] = useState(() => {
10
5
  if (typeof window === "undefined") return "/";
11
6
  return window.location.pathname;
12
7
  });
13
- (0, import_react.useEffect)(() => {
8
+ useEffect(() => {
14
9
  if (typeof window === "undefined") return;
15
10
  const handleNavigation = () => {
16
11
  setPathname(window.location.pathname);
@@ -1,26 +1,22 @@
1
1
  import {
2
2
  RouterContext
3
- } from "./chunk-7BXNTMPM.js";
4
- import {
5
- __toESM,
6
- require_react
7
- } from "./chunk-TFRUFD5A.js";
3
+ } from "./chunk-LOK5UEME.js";
8
4
 
9
5
  // Router.tsx
10
- var import_react = __toESM(require_react(), 1);
11
- import { routes } from "olova/routes";
6
+ import React, { useState, useEffect } from "react";
7
+ import { routes } from "virtual:olova-routes";
12
8
  function parseMarkdown(md) {
13
9
  return md.replace(/^### (.*$)/gim, "<h3>$1</h3>").replace(/^## (.*$)/gim, "<h2>$1</h2>").replace(/^# (.*$)/gim, "<h1>$1</h1>").replace(/\*\*\*(.*?)\*\*\*/g, "<strong><em>$1</em></strong>").replace(/\*\*(.*?)\*\*/g, "<strong>$1</strong>").replace(/\*(.*?)\*/g, "<em>$1</em>").replace(/```([\s\S]*?)```/g, "<pre><code>$1</code></pre>").replace(/`(.*?)`/g, "<code>$1</code>").replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>').replace(/\n\n/g, "</p><p>").replace(/\n/g, "<br>").replace(/^(.*)$/, "<p>$1</p>");
14
10
  }
15
11
  function HtmlContent({ html }) {
16
- return import_react.default.createElement("div", {
12
+ return React.createElement("div", {
17
13
  dangerouslySetInnerHTML: { __html: html },
18
14
  className: "olova-html-content"
19
15
  });
20
16
  }
21
17
  function MarkdownContent({ markdown }) {
22
18
  const html = parseMarkdown(markdown);
23
- return import_react.default.createElement("article", {
19
+ return React.createElement("article", {
24
20
  dangerouslySetInnerHTML: { __html: html },
25
21
  className: "olova-markdown-content"
26
22
  });
@@ -84,11 +80,11 @@ async function loadRoute(path) {
84
80
  return null;
85
81
  }
86
82
  function Router({ url, initialComponent, initialParams, onRouteChange }) {
87
- const [path, setPath] = (0, import_react.useState)(() => normalizePath(url || (typeof window !== "undefined" ? window.location.pathname : "/")));
88
- const [Component, setComponent] = (0, import_react.useState)(() => initialComponent || null);
89
- const [params, setParams] = (0, import_react.useState)(() => initialParams || {});
90
- const hasHydrated = import_react.default.useRef(false);
91
- (0, import_react.useEffect)(() => {
83
+ const [path, setPath] = useState(() => normalizePath(url || (typeof window !== "undefined" ? window.location.pathname : "/")));
84
+ const [Component, setComponent] = useState(() => initialComponent || null);
85
+ const [params, setParams] = useState(() => initialParams || {});
86
+ const hasHydrated = React.useRef(false);
87
+ useEffect(() => {
92
88
  if (typeof window === "undefined") return;
93
89
  const handleNavigation = () => {
94
90
  const newPath = normalizePath(window.location.pathname);
@@ -102,7 +98,7 @@ function Router({ url, initialComponent, initialParams, onRouteChange }) {
102
98
  window.removeEventListener("pushstate", handleNavigation);
103
99
  };
104
100
  }, []);
105
- (0, import_react.useEffect)(() => {
101
+ useEffect(() => {
106
102
  if (!hasHydrated.current && initialComponent && path === normalizePath(url || "")) {
107
103
  console.log(`[Router] Hydration skipped for: ${path}`);
108
104
  hasHydrated.current = true;
@@ -128,7 +124,7 @@ function Router({ url, initialComponent, initialParams, onRouteChange }) {
128
124
  onRouteChange(fallbackResult.metadata);
129
125
  }
130
126
  } else {
131
- setComponent(() => () => import_react.default.createElement("div", null, "404 Not Found"));
127
+ setComponent(() => () => React.createElement("div", null, "404 Not Found"));
132
128
  setParams({});
133
129
  if (onRouteChange) {
134
130
  onRouteChange(void 0);
@@ -142,11 +138,11 @@ function Router({ url, initialComponent, initialParams, onRouteChange }) {
142
138
  isCancelled = true;
143
139
  };
144
140
  }, [path, onRouteChange]);
145
- if (!Component) return import_react.default.createElement("div", null, "Loading...");
146
- return import_react.default.createElement(
141
+ if (!Component) return React.createElement("div", null, "Loading...");
142
+ return React.createElement(
147
143
  RouterContext.Provider,
148
144
  { value: { params, path } },
149
- import_react.default.createElement(Component, params)
145
+ React.createElement(Component, params)
150
146
  );
151
147
  }
152
148
 
@@ -0,0 +1,5 @@
1
+ import React__default from 'react';
2
+
3
+ declare function hydrate(RootLayout?: React__default.ComponentType<any>): Promise<void>;
4
+
5
+ export { hydrate };
package/dist/client.js ADDED
@@ -0,0 +1,72 @@
1
+ import {
2
+ Router,
3
+ loadRoute
4
+ } from "./chunk-Y3CEUWVD.js";
5
+ import "./chunk-LOK5UEME.js";
6
+
7
+ // client.tsx
8
+ import React from "react";
9
+ import { hydrateRoot, createRoot } from "react-dom/client";
10
+ async function hydrate(RootLayout) {
11
+ const hydrationData = window.__OLOVA_DATA__;
12
+ const url = window.location.pathname;
13
+ let Component;
14
+ let params = {};
15
+ if (hydrationData) {
16
+ const result = await loadRoute(url);
17
+ if (result) {
18
+ Component = result.module.default;
19
+ params = hydrationData.params;
20
+ }
21
+ }
22
+ if (!Component) {
23
+ const result = await loadRoute(url);
24
+ if (result) {
25
+ Component = result.module.default;
26
+ params = result.params;
27
+ } else {
28
+ const fallback = await loadRoute("/404");
29
+ if (fallback) {
30
+ Component = fallback.module.default;
31
+ params = fallback.params;
32
+ } else {
33
+ Component = () => React.createElement("div", null, "404 Not Found");
34
+ }
35
+ }
36
+ }
37
+ if (RootLayout) {
38
+ const App = React.createElement(
39
+ RootLayout,
40
+ null,
41
+ React.createElement(Router, {
42
+ url,
43
+ initialComponent: Component,
44
+ initialParams: params
45
+ })
46
+ );
47
+ if (hydrationData) {
48
+ hydrateRoot(document, App);
49
+ } else {
50
+ createRoot(document).render(App);
51
+ }
52
+ } else {
53
+ const root = document.getElementById("root");
54
+ if (root) {
55
+ const App = React.createElement(Router, {
56
+ url,
57
+ initialComponent: Component,
58
+ initialParams: params
59
+ });
60
+ if (hydrationData) {
61
+ hydrateRoot(root, App);
62
+ } else {
63
+ createRoot(root).render(App);
64
+ }
65
+ }
66
+ }
67
+ }
68
+ if (typeof window !== "undefined" && !window.__OLOVA_HYDRATE_MANUAL__) {
69
+ }
70
+ export {
71
+ hydrate
72
+ };
package/dist/index.js CHANGED
@@ -1,25 +1,24 @@
1
1
  import {
2
2
  Link
3
- } from "./chunk-WNRULQF5.js";
3
+ } from "./chunk-CYX762OE.js";
4
4
  import {
5
5
  Router,
6
6
  loadRoute,
7
7
  matchRoute
8
- } from "./chunk-4CH3KNWP.js";
8
+ } from "./chunk-Y3CEUWVD.js";
9
9
  import {
10
10
  useParams,
11
11
  usePath
12
- } from "./chunk-YVUSXRPM.js";
12
+ } from "./chunk-K6EDUQDD.js";
13
13
  import {
14
14
  RouterContext
15
- } from "./chunk-7BXNTMPM.js";
15
+ } from "./chunk-LOK5UEME.js";
16
16
  import {
17
17
  usePathname
18
- } from "./chunk-RCRG2FBU.js";
18
+ } from "./chunk-XGX5YRJV.js";
19
19
  import {
20
20
  useSearchParams
21
- } from "./chunk-K2URQPLW.js";
22
- import "./chunk-TFRUFD5A.js";
21
+ } from "./chunk-NEMX72XA.js";
23
22
  export {
24
23
  Link,
25
24
  Router,
@@ -0,0 +1,13 @@
1
+ import React__default from 'react';
2
+ import { Metadata } from './Router.js';
3
+
4
+ declare function render(url: string, RootLayout?: React__default.ComponentType<any>): Promise<{
5
+ html: string;
6
+ hydrationData: {
7
+ params: {};
8
+ metadata: Metadata;
9
+ };
10
+ }>;
11
+ declare function renderShellWithMetadata(metadata: Metadata): string;
12
+
13
+ export { render, renderShellWithMetadata };
package/dist/server.js ADDED
@@ -0,0 +1,87 @@
1
+ import {
2
+ Router,
3
+ loadRoute
4
+ } from "./chunk-Y3CEUWVD.js";
5
+ import "./chunk-LOK5UEME.js";
6
+
7
+ // server.tsx
8
+ import React from "react";
9
+ import { renderToString } from "react-dom/server";
10
+ function renderShell(content, metadata) {
11
+ const title = metadata.title || "My Framework";
12
+ const description = metadata.description || "";
13
+ const head = `
14
+ <meta charset="UTF-8" />
15
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
16
+ <title>${title}</title>
17
+ <meta name="description" content="${description}" />
18
+ ${metadata.keywords ? `<meta name="keywords" content="${Array.isArray(metadata.keywords) ? metadata.keywords.join(",") : metadata.keywords}" />` : ""}
19
+ ${metadata.robots ? `<meta name="robots" content="${metadata.robots}" />` : ""}
20
+ ${metadata.canonical ? `<link rel="canonical" href="${metadata.canonical}" />` : ""}
21
+ `;
22
+ return `<!DOCTYPE html>
23
+ <html lang="en">
24
+ <head>
25
+ ${head}
26
+ </head>
27
+ <body>
28
+ <div id="root">${content}</div>
29
+ </body>
30
+ </html>`;
31
+ }
32
+ async function render(url, RootLayout) {
33
+ const result = await loadRoute(url);
34
+ let Component = void 0;
35
+ let params = {};
36
+ let metadata = {};
37
+ if (result) {
38
+ Component = result.module.default;
39
+ params = result.params;
40
+ metadata = result.metadata || {};
41
+ } else {
42
+ const fallback = await loadRoute("/404");
43
+ if (fallback) {
44
+ Component = fallback.module.default;
45
+ params = fallback.params;
46
+ metadata = fallback.metadata || {};
47
+ } else {
48
+ Component = () => React.createElement("div", null, "404 Not Found");
49
+ }
50
+ }
51
+ let appHtml;
52
+ if (RootLayout) {
53
+ const App = React.createElement(
54
+ RootLayout,
55
+ null,
56
+ React.createElement(Router, {
57
+ url,
58
+ initialComponent: Component,
59
+ initialParams: params
60
+ })
61
+ );
62
+ appHtml = "<!DOCTYPE html>" + renderToString(App);
63
+ } else {
64
+ const content = renderToString(
65
+ React.createElement(Router, {
66
+ url,
67
+ initialComponent: Component,
68
+ initialParams: params
69
+ })
70
+ );
71
+ appHtml = renderShell(content, metadata);
72
+ }
73
+ return {
74
+ html: appHtml,
75
+ hydrationData: {
76
+ params,
77
+ metadata
78
+ }
79
+ };
80
+ }
81
+ function renderShellWithMetadata(metadata) {
82
+ return renderShell("", metadata);
83
+ }
84
+ export {
85
+ render,
86
+ renderShellWithMetadata
87
+ };
package/dist/useParams.js CHANGED
@@ -2,9 +2,8 @@ import {
2
2
  useParams,
3
3
  useParams_default,
4
4
  usePath
5
- } from "./chunk-YVUSXRPM.js";
6
- import "./chunk-7BXNTMPM.js";
7
- import "./chunk-TFRUFD5A.js";
5
+ } from "./chunk-K6EDUQDD.js";
6
+ import "./chunk-LOK5UEME.js";
8
7
  export {
9
8
  useParams_default as default,
10
9
  useParams,
@@ -1,8 +1,7 @@
1
1
  import {
2
2
  usePathname,
3
3
  usePathname_default
4
- } from "./chunk-RCRG2FBU.js";
5
- import "./chunk-TFRUFD5A.js";
4
+ } from "./chunk-XGX5YRJV.js";
6
5
  export {
7
6
  usePathname_default as default,
8
7
  usePathname
@@ -1,8 +1,7 @@
1
1
  import {
2
2
  useSearchParams,
3
3
  useSearchParams_default
4
- } from "./chunk-K2URQPLW.js";
5
- import "./chunk-TFRUFD5A.js";
4
+ } from "./chunk-NEMX72XA.js";
6
5
  export {
7
6
  useSearchParams_default as default,
8
7
  useSearchParams
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
 
2
2
  {
3
3
  "name": "olova",
4
- "version": "2.0.18",
4
+ "version": "2.0.19",
5
5
  "description": "Olova framework core",
6
6
  "type": "module",
7
7
  "files": [
@@ -31,12 +31,24 @@
31
31
  "./Router": {
32
32
  "import": "./dist/Router.js",
33
33
  "types": "./dist/Router.d.ts"
34
+ },
35
+ "./client": {
36
+ "import": "./dist/client.js",
37
+ "types": "./dist/client.d.ts"
38
+ },
39
+ "./server": {
40
+ "import": "./dist/server.js",
41
+ "types": "./dist/server.d.ts"
34
42
  }
35
43
  },
36
44
  "scripts": {
37
- "build": "tsup index.ts Link.tsx useSearchParams.ts usePathname.ts useParams.ts Router.tsx --format esm --dts --clean --external olova/routes react react-dom",
45
+ "build": "tsup index.ts Link.tsx useSearchParams.ts usePathname.ts useParams.ts Router.tsx server.tsx client.tsx --format esm --dts --clean --external virtual:olova-routes react react-dom react-dom/client react-dom/server",
38
46
  "prepublishOnly": "npm run build"
39
47
  },
48
+ "peerDependencies": {
49
+ "react": ">=18.0.0",
50
+ "react-dom": ">=18.0.0"
51
+ },
40
52
  "devDependencies": {
41
53
  "tsup": "^8.0.0",
42
54
  "typescript": "^5.0.0",
@@ -1,12 +0,0 @@
1
- import {
2
- __toESM,
3
- require_react
4
- } from "./chunk-TFRUFD5A.js";
5
-
6
- // context.ts
7
- var import_react = __toESM(require_react(), 1);
8
- var RouterContext = (0, import_react.createContext)({ params: {}, path: "/" });
9
-
10
- export {
11
- RouterContext
12
- };