hono 4.12.9 → 4.12.18

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 (57) hide show
  1. package/dist/adapter/aws-lambda/handler.js +9 -2
  2. package/dist/cjs/adapter/aws-lambda/handler.js +9 -2
  3. package/dist/cjs/helper/css/common.js +56 -7
  4. package/dist/cjs/helper/css/index.js +11 -4
  5. package/dist/cjs/helper/ssg/ssg.js +12 -8
  6. package/dist/cjs/helper/ssg/utils.js +9 -0
  7. package/dist/cjs/jsx/base.js +7 -1
  8. package/dist/cjs/jsx/dom/css.js +11 -4
  9. package/dist/cjs/jsx/dom/render.js +39 -17
  10. package/dist/cjs/jsx/jsx-runtime.js +3 -0
  11. package/dist/cjs/jsx/utils.js +155 -5
  12. package/dist/cjs/middleware/body-limit/index.js +21 -30
  13. package/dist/cjs/middleware/cache/index.js +11 -3
  14. package/dist/cjs/middleware/compress/index.js +4 -0
  15. package/dist/cjs/middleware/cors/index.js +2 -5
  16. package/dist/cjs/middleware/ip-restriction/index.js +31 -9
  17. package/dist/cjs/middleware/method-override/index.js +1 -1
  18. package/dist/cjs/middleware/serve-static/index.js +1 -1
  19. package/dist/cjs/middleware/trailing-slash/index.js +2 -2
  20. package/dist/cjs/utils/cookie.js +26 -5
  21. package/dist/cjs/utils/ipaddr.js +10 -4
  22. package/dist/cjs/utils/jwt/jws.js +1 -1
  23. package/dist/cjs/utils/jwt/jwt.js +12 -6
  24. package/dist/helper/css/common.js +56 -7
  25. package/dist/helper/css/index.js +11 -4
  26. package/dist/helper/ssg/ssg.js +19 -9
  27. package/dist/helper/ssg/utils.js +8 -0
  28. package/dist/jsx/base.js +13 -2
  29. package/dist/jsx/dom/css.js +11 -4
  30. package/dist/jsx/dom/render.js +39 -17
  31. package/dist/jsx/jsx-runtime.js +4 -1
  32. package/dist/jsx/utils.js +153 -5
  33. package/dist/middleware/body-limit/index.js +21 -30
  34. package/dist/middleware/cache/index.js +11 -3
  35. package/dist/middleware/compress/index.js +4 -0
  36. package/dist/middleware/cors/index.js +2 -5
  37. package/dist/middleware/ip-restriction/index.js +34 -10
  38. package/dist/middleware/method-override/index.js +1 -1
  39. package/dist/middleware/serve-static/index.js +1 -1
  40. package/dist/middleware/trailing-slash/index.js +2 -2
  41. package/dist/tsconfig.build.tsbuildinfo +1 -1
  42. package/dist/types/helper/css/common.d.ts +20 -3
  43. package/dist/types/helper/css/index.d.ts +9 -2
  44. package/dist/types/helper/ssg/utils.d.ts +1 -0
  45. package/dist/types/jsx/dom/css.d.ts +8 -2
  46. package/dist/types/jsx/utils.d.ts +3 -1
  47. package/dist/types/middleware/cache/index.d.ts +2 -0
  48. package/dist/types/middleware/cors/index.d.ts +1 -1
  49. package/dist/types/middleware/ip-restriction/index.d.ts +38 -2
  50. package/dist/types/middleware/trailing-slash/index.d.ts +16 -0
  51. package/dist/types/types.d.ts +116 -116
  52. package/dist/types/utils/ipaddr.d.ts +12 -0
  53. package/dist/utils/cookie.js +26 -5
  54. package/dist/utils/ipaddr.js +7 -3
  55. package/dist/utils/jwt/jws.js +1 -1
  56. package/dist/utils/jwt/jwt.js +12 -6
  57. package/package.json +1 -1
