hono 4.0.4 → 4.0.6

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 (34) hide show
  1. package/dist/adapter/bun/serve-static.js +16 -37
  2. package/dist/adapter/cloudflare-workers/serve-static.js +12 -37
  3. package/dist/adapter/deno/serve-static.js +19 -35
  4. package/dist/cjs/adapter/bun/serve-static.js +16 -37
  5. package/dist/cjs/adapter/cloudflare-workers/serve-static.js +12 -37
  6. package/dist/cjs/adapter/deno/serve-static.js +19 -35
  7. package/dist/cjs/helper/ssg/index.js +2 -3
  8. package/dist/cjs/helper/streaming/sse.js +14 -2
  9. package/dist/cjs/helper/streaming/stream.js +14 -2
  10. package/dist/cjs/helper/streaming/text.js +2 -2
  11. package/dist/cjs/jsx/dom/render.js +55 -4
  12. package/dist/cjs/middleware/serve-static/index.js +84 -0
  13. package/dist/cjs/router/reg-exp-router/router.js +3 -7
  14. package/dist/cjs/utils/filepath.js +16 -6
  15. package/dist/helper/ssg/index.js +2 -3
  16. package/dist/helper/streaming/sse.js +14 -2
  17. package/dist/helper/streaming/stream.js +14 -2
  18. package/dist/helper/streaming/text.js +2 -2
  19. package/dist/jsx/dom/render.js +55 -4
  20. package/dist/middleware/serve-static/index.js +61 -0
  21. package/dist/router/reg-exp-router/router.js +3 -8
  22. package/dist/types/adapter/bun/serve-static.d.ts +2 -9
  23. package/dist/types/adapter/cloudflare-workers/serve-static.d.ts +3 -8
  24. package/dist/types/adapter/deno/serve-static.d.ts +2 -9
  25. package/dist/types/context.d.ts +8 -8
  26. package/dist/types/helper/streaming/sse.d.ts +1 -1
  27. package/dist/types/helper/streaming/stream.d.ts +1 -1
  28. package/dist/types/helper/streaming/text.d.ts +1 -1
  29. package/dist/types/jsx/dom/render.d.ts +7 -2
  30. package/dist/types/middleware/jsx-renderer/index.d.ts +1 -2
  31. package/dist/types/middleware/serve-static/index.d.ts +16 -0
  32. package/dist/types/utils/filepath.d.ts +1 -0
  33. package/dist/utils/filepath.js +14 -5
  34. package/package.json +1 -1
@@ -1,41 +1,20 @@
1
1
  // src/adapter/bun/serve-static.ts
2
- import { getFilePath } from "../../utils/filepath.js";
3
- import { getMimeType } from "../../utils/mime.js";
4
- var DEFAULT_DOCUMENT = "index.html";
5
- var serveStatic = (options = { root: "" }) => {
6
- return async (c, next) => {
7
- if (c.finalized) {
8
- await next();
9
- return;
10
- }
11
- const url = new URL(c.req.url);
12
- const filename = options.path ?? decodeURI(url.pathname);
13
- let path = getFilePath({
14
- filename: options.rewriteRequestPath ? options.rewriteRequestPath(filename) : filename,
15
- root: options.root,
16
- defaultDocument: DEFAULT_DOCUMENT
17
- });
18
- if (!path) {
19
- return await next();
20
- }
21
- path = `./${path}`;
22
- const file = Bun.file(path);
23
- const isExists = await file.exists();
24
- if (isExists) {
25
- let mimeType = void 0;
26
- if (options.mimes) {
27
- mimeType = getMimeType(path, options.mimes) ?? getMimeType(path);
28
- } else {
29
- mimeType = getMimeType(path);
30
- }
31
- if (mimeType) {
32
- c.header("Content-Type", mimeType);
33
- }
34
- return c.body(file);
35
- }
36
- await options.onNotFound?.(path, c);
37
- await next();
38
- return;
2
+ import { serveStatic as baseServeStatic } from "../../middleware/serve-static/index.js";
3
+ var serveStatic = (options) => {
4
+ return async function serveStatic2(c, next) {
5
+ const getContent = async (path) => {
6
+ path = `./${path}`;
7
+ const file = Bun.file(path);
8
+ return await file.exists() ? file : null;
9
+ };
10
+ const pathResolve = (path) => {
11
+ return `./${path}`;
12
+ };
13
+ return baseServeStatic({
14
+ ...options,
15
+ getContent,
16
+ pathResolve
17
+ })(c, next);
39
18
  };
40
19
  };
41
20
  export {
@@ -1,43 +1,18 @@
1
1
  // src/adapter/cloudflare-workers/serve-static.ts
2
- import { getFilePath } from "../../utils/filepath.js";
3
- import { getMimeType } from "../../utils/mime.js";
2
+ import { serveStatic as baseServeStatic } from "../../middleware/serve-static/index.js";
4
3
  import { getContentFromKVAsset } from "./utils.js";
5
- var DEFAULT_DOCUMENT = "index.html";
6
4
  var serveStatic = (options) => {
7
- return async (c, next) => {
8
- if (c.finalized) {
9
- await next();
10
- return;
11
- }
12
- const url = new URL(c.req.url);
13
- const filename = options.path ?? decodeURI(url.pathname);
14
- const path = getFilePath({
15
- filename: options.rewriteRequestPath ? options.rewriteRequestPath(filename) : filename,
16
- root: options.root,
17
- defaultDocument: DEFAULT_DOCUMENT
18
- });
19
- if (!path) {
20
- return await next();
21
- }
22
- const content = await getContentFromKVAsset(path, {
23
- manifest: options.manifest,
24
- namespace: options.namespace ? options.namespace : c.env ? c.env.__STATIC_CONTENT : void 0
25
- });
26
- if (content) {
27
- let mimeType = void 0;
28
- if (options.mimes) {
29
- mimeType = getMimeType(path, options.mimes) ?? getMimeType(path);
30
- } else {
31
- mimeType = getMimeType(path);
32
- }
33
- if (mimeType) {
34
- c.header("Content-Type", mimeType);
35
- }
36
- return c.body(content);
37
- }
38
- await options.onNotFound?.(path, c);
39
- await next();
40
- return;
5
+ return async function serveStatic2(c, next) {
6
+ const getContent = async (path) => {
7
+ return getContentFromKVAsset(path, {
8
+ manifest: options.manifest,
9
+ namespace: options.namespace ? options.namespace : c.env ? c.env.__STATIC_CONTENT : void 0
10
+ });
11
+ };
12
+ return baseServeStatic({
13
+ ...options,
14
+ getContent
15
+ })(c, next);
41
16
  };
42
17
  };
43
18
  export {
@@ -1,41 +1,25 @@
1
1
  // src/adapter/deno/serve-static.ts
2
- import { getFilePath } from "../../utils/filepath.js";
3
- import { getMimeType } from "../../utils/mime.js";
2
+ import { serveStatic as baseServeStatic } from "../../middleware/serve-static/index.js";
4
3
  var { open } = Deno;
5
- var DEFAULT_DOCUMENT = "index.html";
6
- var serveStatic = (options = { root: "" }) => {
7
- return async (c, next) => {
8
- if (c.finalized) {
9
- await next();
10
- return;
11
- }
12
- const url = new URL(c.req.url);
13
- const filename = options.path ?? decodeURI(url.pathname);
14
- let path = getFilePath({
15
- filename: options.rewriteRequestPath ? options.rewriteRequestPath(filename) : filename,
16
- root: options.root,
17
- defaultDocument: DEFAULT_DOCUMENT
18
- });
19
- if (!path) {
20
- return await next();
21
- }
22
- path = `./${path}`;
23
- let file;
24
- try {
25
- file = await open(path);
26
- } catch (e) {
27
- console.warn(`${e}`);
28
- }
29
- if (file) {
30
- const mimeType = getMimeType(path);
31
- if (mimeType) {
32
- c.header("Content-Type", mimeType);
4
+ var serveStatic = (options) => {
5
+ return async function serveStatic2(c, next) {
6
+ const getContent = async (path) => {
7
+ let file;
8
+ try {
9
+ file = await open(path);
10
+ } catch (e) {
11
+ console.warn(`${e}`);
33
12
  }
34
- return c.body(file.readable);
35
- }
36
- await options.onNotFound?.(path, c);
37
- await next();
38
- return;
13
+ return file ? file.readable : void 0;
14
+ };
15
+ const pathResolve = (path) => {
16
+ return `./${path}`;
17
+ };
18
+ return baseServeStatic({
19
+ ...options,
20
+ getContent,
21
+ pathResolve
22
+ })(c, next);
39
23
  };
40
24
  };
41
25
  export {
@@ -21,43 +21,22 @@ __export(serve_static_exports, {
21
21
  serveStatic: () => serveStatic
22
22
  });
23
23
  module.exports = __toCommonJS(serve_static_exports);
24
- var import_filepath = require("../../utils/filepath");
25
- var import_mime = require("../../utils/mime");
26
- const DEFAULT_DOCUMENT = "index.html";
27
- const serveStatic = (options = { root: "" }) => {
28
- return async (c, next) => {
29
- if (c.finalized) {
30
- await next();
31
- return;
32
- }
33
- const url = new URL(c.req.url);
34
- const filename = options.path ?? decodeURI(url.pathname);
35
- let path = (0, import_filepath.getFilePath)({
36
- filename: options.rewriteRequestPath ? options.rewriteRequestPath(filename) : filename,
37
- root: options.root,
38
- defaultDocument: DEFAULT_DOCUMENT
39
- });
40
- if (!path) {
41
- return await next();
42
- }
43
- path = `./${path}`;
44
- const file = Bun.file(path);
45
- const isExists = await file.exists();
46
- if (isExists) {
47
- let mimeType = void 0;
48
- if (options.mimes) {
49
- mimeType = (0, import_mime.getMimeType)(path, options.mimes) ?? (0, import_mime.getMimeType)(path);
50
- } else {
51
- mimeType = (0, import_mime.getMimeType)(path);
52
- }
53
- if (mimeType) {
54
- c.header("Content-Type", mimeType);
55
- }
56
- return c.body(file);
57
- }
58
- await options.onNotFound?.(path, c);
59
- await next();
60
- return;
24
+ var import_serve_static = require("../../middleware/serve-static");
25
+ const serveStatic = (options) => {
26
+ return async function serveStatic2(c, next) {
27
+ const getContent = async (path) => {
28
+ path = `./${path}`;
29
+ const file = Bun.file(path);
30
+ return await file.exists() ? file : null;
31
+ };
32
+ const pathResolve = (path) => {
33
+ return `./${path}`;
34
+ };
35
+ return (0, import_serve_static.serveStatic)({
36
+ ...options,
37
+ getContent,
38
+ pathResolve
39
+ })(c, next);
61
40
  };
62
41
  };
63
42
  // Annotate the CommonJS export names for ESM import in node:
@@ -21,45 +21,20 @@ __export(serve_static_exports, {
21
21
  serveStatic: () => serveStatic
22
22
  });
23
23
  module.exports = __toCommonJS(serve_static_exports);
24
- var import_filepath = require("../../utils/filepath");
25
- var import_mime = require("../../utils/mime");
24
+ var import_serve_static = require("../../middleware/serve-static");
26
25
  var import_utils = require("./utils");
27
- const DEFAULT_DOCUMENT = "index.html";
28
26
  const serveStatic = (options) => {
29
- return async (c, next) => {
30
- if (c.finalized) {
31
- await next();
32
- return;
33
- }
34
- const url = new URL(c.req.url);
35
- const filename = options.path ?? decodeURI(url.pathname);
36
- const path = (0, import_filepath.getFilePath)({
37
- filename: options.rewriteRequestPath ? options.rewriteRequestPath(filename) : filename,
38
- root: options.root,
39
- defaultDocument: DEFAULT_DOCUMENT
40
- });
41
- if (!path) {
42
- return await next();
43
- }
44
- const content = await (0, import_utils.getContentFromKVAsset)(path, {
45
- manifest: options.manifest,
46
- namespace: options.namespace ? options.namespace : c.env ? c.env.__STATIC_CONTENT : void 0
47
- });
48
- if (content) {
49
- let mimeType = void 0;
50
- if (options.mimes) {
51
- mimeType = (0, import_mime.getMimeType)(path, options.mimes) ?? (0, import_mime.getMimeType)(path);
52
- } else {
53
- mimeType = (0, import_mime.getMimeType)(path);
54
- }
55
- if (mimeType) {
56
- c.header("Content-Type", mimeType);
57
- }
58
- return c.body(content);
59
- }
60
- await options.onNotFound?.(path, c);
61
- await next();
62
- return;
27
+ return async function serveStatic2(c, next) {
28
+ const getContent = async (path) => {
29
+ return (0, import_utils.getContentFromKVAsset)(path, {
30
+ manifest: options.manifest,
31
+ namespace: options.namespace ? options.namespace : c.env ? c.env.__STATIC_CONTENT : void 0
32
+ });
33
+ };
34
+ return (0, import_serve_static.serveStatic)({
35
+ ...options,
36
+ getContent
37
+ })(c, next);
63
38
  };
64
39
  };
65
40
  // Annotate the CommonJS export names for ESM import in node:
@@ -21,43 +21,27 @@ __export(serve_static_exports, {
21
21
  serveStatic: () => serveStatic
22
22
  });
23
23
  module.exports = __toCommonJS(serve_static_exports);
24
- var import_filepath = require("../../utils/filepath");
25
- var import_mime = require("../../utils/mime");
24
+ var import_serve_static = require("../../middleware/serve-static");
26
25
  const { open } = Deno;
27
- const DEFAULT_DOCUMENT = "index.html";
28
- const serveStatic = (options = { root: "" }) => {
29
- return async (c, next) => {
30
- if (c.finalized) {
31
- await next();
32
- return;
33
- }
34
- const url = new URL(c.req.url);
35
- const filename = options.path ?? decodeURI(url.pathname);
36
- let path = (0, import_filepath.getFilePath)({
37
- filename: options.rewriteRequestPath ? options.rewriteRequestPath(filename) : filename,
38
- root: options.root,
39
- defaultDocument: DEFAULT_DOCUMENT
40
- });
41
- if (!path) {
42
- return await next();
43
- }
44
- path = `./${path}`;
45
- let file;
46
- try {
47
- file = await open(path);
48
- } catch (e) {
49
- console.warn(`${e}`);
50
- }
51
- if (file) {
52
- const mimeType = (0, import_mime.getMimeType)(path);
53
- if (mimeType) {
54
- c.header("Content-Type", mimeType);
26
+ const serveStatic = (options) => {
27
+ return async function serveStatic2(c, next) {
28
+ const getContent = async (path) => {
29
+ let file;
30
+ try {
31
+ file = await open(path);
32
+ } catch (e) {
33
+ console.warn(`${e}`);
55
34
  }
56
- return c.body(file.readable);
57
- }
58
- await options.onNotFound?.(path, c);
59
- await next();
60
- return;
35
+ return file ? file.readable : void 0;
36
+ };
37
+ const pathResolve = (path) => {
38
+ return `./${path}`;
39
+ };
40
+ return (0, import_serve_static.serveStatic)({
41
+ ...options,
42
+ getContent,
43
+ pathResolve
44
+ })(c, next);
61
45
  };
62
46
  };
63
47
  // Annotate the CommonJS export names for ESM import in node:
@@ -35,11 +35,10 @@ var import_utils2 = require("./utils");
35
35
  const SSG_CONTEXT = "HONO_SSG_CONTEXT";
36
36
  const SSG_DISABLED_RESPONSE = new Response("SSG is disabled", { status: 404 });
37
37
  const generateFilePath = (routePath, outDir, mimeType) => {
38
- const hasExtension = /\.[^\/]+$/.test(routePath);
39
- if (hasExtension) {
38
+ const extension = determineExtension(mimeType);
39
+ if (routePath.endsWith(`.${extension}`)) {
40
40
  return (0, import_utils2.joinPaths)(outDir, routePath);
41
41
  }
42
- const extension = determineExtension(mimeType);
43
42
  if (routePath === "/") {
44
43
  return (0, import_utils2.joinPaths)(outDir, `index.${extension}`);
45
44
  }
@@ -46,10 +46,22 @@ const setSSEHeaders = (context) => {
46
46
  context.header("Cache-Control", "no-cache");
47
47
  context.header("Connection", "keep-alive");
48
48
  };
49
- const streamSSE = (c, cb) => {
49
+ const streamSSE = (c, cb, onError) => {
50
50
  const { readable, writable } = new TransformStream();
51
51
  const stream = new SSEStreamingApi(writable, readable);
52
- cb(stream).finally(() => stream.close());
52
+ (async () => {
53
+ try {
54
+ await cb(stream);
55
+ } catch (e) {
56
+ if (e instanceof Error && onError) {
57
+ await onError(e, stream);
58
+ } else {
59
+ console.error(e);
60
+ }
61
+ } finally {
62
+ stream.close();
63
+ }
64
+ })();
53
65
  setSSEHeaders(c);
54
66
  return c.newResponse(stream.responseReadable);
55
67
  };
@@ -22,10 +22,22 @@ __export(stream_exports, {
22
22
  });
23
23
  module.exports = __toCommonJS(stream_exports);
24
24
  var import_stream = require("../../utils/stream");
25
- const stream = (c, cb) => {
25
+ const stream = (c, cb, onError) => {
26
26
  const { readable, writable } = new TransformStream();
27
27
  const stream2 = new import_stream.StreamingApi(writable, readable);
28
- cb(stream2).finally(() => stream2.close());
28
+ (async () => {
29
+ try {
30
+ await cb(stream2);
31
+ } catch (e) {
32
+ if (e instanceof Error && onError) {
33
+ await onError(e, stream2);
34
+ } else {
35
+ console.error(e);
36
+ }
37
+ } finally {
38
+ stream2.close();
39
+ }
40
+ })();
29
41
  return c.newResponse(stream2.responseReadable);
30
42
  };
31
43
  // Annotate the CommonJS export names for ESM import in node:
@@ -23,11 +23,11 @@ __export(text_exports, {
23
23
  module.exports = __toCommonJS(text_exports);
24
24
  var import_context = require("../../context");
25
25
  var import__ = require(".");
26
- const streamText = (c, cb) => {
26
+ const streamText = (c, cb, onError) => {
27
27
  c.header("Content-Type", import_context.TEXT_PLAIN);
28
28
  c.header("X-Content-Type-Options", "nosniff");
29
29
  c.header("Transfer-Encoding", "chunked");
30
- return (0, import__.stream)(c, cb);
30
+ return (0, import__.stream)(c, cb, onError);
31
31
  };
32
32
  // Annotate the CommonJS export names for ESM import in node:
33
33
  0 && (module.exports = {
@@ -27,11 +27,17 @@ module.exports = __toCommonJS(render_exports);
27
27
  var import_constants = require("../constants");
28
28
  var import_context = require("../context");
29
29
  var import_hooks = require("../hooks");
30
+ var import__ = require(".");
30
31
  const eventAliasMap = {
31
32
  Change: "Input",
32
33
  DoubleClick: "DblClick"
33
34
  };
35
+ const nameSpaceMap = {
36
+ svg: "http://www.w3.org/2000/svg",
37
+ math: "http://www.w3.org/1998/Math/MathML"
38
+ };
34
39
  const buildDataStack = [];
40
+ let nameSpaceContext = void 0;
35
41
  const isNodeString = (node) => Array.isArray(node);
36
42
  const getEventSpec = (key) => {
37
43
  const match = key.match(/^on([A-Z][a-zA-Z]+?)((?<!Pointer)Capture)?$/);
@@ -70,6 +76,26 @@ const applyProps = (container, attributes, oldAttributes) => {
70
76
  Object.assign(container.style, value);
71
77
  }
72
78
  } else {
79
+ const nodeName = container.nodeName;
80
+ if (key === "value") {
81
+ if (nodeName === "INPUT" || nodeName === "TEXTAREA" || nodeName === "SELECT") {
82
+ ;
83
+ container.value = value === null || value === void 0 || value === false ? null : value;
84
+ if (nodeName === "TEXTAREA") {
85
+ container.textContent = value;
86
+ continue;
87
+ } else if (nodeName === "SELECT") {
88
+ if (container.selectedIndex === -1) {
89
+ ;
90
+ container.selectedIndex = 0;
91
+ }
92
+ continue;
93
+ }
94
+ }
95
+ } else if (key === "checked" && nodeName === "INPUT" || key === "selected" && nodeName === "OPTION") {
96
+ ;
97
+ container[key] = value;
98
+ }
73
99
  if (value === null || value === void 0 || value === false) {
74
100
  container.removeAttribute(key);
75
101
  } else if (value === true) {
@@ -200,12 +226,13 @@ const applyNodeObject = (node, container) => {
200
226
  const child = next[i];
201
227
  let el;
202
228
  if (isNodeString(child)) {
203
- if (child.e) {
229
+ if (child.e && child[1]) {
204
230
  child.e.textContent = child[0];
205
231
  }
232
+ child[1] = false;
206
233
  el = child.e || (child.e = document.createTextNode(child[0]));
207
234
  } else {
208
- el = child.e || (child.e = document.createElement(child.tag));
235
+ el = child.e || (child.e = child.n ? document.createElementNS(child.n, child.tag) : document.createElement(child.tag));
209
236
  applyProps(el, child.props, child.pP);
210
237
  applyNode(child, el);
211
238
  }
@@ -255,7 +282,10 @@ const build = (context, node, topLevelErrorHandlerNode, children) => {
255
282
  if (!isNodeString(oldChild)) {
256
283
  vChildrenToRemove.push(oldChild);
257
284
  } else {
258
- oldChild[0] = child[0];
285
+ if (oldChild[0] !== child[0]) {
286
+ oldChild[0] = child[0];
287
+ oldChild[1] = true;
288
+ }
259
289
  child = oldChild;
260
290
  }
261
291
  } else if (oldChild.tag !== child.tag) {
@@ -266,6 +296,11 @@ const build = (context, node, topLevelErrorHandlerNode, children) => {
266
296
  oldChild.children = child.children;
267
297
  child = oldChild;
268
298
  }
299
+ } else if (!isNodeString(child) && nameSpaceContext) {
300
+ const ns = (0, import__.useContext)(nameSpaceContext);
301
+ if (ns) {
302
+ child.n = ns;
303
+ }
269
304
  }
270
305
  if (!isNodeString(child)) {
271
306
  build(context, child, topLevelErrorHandlerNode);
@@ -298,11 +333,27 @@ const buildNode = (node) => {
298
333
  if (node === void 0 || node === null || typeof node === "boolean") {
299
334
  return void 0;
300
335
  } else if (typeof node === "string" || typeof node === "number") {
301
- return [node.toString()];
336
+ return [node.toString(), true];
302
337
  } else {
303
338
  if (typeof node.tag === "function") {
304
339
  ;
305
340
  node[import_constants.DOM_STASH] = [0, []];
341
+ } else {
342
+ const ns = nameSpaceMap[node.tag];
343
+ if (ns) {
344
+ ;
345
+ node.n = ns;
346
+ nameSpaceContext || (nameSpaceContext = (0, import__.createContext)(""));
347
+ node.children = [
348
+ {
349
+ tag: nameSpaceContext.Provider,
350
+ props: {
351
+ value: ns
352
+ },
353
+ children: node.children
354
+ }
355
+ ];
356
+ }
306
357
  }
307
358
  return node;
308
359
  }
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var serve_static_exports = {};
20
+ __export(serve_static_exports, {
21
+ serveStatic: () => serveStatic
22
+ });
23
+ module.exports = __toCommonJS(serve_static_exports);
24
+ var import_filepath = require("../../utils/filepath");
25
+ var import_mime = require("../../utils/mime");
26
+ const DEFAULT_DOCUMENT = "index.html";
27
+ const defaultPathResolve = (path) => path;
28
+ const serveStatic = (options) => {
29
+ return async (c, next) => {
30
+ if (c.finalized) {
31
+ await next();
32
+ return;
33
+ }
34
+ const url = new URL(c.req.url);
35
+ let filename = options.path ?? decodeURI(url.pathname);
36
+ filename = options.rewriteRequestPath ? options.rewriteRequestPath(filename) : filename;
37
+ const root = options.root;
38
+ let path = (0, import_filepath.getFilePath)({
39
+ filename,
40
+ root,
41
+ defaultDocument: DEFAULT_DOCUMENT
42
+ });
43
+ if (!path) {
44
+ return await next();
45
+ }
46
+ const getContent = options.getContent;
47
+ const pathResolve = options.pathResolve ?? defaultPathResolve;
48
+ path = pathResolve(path);
49
+ let content = await getContent(path);
50
+ if (!content) {
51
+ let pathWithOutDefaultDocument = (0, import_filepath.getFilePathWithoutDefaultDocument)({
52
+ filename,
53
+ root
54
+ });
55
+ if (!pathWithOutDefaultDocument) {
56
+ return await next();
57
+ }
58
+ pathWithOutDefaultDocument = pathResolve(pathWithOutDefaultDocument);
59
+ content = await getContent(pathWithOutDefaultDocument);
60
+ if (content) {
61
+ path = pathWithOutDefaultDocument;
62
+ }
63
+ }
64
+ if (content) {
65
+ let mimeType = void 0;
66
+ if (options.mimes) {
67
+ mimeType = (0, import_mime.getMimeType)(path, options.mimes) ?? (0, import_mime.getMimeType)(path);
68
+ } else {
69
+ mimeType = (0, import_mime.getMimeType)(path);
70
+ }
71
+ if (mimeType) {
72
+ c.header("Content-Type", mimeType);
73
+ }
74
+ return c.body(content);
75
+ }
76
+ await options.onNotFound?.(path, c);
77
+ await next();
78
+ return;
79
+ };
80
+ };
81
+ // Annotate the CommonJS export names for ESM import in node:
82
+ 0 && (module.exports = {
83
+ serveStatic
84
+ });
@@ -25,7 +25,6 @@ var import_router = require("../../router");
25
25
  var import_url = require("../../utils/url");
26
26
  var import_node = require("./node");
27
27
  var import_trie = require("./trie");
28
- const methodNames = [import_router.METHOD_NAME_ALL, ...import_router.METHODS].map((method) => method.toUpperCase());
29
28
  const emptyParam = [];
30
29
  const nullMatcher = [/^$/, [], {}];
31
30
  let wildcardRegExpCache = {};
@@ -117,9 +116,6 @@ class RegExpRouter {
117
116
  if (!middleware || !routes) {
118
117
  throw new Error(import_router.MESSAGE_MATCHER_IS_ALREADY_BUILT);
119
118
  }
120
- if (methodNames.indexOf(method) === -1) {
121
- methodNames.push(method);
122
- }
123
119
  if (!middleware[method]) {
124
120
  ;
125
121
  [middleware, routes].forEach((handlerMap) => {
@@ -177,7 +173,7 @@ class RegExpRouter {
177
173
  clearWildcardRegExpCache();
178
174
  const matchers = this.buildAllMatchers();
179
175
  this.match = (method2, path2) => {
180
- const matcher = matchers[method2];
176
+ const matcher = matchers[method2] || matchers[import_router.METHOD_NAME_ALL];
181
177
  const staticMatch = matcher[2][path2];
182
178
  if (staticMatch) {
183
179
  return staticMatch;
@@ -193,8 +189,8 @@ class RegExpRouter {
193
189
  }
194
190
  buildAllMatchers() {
195
191
  const matchers = {};
196
- methodNames.forEach((method) => {
197
- matchers[method] = this.buildMatcher(method) || matchers[import_router.METHOD_NAME_ALL];
192
+ [...Object.keys(this.routes), ...Object.keys(this.middleware)].forEach((method) => {
193
+ matchers[method] || (matchers[method] = this.buildMatcher(method));
198
194
  });
199
195
  this.middleware = this.routes = void 0;
200
196
  return matchers;
@@ -18,21 +18,30 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var filepath_exports = {};
20
20
  __export(filepath_exports, {
21
- getFilePath: () => getFilePath
21
+ getFilePath: () => getFilePath,
22
+ getFilePathWithoutDefaultDocument: () => getFilePathWithoutDefaultDocument
22
23
  });
23
24
  module.exports = __toCommonJS(filepath_exports);
24
25
  const getFilePath = (options) => {
25
26
  let filename = options.filename;
26
- if (/(?:^|[\/\\])\.\.(?:$|[\/\\])/.test(filename)) {
27
- return;
28
- }
29
- let root = options.root || "";
30
27
  const defaultDocument = options.defaultDocument || "index.html";
31
28
  if (filename.endsWith("/")) {
32
29
  filename = filename.concat(defaultDocument);
33
30
  } else if (!filename.match(/\.[a-zA-Z0-9]+$/)) {
34
31
  filename = filename.concat("/" + defaultDocument);
35
32
  }
33
+ const path = getFilePathWithoutDefaultDocument({
34
+ root: options.root,
35
+ filename
36
+ });
37
+ return path;
38
+ };
39
+ const getFilePathWithoutDefaultDocument = (options) => {
40
+ let root = options.root || "";
41
+ let filename = options.filename;
42
+ if (/(?:^|[\/\\])\.\.(?:$|[\/\\])/.test(filename)) {
43
+ return;
44
+ }
36
45
  filename = filename.replace(/^\.?[\/\\]/, "");
37
46
  filename = filename.replace(/\\/, "/");
38
47
  root = root.replace(/\/$/, "");
@@ -42,5 +51,6 @@ const getFilePath = (options) => {
42
51
  };
43
52
  // Annotate the CommonJS export names for ESM import in node:
44
53
  0 && (module.exports = {
45
- getFilePath
54
+ getFilePath,
55
+ getFilePathWithoutDefaultDocument
46
56
  });
@@ -6,11 +6,10 @@ import { joinPaths, dirname, filterStaticGenerateRoutes } from "./utils.js";
6
6
  var SSG_CONTEXT = "HONO_SSG_CONTEXT";
7
7
  var SSG_DISABLED_RESPONSE = new Response("SSG is disabled", { status: 404 });
8
8
  var generateFilePath = (routePath, outDir, mimeType) => {
9
- const hasExtension = /\.[^\/]+$/.test(routePath);
10
- if (hasExtension) {
9
+ const extension = determineExtension(mimeType);
10
+ if (routePath.endsWith(`.${extension}`)) {
11
11
  return joinPaths(outDir, routePath);
12
12
  }
13
- const extension = determineExtension(mimeType);
14
13
  if (routePath === "/") {
15
14
  return joinPaths(outDir, `index.${extension}`);
16
15
  }
@@ -23,10 +23,22 @@ var setSSEHeaders = (context) => {
23
23
  context.header("Cache-Control", "no-cache");
24
24
  context.header("Connection", "keep-alive");
25
25
  };
26
- var streamSSE = (c, cb) => {
26
+ var streamSSE = (c, cb, onError) => {
27
27
  const { readable, writable } = new TransformStream();
28
28
  const stream = new SSEStreamingApi(writable, readable);
29
- cb(stream).finally(() => stream.close());
29
+ (async () => {
30
+ try {
31
+ await cb(stream);
32
+ } catch (e) {
33
+ if (e instanceof Error && onError) {
34
+ await onError(e, stream);
35
+ } else {
36
+ console.error(e);
37
+ }
38
+ } finally {
39
+ stream.close();
40
+ }
41
+ })();
30
42
  setSSEHeaders(c);
31
43
  return c.newResponse(stream.responseReadable);
32
44
  };
@@ -1,9 +1,21 @@
1
1
  // src/helper/streaming/stream.ts
2
2
  import { StreamingApi } from "../../utils/stream.js";
3
- var stream = (c, cb) => {
3
+ var stream = (c, cb, onError) => {
4
4
  const { readable, writable } = new TransformStream();
5
5
  const stream2 = new StreamingApi(writable, readable);
6
- cb(stream2).finally(() => stream2.close());
6
+ (async () => {
7
+ try {
8
+ await cb(stream2);
9
+ } catch (e) {
10
+ if (e instanceof Error && onError) {
11
+ await onError(e, stream2);
12
+ } else {
13
+ console.error(e);
14
+ }
15
+ } finally {
16
+ stream2.close();
17
+ }
18
+ })();
7
19
  return c.newResponse(stream2.responseReadable);
8
20
  };
9
21
  export {
@@ -1,11 +1,11 @@
1
1
  // src/helper/streaming/text.ts
2
2
  import { TEXT_PLAIN } from "../../context.js";
3
3
  import { stream } from "./index.js";
4
- var streamText = (c, cb) => {
4
+ var streamText = (c, cb, onError) => {
5
5
  c.header("Content-Type", TEXT_PLAIN);
6
6
  c.header("X-Content-Type-Options", "nosniff");
7
7
  c.header("Transfer-Encoding", "chunked");
8
- return stream(c, cb);
8
+ return stream(c, cb, onError);
9
9
  };
10
10
  export {
11
11
  streamText
@@ -2,11 +2,17 @@
2
2
  import { DOM_RENDERER, DOM_ERROR_HANDLER, DOM_STASH } from "../constants.js";
3
3
  import { globalContexts as globalJSXContexts } from "../context.js";
4
4
  import { STASH_EFFECT } from "../hooks/index.js";
5
+ import { useContext, createContext } from "./index.js";
5
6
  var eventAliasMap = {
6
7
  Change: "Input",
7
8
  DoubleClick: "DblClick"
8
9
  };
10
+ var nameSpaceMap = {
11
+ svg: "http://www.w3.org/2000/svg",
12
+ math: "http://www.w3.org/1998/Math/MathML"
13
+ };
9
14
  var buildDataStack = [];
15
+ var nameSpaceContext = void 0;
10
16
  var isNodeString = (node) => Array.isArray(node);
11
17
  var getEventSpec = (key) => {
12
18
  const match = key.match(/^on([A-Z][a-zA-Z]+?)((?<!Pointer)Capture)?$/);
@@ -45,6 +51,26 @@ var applyProps = (container, attributes, oldAttributes) => {
45
51
  Object.assign(container.style, value);
46
52
  }
47
53
  } else {
54
+ const nodeName = container.nodeName;
55
+ if (key === "value") {
56
+ if (nodeName === "INPUT" || nodeName === "TEXTAREA" || nodeName === "SELECT") {
57
+ ;
58
+ container.value = value === null || value === void 0 || value === false ? null : value;
59
+ if (nodeName === "TEXTAREA") {
60
+ container.textContent = value;
61
+ continue;
62
+ } else if (nodeName === "SELECT") {
63
+ if (container.selectedIndex === -1) {
64
+ ;
65
+ container.selectedIndex = 0;
66
+ }
67
+ continue;
68
+ }
69
+ }
70
+ } else if (key === "checked" && nodeName === "INPUT" || key === "selected" && nodeName === "OPTION") {
71
+ ;
72
+ container[key] = value;
73
+ }
48
74
  if (value === null || value === void 0 || value === false) {
49
75
  container.removeAttribute(key);
50
76
  } else if (value === true) {
@@ -175,12 +201,13 @@ var applyNodeObject = (node, container) => {
175
201
  const child = next[i];
176
202
  let el;
177
203
  if (isNodeString(child)) {
178
- if (child.e) {
204
+ if (child.e && child[1]) {
179
205
  child.e.textContent = child[0];
180
206
  }
207
+ child[1] = false;
181
208
  el = child.e || (child.e = document.createTextNode(child[0]));
182
209
  } else {
183
- el = child.e || (child.e = document.createElement(child.tag));
210
+ el = child.e || (child.e = child.n ? document.createElementNS(child.n, child.tag) : document.createElement(child.tag));
184
211
  applyProps(el, child.props, child.pP);
185
212
  applyNode(child, el);
186
213
  }
@@ -230,7 +257,10 @@ var build = (context, node, topLevelErrorHandlerNode, children) => {
230
257
  if (!isNodeString(oldChild)) {
231
258
  vChildrenToRemove.push(oldChild);
232
259
  } else {
233
- oldChild[0] = child[0];
260
+ if (oldChild[0] !== child[0]) {
261
+ oldChild[0] = child[0];
262
+ oldChild[1] = true;
263
+ }
234
264
  child = oldChild;
235
265
  }
236
266
  } else if (oldChild.tag !== child.tag) {
@@ -241,6 +271,11 @@ var build = (context, node, topLevelErrorHandlerNode, children) => {
241
271
  oldChild.children = child.children;
242
272
  child = oldChild;
243
273
  }
274
+ } else if (!isNodeString(child) && nameSpaceContext) {
275
+ const ns = useContext(nameSpaceContext);
276
+ if (ns) {
277
+ child.n = ns;
278
+ }
244
279
  }
245
280
  if (!isNodeString(child)) {
246
281
  build(context, child, topLevelErrorHandlerNode);
@@ -273,11 +308,27 @@ var buildNode = (node) => {
273
308
  if (node === void 0 || node === null || typeof node === "boolean") {
274
309
  return void 0;
275
310
  } else if (typeof node === "string" || typeof node === "number") {
276
- return [node.toString()];
311
+ return [node.toString(), true];
277
312
  } else {
278
313
  if (typeof node.tag === "function") {
279
314
  ;
280
315
  node[DOM_STASH] = [0, []];
316
+ } else {
317
+ const ns = nameSpaceMap[node.tag];
318
+ if (ns) {
319
+ ;
320
+ node.n = ns;
321
+ nameSpaceContext || (nameSpaceContext = createContext(""));
322
+ node.children = [
323
+ {
324
+ tag: nameSpaceContext.Provider,
325
+ props: {
326
+ value: ns
327
+ },
328
+ children: node.children
329
+ }
330
+ ];
331
+ }
281
332
  }
282
333
  return node;
283
334
  }
@@ -0,0 +1,61 @@
1
+ // src/middleware/serve-static/index.ts
2
+ import { getFilePath, getFilePathWithoutDefaultDocument } from "../../utils/filepath.js";
3
+ import { getMimeType } from "../../utils/mime.js";
4
+ var DEFAULT_DOCUMENT = "index.html";
5
+ var defaultPathResolve = (path) => path;
6
+ var serveStatic = (options) => {
7
+ return async (c, next) => {
8
+ if (c.finalized) {
9
+ await next();
10
+ return;
11
+ }
12
+ const url = new URL(c.req.url);
13
+ let filename = options.path ?? decodeURI(url.pathname);
14
+ filename = options.rewriteRequestPath ? options.rewriteRequestPath(filename) : filename;
15
+ const root = options.root;
16
+ let path = getFilePath({
17
+ filename,
18
+ root,
19
+ defaultDocument: DEFAULT_DOCUMENT
20
+ });
21
+ if (!path) {
22
+ return await next();
23
+ }
24
+ const getContent = options.getContent;
25
+ const pathResolve = options.pathResolve ?? defaultPathResolve;
26
+ path = pathResolve(path);
27
+ let content = await getContent(path);
28
+ if (!content) {
29
+ let pathWithOutDefaultDocument = getFilePathWithoutDefaultDocument({
30
+ filename,
31
+ root
32
+ });
33
+ if (!pathWithOutDefaultDocument) {
34
+ return await next();
35
+ }
36
+ pathWithOutDefaultDocument = pathResolve(pathWithOutDefaultDocument);
37
+ content = await getContent(pathWithOutDefaultDocument);
38
+ if (content) {
39
+ path = pathWithOutDefaultDocument;
40
+ }
41
+ }
42
+ if (content) {
43
+ let mimeType = void 0;
44
+ if (options.mimes) {
45
+ mimeType = getMimeType(path, options.mimes) ?? getMimeType(path);
46
+ } else {
47
+ mimeType = getMimeType(path);
48
+ }
49
+ if (mimeType) {
50
+ c.header("Content-Type", mimeType);
51
+ }
52
+ return c.body(content);
53
+ }
54
+ await options.onNotFound?.(path, c);
55
+ await next();
56
+ return;
57
+ };
58
+ };
59
+ export {
60
+ serveStatic
61
+ };
@@ -1,14 +1,12 @@
1
1
  // src/router/reg-exp-router/router.ts
2
2
  import {
3
3
  METHOD_NAME_ALL,
4
- METHODS,
5
4
  UnsupportedPathError,
6
5
  MESSAGE_MATCHER_IS_ALREADY_BUILT
7
6
  } from "../../router.js";
8
7
  import { checkOptionalParameter } from "../../utils/url.js";
9
8
  import { PATH_ERROR } from "./node.js";
10
9
  import { Trie } from "./trie.js";
11
- var methodNames = [METHOD_NAME_ALL, ...METHODS].map((method) => method.toUpperCase());
12
10
  var emptyParam = [];
13
11
  var nullMatcher = [/^$/, [], {}];
14
12
  var wildcardRegExpCache = {};
@@ -100,9 +98,6 @@ var RegExpRouter = class {
100
98
  if (!middleware || !routes) {
101
99
  throw new Error(MESSAGE_MATCHER_IS_ALREADY_BUILT);
102
100
  }
103
- if (methodNames.indexOf(method) === -1) {
104
- methodNames.push(method);
105
- }
106
101
  if (!middleware[method]) {
107
102
  ;
108
103
  [middleware, routes].forEach((handlerMap) => {
@@ -160,7 +155,7 @@ var RegExpRouter = class {
160
155
  clearWildcardRegExpCache();
161
156
  const matchers = this.buildAllMatchers();
162
157
  this.match = (method2, path2) => {
163
- const matcher = matchers[method2];
158
+ const matcher = matchers[method2] || matchers[METHOD_NAME_ALL];
164
159
  const staticMatch = matcher[2][path2];
165
160
  if (staticMatch) {
166
161
  return staticMatch;
@@ -176,8 +171,8 @@ var RegExpRouter = class {
176
171
  }
177
172
  buildAllMatchers() {
178
173
  const matchers = {};
179
- methodNames.forEach((method) => {
180
- matchers[method] = this.buildMatcher(method) || matchers[METHOD_NAME_ALL];
174
+ [...Object.keys(this.routes), ...Object.keys(this.middleware)].forEach((method) => {
175
+ matchers[method] || (matchers[method] = this.buildMatcher(method));
181
176
  });
182
177
  this.middleware = this.routes = void 0;
183
178
  return matchers;
@@ -1,10 +1,3 @@
1
- import type { Context } from '../../context';
1
+ import type { ServeStaticOptions } from '../../middleware/serve-static';
2
2
  import type { Env, MiddlewareHandler } from '../../types';
3
- export type ServeStaticOptions<E extends Env = Env> = {
4
- root?: string;
5
- path?: string;
6
- mimes?: Record<string, string>;
7
- rewriteRequestPath?: (path: string) => string;
8
- onNotFound?: (path: string, c: Context<E>) => void | Promise<void>;
9
- };
10
- export declare const serveStatic: <E extends Env = Env>(options?: ServeStaticOptions<E>) => MiddlewareHandler;
3
+ export declare const serveStatic: <E extends Env = Env>(options: ServeStaticOptions<E>) => MiddlewareHandler;
@@ -1,13 +1,8 @@
1
1
  import type { KVNamespace } from '@cloudflare/workers-types';
2
- import type { Context } from '../../context';
2
+ import type { ServeStaticOptions as BaseServeStaticOptions } from '../../middleware/serve-static';
3
3
  import type { Env, MiddlewareHandler } from '../../types';
4
- export type ServeStaticOptions<E extends Env = Env> = {
5
- root?: string;
6
- path?: string;
7
- mimes?: Record<string, string>;
8
- manifest: object | string;
4
+ export type ServeStaticOptions<E extends Env = Env> = BaseServeStaticOptions<E> & {
9
5
  namespace?: KVNamespace;
10
- rewriteRequestPath?: (path: string) => string;
11
- onNotFound?: (path: string, c: Context<E>) => void | Promise<void>;
6
+ manifest: object | string;
12
7
  };
13
8
  export declare const serveStatic: <E extends Env = Env>(options: ServeStaticOptions<E>) => MiddlewareHandler;
@@ -1,10 +1,3 @@
1
- import type { Context } from '../../context';
1
+ import type { ServeStaticOptions } from '../../middleware/serve-static';
2
2
  import type { Env, MiddlewareHandler } from '../../types';
3
- export type ServeStaticOptions<E extends Env = Env> = {
4
- root?: string;
5
- path?: string;
6
- mimes?: Record<string, string>;
7
- rewriteRequestPath?: (path: string) => string;
8
- onNotFound?: (path: string, c: Context<E>) => void | Promise<void>;
9
- };
10
- export declare const serveStatic: <E extends Env = Env>(options?: ServeStaticOptions<E>) => MiddlewareHandler;
3
+ export declare const serveStatic: <E extends Env = Env>(options: ServeStaticOptions<E>) => MiddlewareHandler;
@@ -1,5 +1,3 @@
1
- import type { FC } from './jsx';
2
- import type { PropsForRenderer } from './middleware/jsx-renderer';
3
1
  import type { HonoRequest } from './request';
4
2
  import type { Env, FetchEventLike, NotFoundHandler, Input, TypedResponse } from './types';
5
3
  import type { RedirectStatusCode, StatusCode } from './utils/http-status';
@@ -18,6 +16,8 @@ interface DefaultRenderer {
18
16
  (content: string | Promise<string>): Response | Promise<Response>;
19
17
  }
20
18
  export type Renderer = ContextRenderer extends Function ? ContextRenderer : DefaultRenderer;
19
+ export type PropsForRenderer = [...Required<Parameters<Renderer>>] extends [unknown, infer Props] ? Props : unknown;
20
+ export type Layout<T = Record<string, any>> = (props: T) => any;
21
21
  interface Get<E extends Env> {
22
22
  <Key extends keyof ContextVariableMap>(key: Key): ContextVariableMap[Key];
23
23
  <Key extends keyof E['Variables']>(key: Key): E['Variables'][Key];
@@ -112,13 +112,13 @@ export declare class Context<E extends Env = any, P extends string = any, I exte
112
112
  * @see https://hono.dev/api/context#render-setrenderer
113
113
  */
114
114
  render: Renderer;
115
- setLayout: (layout: FC<PropsForRenderer & {
116
- Layout: FC;
117
- }>) => FC<{
118
- Layout: FC;
115
+ setLayout: (layout: Layout<PropsForRenderer & {
116
+ Layout: Layout;
117
+ }>) => Layout<{
118
+ Layout: Layout;
119
119
  }>;
120
- getLayout: () => FC<{
121
- Layout: FC;
120
+ getLayout: () => Layout<{
121
+ Layout: Layout;
122
122
  }> | undefined;
123
123
  /**
124
124
  * `.setRenderer()` can set the layout in the custom middleware.
@@ -10,4 +10,4 @@ export declare class SSEStreamingApi extends StreamingApi {
10
10
  constructor(writable: WritableStream, readable: ReadableStream);
11
11
  writeSSE(message: SSEMessage): Promise<void>;
12
12
  }
13
- export declare const streamSSE: (c: Context, cb: (stream: SSEStreamingApi) => Promise<void>) => Response;
13
+ export declare const streamSSE: (c: Context, cb: (stream: SSEStreamingApi) => Promise<void>, onError?: ((e: Error, stream: SSEStreamingApi) => Promise<void>) | undefined) => Response;
@@ -1,3 +1,3 @@
1
1
  import type { Context } from '../../context';
2
2
  import { StreamingApi } from '../../utils/stream';
3
- export declare const stream: (c: Context, cb: (stream: StreamingApi) => Promise<void>) => Response;
3
+ export declare const stream: (c: Context, cb: (stream: StreamingApi) => Promise<void>, onError?: ((e: Error, stream: StreamingApi) => Promise<void>) | undefined) => Response;
@@ -1,3 +1,3 @@
1
1
  import type { Context } from '../../context';
2
2
  import type { StreamingApi } from '../../utils/stream';
3
- export declare const streamText: (c: Context, cb: (stream: StreamingApi) => Promise<void>) => Response;
3
+ export declare const streamText: (c: Context, cb: (stream: StreamingApi) => Promise<void>, onError?: ((e: Error, stream: StreamingApi) => Promise<void>) | undefined) => Response;
@@ -8,14 +8,16 @@ export type HasRenderToDom = FC<any> & {
8
8
  export type ErrorHandler = (error: any, retry: () => void) => Child | undefined;
9
9
  type Container = HTMLElement | DocumentFragment;
10
10
  type LocalJSXContexts = [JSXContext<unknown>, unknown][] | undefined;
11
+ type SupportedElement = HTMLElement | SVGElement | MathMLElement;
11
12
  export type NodeObject = {
12
13
  pP: Props | undefined;
13
14
  nN: Node | undefined;
14
15
  vC: Node[];
15
16
  vR: Node[];
16
17
  s?: Node[];
18
+ n?: string;
17
19
  c: Container | undefined;
18
- e: HTMLElement | Text | undefined;
20
+ e: SupportedElement | Text | undefined;
19
21
  [DOM_STASH]: [
20
22
  number,
21
23
  any[][],
@@ -25,7 +27,10 @@ export type NodeObject = {
25
27
  any[][]
26
28
  ];
27
29
  } & JSXNode;
28
- type NodeString = [string] & {
30
+ type NodeString = [
31
+ string,
32
+ boolean
33
+ ] & {
29
34
  e?: Text;
30
35
  vC: undefined;
31
36
  nN: undefined;
@@ -1,8 +1,7 @@
1
- import type { Context, Renderer } from '../../context';
1
+ import type { Context, PropsForRenderer } from '../../context';
2
2
  import type { FC, PropsWithChildren } from '../../jsx';
3
3
  import type { Env, Input, MiddlewareHandler } from '../../types';
4
4
  export declare const RequestContext: import("../../jsx").Context<Context<any, any, {}> | null>;
5
- export type PropsForRenderer = [...Required<Parameters<Renderer>>] extends [unknown, infer Props] ? Props : unknown;
6
5
  type RendererOptions = {
7
6
  docType?: boolean | string;
8
7
  stream?: boolean | Record<string, string>;
@@ -0,0 +1,16 @@
1
+ import type { Context } from '../../context';
2
+ import type { Env, MiddlewareHandler } from '../../types';
3
+ export type ServeStaticOptions<E extends Env = Env> = {
4
+ root?: string;
5
+ path?: string;
6
+ mimes?: Record<string, string>;
7
+ rewriteRequestPath?: (path: string) => string;
8
+ onNotFound?: (path: string, c: Context<E>) => void | Promise<void>;
9
+ };
10
+ /**
11
+ * This middleware is not directly used by the user. Create a wrapper specifying `getContent()` by the environment such as Deno or Bun.
12
+ */
13
+ export declare const serveStatic: <E extends Env = Env>(options: ServeStaticOptions<E> & {
14
+ getContent: (path: string) => any;
15
+ pathResolve?: ((path: string) => string) | undefined;
16
+ }) => MiddlewareHandler;
@@ -4,4 +4,5 @@ type FilePathOptions = {
4
4
  defaultDocument?: string;
5
5
  };
6
6
  export declare const getFilePath: (options: FilePathOptions) => string | undefined;
7
+ export declare const getFilePathWithoutDefaultDocument: (options: Omit<FilePathOptions, 'defaultDocument'>) => string | undefined;
7
8
  export {};
@@ -1,16 +1,24 @@
1
1
  // src/utils/filepath.ts
2
2
  var getFilePath = (options) => {
3
3
  let filename = options.filename;
4
- if (/(?:^|[\/\\])\.\.(?:$|[\/\\])/.test(filename)) {
5
- return;
6
- }
7
- let root = options.root || "";
8
4
  const defaultDocument = options.defaultDocument || "index.html";
9
5
  if (filename.endsWith("/")) {
10
6
  filename = filename.concat(defaultDocument);
11
7
  } else if (!filename.match(/\.[a-zA-Z0-9]+$/)) {
12
8
  filename = filename.concat("/" + defaultDocument);
13
9
  }
10
+ const path = getFilePathWithoutDefaultDocument({
11
+ root: options.root,
12
+ filename
13
+ });
14
+ return path;
15
+ };
16
+ var getFilePathWithoutDefaultDocument = (options) => {
17
+ let root = options.root || "";
18
+ let filename = options.filename;
19
+ if (/(?:^|[\/\\])\.\.(?:$|[\/\\])/.test(filename)) {
20
+ return;
21
+ }
14
22
  filename = filename.replace(/^\.?[\/\\]/, "");
15
23
  filename = filename.replace(/\\/, "/");
16
24
  root = root.replace(/\/$/, "");
@@ -19,5 +27,6 @@ var getFilePath = (options) => {
19
27
  return path;
20
28
  };
21
29
  export {
22
- getFilePath
30
+ getFilePath,
31
+ getFilePathWithoutDefaultDocument
23
32
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hono",
3
- "version": "4.0.4",
3
+ "version": "4.0.6",
4
4
  "description": "Ultrafast web framework for the Edges",
5
5
  "main": "dist/cjs/index.js",
6
6
  "type": "module",