@@ -62,8 +62,15 @@ var streamHandle = (app) => {
62
62
  var handle = (app, { isContentTypeBinary } = { isContentTypeBinary: void 0 }) => {
63
63
  return async (event, lambdaContext) => {
64
64
  const processor = getProcessor(event);
65
- const req = processor.createRequest(event);
66
- const requestContext = getRequestContext(event);
65
+ let req, requestContext;
66
+ try {
67
+ req = processor.createRequest(event);
68
+ requestContext = getRequestContext(event);
69
+ } catch (error) {
70
+ console.error("Error processing request:", error);
71
+ const errorResponse = error instanceof TypeError ? new Response("Invalid request", { status: 400 }) : new Response("Internal Server Error", { status: 500 });
72
+ return processor.createResult(event, errorResponse, { isContentTypeBinary });
73
+ }
67
74
  const res = await app.fetch(req, {
68
75
  event,
69
76
  requestContext,
@@ -92,8 +92,15 @@ const streamHandle = (app) => {
92
92
  const handle = (app, { isContentTypeBinary } = { isContentTypeBinary: void 0 }) => {
93
93
  return async (event, lambdaContext) => {
94
94
  const processor = getProcessor(event);
95
- const req = processor.createRequest(event);
96
- const requestContext = getRequestContext(event);
95
+ let req, requestContext;
96
+ try {
97
+ req = processor.createRequest(event);
98
+ requestContext = getRequestContext(event);
99
+ } catch (error) {
100
+ console.error("Error processing request:", error);
101
+ const errorResponse = error instanceof TypeError ? new Response("Invalid request", { status: 400 }) : new Response("Internal Server Error", { status: 500 });
102
+ return processor.createResult(event, errorResponse, { isContentTypeBinary });
103
+ }
97
104
  const res = await app.fetch(req, {
98
105
  event,
99
106
  requestContext,
@@ -57,6 +57,23 @@ const toHash = (str) => {
57
57
  }
58
58
  return "css-" + out;
59
59
  };
60
+ const normalizeLabel = (label) => {
61
+ return label.trim().replace(/\s+/g, "-");
62
+ };
63
+ const isValidClassName = (name) => /^-?[_a-zA-Z][_a-zA-Z0-9-]*$/.test(name);
64
+ const RESERVED_KEYFRAME_NAMES = /* @__PURE__ */ new Set([
65
+ "default",
66
+ "inherit",
67
+ "initial",
68
+ "none",
69
+ "revert",
70
+ "revert-layer",
71
+ "unset"
72
+ ]);
73
+ const isValidKeyframeName = (name) => isValidClassName(name) && !RESERVED_KEYFRAME_NAMES.has(name.toLowerCase());
74
+ const defaultOnInvalidSlug = (slug) => {
75
+ console.warn(`Invalid slug: ${slug}`);
76
+ };
60
77
  const cssStringReStr = [
61
78
  '"(?:(?:\\\\[\\s\\S]|[^"\\\\])*)"',
62
79
  // double quoted string
@@ -143,13 +160,26 @@ const buildStyleString = (strings, values) => {
143
160
  }
144
161
  return [label, minify(styleString), selectors, externalClassNames];
145
162
  };
146
- const cssCommon = (strings, values) => {
163
+ const cssCommon = (strings, values, classNameSlug, onInvalidSlug) => {
147
164
  let [label, thisStyleString, selectors, externalClassNames] = buildStyleString(strings, values);
148
165
  const isPseudoGlobal = isPseudoGlobalSelectorRe.exec(thisStyleString);
149
166
  if (isPseudoGlobal) {
150
167
  thisStyleString = isPseudoGlobal[1];
151
168
  }
152
- const selector = (isPseudoGlobal ? PSEUDO_GLOBAL_SELECTOR : "") + toHash(label + thisStyleString);
169
+ const hash = toHash(label + thisStyleString);
170
+ let customSlug;
171
+ if (classNameSlug) {
172
+ const slug = classNameSlug(hash, normalizeLabel(label), thisStyleString);
173
+ if (slug) {
174
+ if (isValidClassName(slug)) {
175
+ customSlug = slug;
176
+ } else {
177
+ ;
178
+ (onInvalidSlug || defaultOnInvalidSlug)(slug);
179
+ }
180
+ }
181
+ }
182
+ const selector = (isPseudoGlobal ? PSEUDO_GLOBAL_SELECTOR : "") + (customSlug || hash);
153
183
  const className = (isPseudoGlobal ? selectors.map((s) => s[CLASS_NAME]) : [selector, ...externalClassNames]).join(" ");
154
184
  return {
155
185
  [SELECTOR]: selector,
@@ -174,24 +204,43 @@ const cxCommon = (args) => {
174
204
  }
175
205
  return args;
176
206
  };
177
- const keyframesCommon = (strings, ...values) => {
207
+ const keyframesCommon = (strings, values, classNameSlug, onInvalidSlug) => {
178
208
  const [label, styleString] = buildStyleString(strings, values);
209
+ const hash = toHash(label + styleString);
210
+ let customSlug;
211
+ if (classNameSlug) {
212
+ const slug = classNameSlug(hash, normalizeLabel(label), styleString);
213
+ if (slug) {
214
+ if (isValidKeyframeName(slug)) {
215
+ customSlug = slug;
216
+ } else {
217
+ ;
218
+ (onInvalidSlug || defaultOnInvalidSlug)(slug);
219
+ }
220
+ }
221
+ }
179
222
  return {
180
223
  [SELECTOR]: "",
181
- [CLASS_NAME]: `@keyframes ${toHash(label + styleString)}`,
224
+ [CLASS_NAME]: `@keyframes ${customSlug || hash}`,
182
225
  [STYLE_STRING]: styleString,
183
226
  [SELECTORS]: [],
184
227
  [EXTERNAL_CLASS_NAMES]: []
185
228
  };
186
229
  };
187
230
  let viewTransitionNameIndex = 0;
188
- const viewTransitionCommon = ((strings, values) => {
231
+ const viewTransitionCommon = ((strings, values, classNameSlug, onInvalidSlug) => {
189
232
  if (!strings) {
190
233
  strings = [`/* h-v-t ${viewTransitionNameIndex++} */`];
191
234
  }
192
- const content = Array.isArray(strings) ? cssCommon(strings, values) : strings;
235
+ const content = Array.isArray(strings) ? cssCommon(strings, values, classNameSlug, onInvalidSlug) : strings;
193
236
  const transitionName = content[CLASS_NAME];
194
- const res = cssCommon(["view-transition-name:", ""], [transitionName]);
237
+ const res = cssCommon(
238
+ ["view-transition-name:", ""],
239
+ // eslint-disable-line @typescript-eslint/no-explicit-any
240
+ [transitionName],
241
+ classNameSlug,
242
+ onInvalidSlug
243
+ );
195
244
  content[CLASS_NAME] = PSEUDO_GLOBAL_SELECTOR + content[CLASS_NAME];
196
245
  content[STYLE_STRING] = content[STYLE_STRING].replace(
197
246
  /(?<=::view-transition(?:[a-z-]*)\()(?=\))/g,
@@ -31,7 +31,11 @@ var import_constants = require("../../jsx/constants");
31
31
  var import_css = require("../../jsx/dom/css");
32
32
  var import_common = require("./common");
33
33
  var import_common2 = require("./common");
34
- const createCssContext = ({ id }) => {
34
+ const createCssContext = ({
35
+ id,
36
+ classNameSlug,
37
+ onInvalidSlug
38
+ }) => {
35
39
  const [cssJsxDomObject, StyleRenderToDom] = (0, import_css.createCssJsxDomObjects)({ id });
36
40
  const contextMap = /* @__PURE__ */ new WeakMap();
37
41
  const nonceMap = /* @__PURE__ */ new WeakMap();
@@ -94,15 +98,18 @@ const createCssContext = ({ id }) => {
94
98
  return promise;
95
99
  };
96
100
  const css2 = (strings, ...values) => {
97
- return newCssClassNameObject((0, import_common.cssCommon)(strings, values));
101
+ return newCssClassNameObject((0, import_common.cssCommon)(strings, values, classNameSlug, onInvalidSlug));
98
102
  };
99
103
  const cx2 = (...args) => {
100
104
  args = (0, import_common.cxCommon)(args);
101
105
  return css2(Array(args.length).fill(""), ...args);
102
106
  };
103
- const keyframes2 = import_common.keyframesCommon;
107
+ const keyframes2 = (strings, ...values) => (0, import_common.keyframesCommon)(strings, values, classNameSlug, onInvalidSlug);
104
108
  const viewTransition2 = ((strings, ...values) => {
105
- return newCssClassNameObject((0, import_common.viewTransitionCommon)(strings, values));
109
+ return newCssClassNameObject(
110
+ (0, import_common.viewTransitionCommon)(strings, values, classNameSlug, onInvalidSlug)
111
+ // eslint-disable-line @typescript-eslint/no-explicit-any
112
+ );
106
113
  });
107
114
  const Style2 = ({ children, nonce } = {}) => (0, import_html.raw)(
108
115
  `<style id="${id}"${nonce ? ` nonce="${nonce}"` : ""}>${children ? children[import_common.STYLE_STRING] : ""}</style>`,
@@ -38,16 +38,18 @@ const DEFAULT_CONTENT_TYPE = "text/plain";
38
38
  const DEFAULT_OUTPUT_DIR = "./static";
39
39
  const generateFilePath = (routePath, outDir, mimeType, extensionMap) => {
40
40
  const extension = determineExtension(mimeType, extensionMap);
41
+ let filePath;
41
42
  if (routePath.endsWith(`.${extension}`)) {
42
- return (0, import_utils2.joinPaths)(outDir, routePath);
43
+ filePath = (0, import_utils2.joinPaths)(outDir, routePath);
44
+ } else if (routePath === "/") {
45
+ filePath = (0, import_utils2.joinPaths)(outDir, `index.${extension}`);
46
+ } else if (routePath.endsWith("/")) {
47
+ filePath = (0, import_utils2.joinPaths)(outDir, routePath, `index.${extension}`);
48
+ } else {
49
+ filePath = (0, import_utils2.joinPaths)(outDir, `${routePath}.${extension}`);
43
50
  }
44
- if (routePath === "/") {
45
- return (0, import_utils2.joinPaths)(outDir, `index.${extension}`);
46
- }
47
- if (routePath.endsWith("/")) {
48
- return (0, import_utils2.joinPaths)(outDir, routePath, `index.${extension}`);
49
- }
50
- return (0, import_utils2.joinPaths)(outDir, `${routePath}.${extension}`);
51
+ (0, import_utils2.ensureWithinOutDir)(outDir, filePath);
52
+ return filePath;
51
53
  };
52
54
  const parseResponseContent = async (response) => {
53
55
  const contentType = response.headers.get("Content-Type");
@@ -67,6 +69,8 @@ const defaultExtensionMap = {
67
69
  "text/html": "html",
68
70
  "text/xml": "xml",
69
71
  "application/xml": "xml",
72
+ "application/atom+xml": "xml",
73
+ "application/rss+xml": "xml",
70
74
  "application/yaml": "yaml"
71
75
  };
72
76
  const determineExtension = (mimeType, userExtensionMap) => {
@@ -18,6 +18,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
18
18
  var utils_exports = {};
19
19
  __export(utils_exports, {
20
20
  dirname: () => dirname,
21
+ ensureWithinOutDir: () => ensureWithinOutDir,
21
22
  filterStaticGenerateRoutes: () => filterStaticGenerateRoutes,
22
23
  isDynamicRoute: () => isDynamicRoute,
23
24
  joinPaths: () => joinPaths
@@ -75,9 +76,17 @@ const filterStaticGenerateRoutes = (hono) => {
75
76
  const isDynamicRoute = (path) => {
76
77
  return path.split("/").some((segment) => segment.startsWith(":") || segment.includes("*"));
77
78
  };
79
+ const ensureWithinOutDir = (outDir, filePath) => {
80
+ const normalizedOutDir = joinPaths("/", outDir);
81
+ const normalizedFilePath = joinPaths("/", filePath);
82
+ if (normalizedFilePath !== normalizedOutDir && !normalizedFilePath.startsWith(`${normalizedOutDir}/`)) {
83
+ throw new Error(`Path traversal detected: "${filePath}" is outside the output directory`);
84
+ }
85
+ };
78
86
  // Annotate the CommonJS export names for ESM import in node:
79
87
  0 && (module.exports = {
80
88
  dirname,
89
+ ensureWithinOutDir,
81
90
  filterStaticGenerateRoutes,
82
91
  isDynamicRoute,
83
92
  joinPaths
@@ -127,6 +127,9 @@ class JSXNode {
127
127
  isEscaped = true;
128
128
  localContexts;
129
129
  constructor(tag, props, children) {
130
+ if (typeof tag !== "function" && !(0, import_utils.isValidTagName)(tag)) {
131
+ throw new Error(`Invalid JSX tag name: ${tag}`);
132
+ }
130
133
  this.tag = tag;
131
134
  this.props = props;
132
135
  this.children = children;
@@ -158,9 +161,12 @@ class JSXNode {
158
161
  const props = this.props;
159
162
  let { children } = this;
160
163
  buffer[0] += `<${tag}`;
161
- const normalizeKey = nameSpaceContext && (0, import_context.useContext)(nameSpaceContext) === "svg" ? (key) => toSVGAttributeName((0, import_utils.normalizeIntrinsicElementKey)(key)) : (key) => (0, import_utils.normalizeIntrinsicElementKey)(key);
164
+ const normalizeKey = tag === "svg" || nameSpaceContext && (0, import_context.useContext)(nameSpaceContext) === "svg" ? (key) => toSVGAttributeName((0, import_utils.normalizeIntrinsicElementKey)(key)) : (key) => (0, import_utils.normalizeIntrinsicElementKey)(key);
162
165
  for (let [key, v] of Object.entries(props)) {
163
166
  key = normalizeKey(key);
167
+ if (!(0, import_utils.isValidAttributeName)(key)) {
168
+ continue;
169
+ }
164
170
  if (key === "children") {
165
171
  } else if (key === "style" && typeof v === "object") {
166
172
  let styleStr = "";
@@ -117,22 +117,29 @@ const createCssJsxDomObjects = ({ id }) => {
117
117
  });
118
118
  return [cssObject, Style2];
119
119
  };
120
- const createCssContext = ({ id }) => {
120
+ const createCssContext = ({
121
+ id,
122
+ classNameSlug,
123
+ onInvalidSlug
124
+ }) => {
121
125
  const [cssObject, Style2] = createCssJsxDomObjects({ id });
122
126
  const newCssClassNameObject = (cssClassName) => {
123
127
  cssClassName.toString = cssObject.toString;
124
128
  return cssClassName;
125
129
  };
126
130
  const css2 = (strings, ...values) => {
127
- return newCssClassNameObject((0, import_common.cssCommon)(strings, values));
131
+ return newCssClassNameObject((0, import_common.cssCommon)(strings, values, classNameSlug, onInvalidSlug));
128
132
  };
129
133
  const cx2 = (...args) => {
130
134
  args = (0, import_common.cxCommon)(args);
131
135
  return css2(Array(args.length).fill(""), ...args);
132
136
  };
133
- const keyframes2 = import_common.keyframesCommon;
137
+ const keyframes2 = (strings, ...values) => (0, import_common.keyframesCommon)(strings, values, classNameSlug, onInvalidSlug);
134
138
  const viewTransition2 = ((strings, ...values) => {
135
- return newCssClassNameObject((0, import_common.viewTransitionCommon)(strings, values));
139
+ return newCssClassNameObject(
140
+ (0, import_common.viewTransitionCommon)(strings, values, classNameSlug, onInvalidSlug)
141
+ // eslint-disable-line @typescript-eslint/no-explicit-any
142
+ );
136
143
  });
137
144
  return {
138
145
  css: css2,
@@ -68,6 +68,17 @@ const getEventSpec = (key) => {
68
68
  };
69
69
  const toAttributeName = (element, key) => nameSpaceContext && element instanceof SVGElement && /[A-Z]/.test(key) && (key in element.style || // Presentation attributes are findable in style object. "clip-path", "font-size", "stroke-width", etc.
70
70
  key.match(/^(?:o|pai|str|u|ve)/)) ? key.replace(/([A-Z])/g, "-$1").toLowerCase() : key;
71
+ const normalizeFormValue = (value) => value === null || value === void 0 || value === false ? null : value;
72
+ const applySelectValue = (select, props) => {
73
+ if (!("value" in props)) {
74
+ return;
75
+ }
76
+ select.value = normalizeFormValue(props["value"]);
77
+ if (!select.multiple && select.selectedIndex === -1) {
78
+ select.selectedIndex = 0;
79
+ }
80
+ };
81
+ const isIgnorableAttributeError = (error) => error instanceof DOMException && error.name === "InvalidCharacterError";
71
82
  const applyProps = (container, attributes, oldAttributes) => {
72
83
  attributes ||= {};
73
84
  for (let key in attributes) {
@@ -111,18 +122,14 @@ const applyProps = (container, attributes, oldAttributes) => {
111
122
  } else {
112
123
  if (key === "value") {
113
124
  const nodeName = container.nodeName;
114
- if (nodeName === "INPUT" || nodeName === "TEXTAREA" || nodeName === "SELECT") {
125
+ if (nodeName === "SELECT") {
126
+ continue;
127
+ } else if (nodeName === "INPUT" || nodeName === "TEXTAREA") {
115
128
  ;
116
- container.value = value === null || value === void 0 || value === false ? null : value;
129
+ container.value = normalizeFormValue(value);
117
130
  if (nodeName === "TEXTAREA") {
118
131
  container.textContent = value;
119
132
  continue;
120
- } else if (nodeName === "SELECT") {
121
- if (container.selectedIndex === -1) {
122
- ;
123
- container.selectedIndex = 0;
124
- }
125
- continue;
126
133
  }
127
134
  }
128
135
  } else if (key === "checked" && container.nodeName === "INPUT" || key === "selected" && container.nodeName === "OPTION") {
@@ -130,14 +137,20 @@ const applyProps = (container, attributes, oldAttributes) => {
130
137
  container[key] = value;
131
138
  }
132
139
  const k = toAttributeName(container, key);
133
- if (value === null || value === void 0 || value === false) {
134
- container.removeAttribute(k);
135
- } else if (value === true) {
136
- container.setAttribute(k, "");
137
- } else if (typeof value === "string" || typeof value === "number") {
138
- container.setAttribute(k, value);
139
- } else {
140
- container.setAttribute(k, value.toString());
140
+ try {
141
+ if (value === null || value === void 0 || value === false) {
142
+ container.removeAttribute(k);
143
+ } else if (value === true) {
144
+ container.setAttribute(k, "");
145
+ } else if (typeof value === "string" || typeof value === "number") {
146
+ container.setAttribute(k, value);
147
+ } else {
148
+ container.setAttribute(k, value.toString());
149
+ }
150
+ } catch (e) {
151
+ if (!isIgnorableAttributeError(e)) {
152
+ throw e;
153
+ }
141
154
  }
142
155
  }
143
156
  }
@@ -153,7 +166,13 @@ const applyProps = (container, attributes, oldAttributes) => {
153
166
  } else if (key === "ref") {
154
167
  refCleanupMap.get(container)?.();
155
168
  } else {
156
- container.removeAttribute(toAttributeName(container, key));
169
+ try {
170
+ container.removeAttribute(toAttributeName(container, key));
171
+ } catch (e) {
172
+ if (!isIgnorableAttributeError(e)) {
173
+ throw e;
174
+ }
175
+ }
157
176
  }
158
177
  }
159
178
  }
@@ -291,6 +310,9 @@ const applyNodeObject = (node, container, isNew) => {
291
310
  el = child.e ||= child.n ? document.createElementNS(child.n, child.tag) : document.createElement(child.tag);
292
311
  applyProps(el, child.props, child.pP);
293
312
  applyNodeObject(child, el, isNewLocal);
313
+ if (child.tag === "select") {
314
+ applySelectValue(el, child.props);
315
+ }
294
316
  }
295
317
  }
296
318
  if (child.tag === HONO_PORTAL_ELEMENT) {
@@ -31,6 +31,9 @@ var import_html = require("../helper/html");
31
31
  var import_html2 = require("../utils/html");
32
32
  var import_utils = require("./utils");
33
33
  const jsxAttr = (key, v) => {
34
+ if (!(0, import_utils.isValidAttributeName)(key)) {
35
+ return (0, import_html.raw)("");
36
+ }
34
37
  const buffer = [`${key}="`];
35
38
  if (key === "style" && typeof v === "object") {
36
39
  let styleStr = "";
@@ -17,6 +17,8 @@ var __copyProps = (to, from, except, desc) => {
17
17
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
18
  var utils_exports = {};
19
19
  __export(utils_exports, {
20
+ isValidAttributeName: () => isValidAttributeName,
21
+ isValidTagName: () => isValidTagName,
20
22
  normalizeIntrinsicElementKey: () => normalizeIntrinsicElementKey,
21
23
  styleObjectForEach: () => styleObjectForEach
22
24
  });
@@ -32,19 +34,167 @@ const normalizeElementKeyMap = /* @__PURE__ */ new Map([
32
34
  ["formAction", "formaction"]
33
35
  ]);
34
36
  const normalizeIntrinsicElementKey = (key) => normalizeElementKeyMap.get(key) || key;
37
+ const invalidAttributeNameCharRe = /[\s"'<>/=`\\\x00-\x1f\x7f-\x9f]/;
38
+ const validAttributeNameCache = /* @__PURE__ */ new Set();
39
+ const validAttributeNameCacheMax = 1024;
40
+ const invalidTagNameCharRe = /^[!?]|[\s"'<>/=`\\\x00-\x1f\x7f-\x9f]/;
41
+ const validTagNameCache = /* @__PURE__ */ new Set();
42
+ const validTagNameCacheMax = 256;
43
+ const cacheValidName = (cache, max, name) => {
44
+ if (cache.size >= max) {
45
+ cache.clear();
46
+ }
47
+ cache.add(name);
48
+ };
49
+ const isValidTagName = (name) => {
50
+ if (validTagNameCache.has(name)) {
51
+ return true;
52
+ }
53
+ if (typeof name !== "string") {
54
+ return false;
55
+ }
56
+ if (name.length === 0) {
57
+ return true;
58
+ }
59
+ if (invalidTagNameCharRe.test(name)) {
60
+ return false;
61
+ }
62
+ cacheValidName(validTagNameCache, validTagNameCacheMax, name);
63
+ return true;
64
+ };
65
+ const isValidAttributeName = (name) => {
66
+ if (validAttributeNameCache.has(name)) {
67
+ return true;
68
+ }
69
+ const len = name.length;
70
+ if (len === 0) {
71
+ return false;
72
+ }
73
+ for (let i = 0; i < len; i++) {
74
+ const c = name.charCodeAt(i);
75
+ if (!(c >= 97 && c <= 122 || // a-z
76
+ c >= 65 && c <= 90 || // A-Z
77
+ c >= 48 && c <= 57 || // 0-9
78
+ c === 45 || // -
79
+ c === 95 || // _
80
+ c === 46 || // .
81
+ c === 58)) {
82
+ if (!invalidAttributeNameCharRe.test(name)) {
83
+ cacheValidName(validAttributeNameCache, validAttributeNameCacheMax, name);
84
+ return true;
85
+ } else {
86
+ return false;
87
+ }
88
+ }
89
+ }
90
+ cacheValidName(validAttributeNameCache, validAttributeNameCacheMax, name);
91
+ return true;
92
+ };
93
+ const invalidStylePropertyNameCharRe = /[\s"'():;\\/\[\]{}\x00-\x1f\x7f-\x9f]/;
94
+ const validStylePropertyNameCache = /* @__PURE__ */ new Set();
95
+ const validStylePropertyNameCacheMax = 1024;
96
+ const isValidStylePropertyName = (name) => {
97
+ if (validStylePropertyNameCache.has(name)) {
98
+ return true;
99
+ }
100
+ const len = name.length;
101
+ if (len === 0) {
102
+ return false;
103
+ }
104
+ for (let i = 0; i < len; i++) {
105
+ const c = name.charCodeAt(i);
106
+ if (!(c >= 97 && c <= 122 || // a-z
107
+ c >= 65 && c <= 90 || // A-Z
108
+ c >= 48 && c <= 57 || // 0-9
109
+ c === 45 || // -
110
+ c === 95)) {
111
+ if (!invalidStylePropertyNameCharRe.test(name)) {
112
+ cacheValidName(validStylePropertyNameCache, validStylePropertyNameCacheMax, name);
113
+ return true;
114
+ } else {
115
+ return false;
116
+ }
117
+ }
118
+ }
119
+ cacheValidName(validStylePropertyNameCache, validStylePropertyNameCacheMax, name);
120
+ return true;
121
+ };
122
+ const unsafeStyleValueCharRe = /[;"'\\/\[\](){}]/;
123
+ const hasUnsafeStyleValue = (value) => {
124
+ if (!unsafeStyleValueCharRe.test(value)) {
125
+ return false;
126
+ }
127
+ let quote = 0;
128
+ const blockStack = [];
129
+ for (let i = 0, len = value.length; i < len; i++) {
130
+ const c = value.charCodeAt(i);
131
+ if (c === 92) {
132
+ if (i === len - 1) {
133
+ return true;
134
+ }
135
+ i++;
136
+ } else if (quote !== 0) {
137
+ if (c === 10 || c === 12 || c === 13) {
138
+ return true;
139
+ }
140
+ if (c === quote) {
141
+ quote = 0;
142
+ }
143
+ } else if (c === 47 && value.charCodeAt(i + 1) === 42) {
144
+ const end = value.indexOf("*/", i + 2);
145
+ if (end === -1) {
146
+ return true;
147
+ }
148
+ i = end + 1;
149
+ } else if (c === 34 || c === 39) {
150
+ quote = c;
151
+ } else if (c === 40) {
152
+ blockStack.push(41);
153
+ } else if (c === 91) {
154
+ blockStack.push(93);
155
+ } else if (c === 123 || c === 125) {
156
+ return true;
157
+ } else if (c === 41 || c === 93) {
158
+ if (blockStack[blockStack.length - 1] !== c) {
159
+ return true;
160
+ }
161
+ blockStack.pop();
162
+ } else if (c === 59 && blockStack.length === 0) {
163
+ return true;
164
+ }
165
+ }
166
+ return quote !== 0 || blockStack.length !== 0;
167
+ };
35
168
  const styleObjectForEach = (style, fn) => {
36
169
  for (const [k, v] of Object.entries(style)) {
37
170
  const key = k[0] === "-" || !/[A-Z]/.test(k) ? k : k.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
38
- fn(
39
- key,
40
- v == null ? null : typeof v === "number" ? !key.match(
171
+ if (!isValidStylePropertyName(key)) {
172
+ continue;
173
+ }
174
+ if (v == null) {
175
+ fn(key, null);
176
+ continue;
177
+ }
178
+ let value;
179
+ if (typeof v === "number") {
180
+ value = !key.match(
41
181
  /^(?:a|border-im|column(?:-c|s)|flex(?:$|-[^b])|grid-(?:ar|[^a])|font-w|li|or|sca|st|ta|wido|z)|ty$/
42
- ) ? `${v}px` : `${v}` : v
43
- );
182
+ ) ? `${v}px` : `${v}`;
183
+ } else if (typeof v === "string") {
184
+ if (hasUnsafeStyleValue(v)) {
185
+ continue;
186
+ }
187
+ value = v;
188
+ } else {
189
+ continue;
190
+ }
191
+ fn(key, value);
44
192
  }
45
193
  };
46
194
  // Annotate the CommonJS export names for ESM import in node:
47
195
  0 && (module.exports = {
196
+ isValidAttributeName,
197
+ isValidTagName,
48
198
  normalizeIntrinsicElementKey,
49
199
  styleObjectForEach
50
200
  });
@@ -22,12 +22,6 @@ __export(body_limit_exports, {
22
22
  module.exports = __toCommonJS(body_limit_exports);
23
23
  var import_http_exception = require("../../http-exception");
24
24
  const ERROR_MESSAGE = "Payload Too Large";
25
- class BodyLimitError extends Error {
26
- constructor(message) {
27
- super(message);
28
- this.name = "BodyLimitError";
29
- }
30
- }
31
25
  const bodyLimit = (options) => {
32
26
  const onError = options.onError || (() => {
33
27
  const res = new Response(ERROR_MESSAGE, {
@@ -42,40 +36,37 @@ const bodyLimit = (options) => {
42
36
  }
43
37
  const hasTransferEncoding = c.req.raw.headers.has("transfer-encoding");
44
38
  const hasContentLength = c.req.raw.headers.has("content-length");
45
- if (hasTransferEncoding && hasContentLength) {
46
- }
47
39
  if (hasContentLength && !hasTransferEncoding) {
48
40
  const contentLength = parseInt(c.req.raw.headers.get("content-length") || "0", 10);
49
41
  return contentLength > maxSize ? onError(c) : next();
50
42
  }
51
43
  let size = 0;
44
+ const chunks = [];
52
45
  const rawReader = c.req.raw.body.getReader();
53
- const reader = new ReadableStream({
54
- async start(controller) {
55
- try {
56
- for (; ; ) {
57
- const { done, value } = await rawReader.read();
58
- if (done) {
59
- break;
60
- }
61
- size += value.length;
62
- if (size > maxSize) {
63
- controller.error(new BodyLimitError(ERROR_MESSAGE));
64
- break;
65
- }
66
- controller.enqueue(value);
46
+ for (; ; ) {
47
+ const { done, value } = await rawReader.read();
48
+ if (done) {
49
+ break;
50
+ }
51
+ size += value.length;
52
+ if (size > maxSize) {
53
+ return onError(c);
54
+ }
55
+ chunks.push(value);
56
+ }
57
+ const requestInit = {
58
+ body: new ReadableStream({
59
+ start(controller) {
60
+ for (const chunk of chunks) {
61
+ controller.enqueue(chunk);
67
62
  }
68
- } finally {
69
63
  controller.close();
70
64
  }
71
- }
72
- });
73
- const requestInit = { body: reader, duplex: "half" };
65
+ }),
66
+ duplex: "half"
67
+ };
74
68
  c.req.raw = new Request(c.req.raw, requestInit);
75
- await next();
76
- if (c.error instanceof BodyLimitError) {
77
- c.res = await onError(c);
78
- }
69
+ return next();
79
70
  };
80
71
  };
81
72
  // Annotate the CommonJS export names for ESM import in node: