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.
- package/dist/adapter/aws-lambda/handler.js +9 -2
- package/dist/cjs/adapter/aws-lambda/handler.js +9 -2
- package/dist/cjs/helper/css/common.js +56 -7
- package/dist/cjs/helper/css/index.js +11 -4
- package/dist/cjs/helper/ssg/ssg.js +12 -8
- package/dist/cjs/helper/ssg/utils.js +9 -0
- package/dist/cjs/jsx/base.js +7 -1
- package/dist/cjs/jsx/dom/css.js +11 -4
- package/dist/cjs/jsx/dom/render.js +39 -17
- package/dist/cjs/jsx/jsx-runtime.js +3 -0
- package/dist/cjs/jsx/utils.js +155 -5
- package/dist/cjs/middleware/body-limit/index.js +21 -30
- package/dist/cjs/middleware/cache/index.js +11 -3
- package/dist/cjs/middleware/compress/index.js +4 -0
- package/dist/cjs/middleware/cors/index.js +2 -5
- package/dist/cjs/middleware/ip-restriction/index.js +31 -9
- package/dist/cjs/middleware/method-override/index.js +1 -1
- package/dist/cjs/middleware/serve-static/index.js +1 -1
- package/dist/cjs/middleware/trailing-slash/index.js +2 -2
- package/dist/cjs/utils/cookie.js +26 -5
- package/dist/cjs/utils/ipaddr.js +10 -4
- package/dist/cjs/utils/jwt/jws.js +1 -1
- package/dist/cjs/utils/jwt/jwt.js +12 -6
- package/dist/helper/css/common.js +56 -7
- package/dist/helper/css/index.js +11 -4
- package/dist/helper/ssg/ssg.js +19 -9
- package/dist/helper/ssg/utils.js +8 -0
- package/dist/jsx/base.js +13 -2
- package/dist/jsx/dom/css.js +11 -4
- package/dist/jsx/dom/render.js +39 -17
- package/dist/jsx/jsx-runtime.js +4 -1
- package/dist/jsx/utils.js +153 -5
- package/dist/middleware/body-limit/index.js +21 -30
- package/dist/middleware/cache/index.js +11 -3
- package/dist/middleware/compress/index.js +4 -0
- package/dist/middleware/cors/index.js +2 -5
- package/dist/middleware/ip-restriction/index.js +34 -10
- package/dist/middleware/method-override/index.js +1 -1
- package/dist/middleware/serve-static/index.js +1 -1
- package/dist/middleware/trailing-slash/index.js +2 -2
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/types/helper/css/common.d.ts +20 -3
- package/dist/types/helper/css/index.d.ts +9 -2
- package/dist/types/helper/ssg/utils.d.ts +1 -0
- package/dist/types/jsx/dom/css.d.ts +8 -2
- package/dist/types/jsx/utils.d.ts +3 -1
- package/dist/types/middleware/cache/index.d.ts +2 -0
- package/dist/types/middleware/cors/index.d.ts +1 -1
- package/dist/types/middleware/ip-restriction/index.d.ts +38 -2
- package/dist/types/middleware/trailing-slash/index.d.ts +16 -0
- package/dist/types/types.d.ts +116 -116
- package/dist/types/utils/ipaddr.d.ts +12 -0
- package/dist/utils/cookie.js +26 -5
- package/dist/utils/ipaddr.js +7 -3
- package/dist/utils/jwt/jws.js +1 -1
- package/dist/utils/jwt/jwt.js +12 -6
- package/package.json +1 -1
|
@@ -22,8 +22,7 @@ __export(cache_exports, {
|
|
|
22
22
|
module.exports = __toCommonJS(cache_exports);
|
|
23
23
|
const defaultCacheableStatusCodes = [200];
|
|
24
24
|
const shouldSkipCache = (res) => {
|
|
25
|
-
|
|
26
|
-
if (vary && vary.includes("*")) {
|
|
25
|
+
if (res.headers.has("Vary")) {
|
|
27
26
|
return true;
|
|
28
27
|
}
|
|
29
28
|
const cacheControl = res.headers.get("Cache-Control");
|
|
@@ -37,7 +36,12 @@ const shouldSkipCache = (res) => {
|
|
|
37
36
|
};
|
|
38
37
|
const cache = (options) => {
|
|
39
38
|
if (!globalThis.caches) {
|
|
40
|
-
|
|
39
|
+
if (options.onCacheNotAvailable === false) {
|
|
40
|
+
} else if (options.onCacheNotAvailable) {
|
|
41
|
+
options.onCacheNotAvailable();
|
|
42
|
+
} else {
|
|
43
|
+
console.log("Cache Middleware is not enabled because caches is not defined.");
|
|
44
|
+
}
|
|
41
45
|
return async (_c, next) => await next();
|
|
42
46
|
}
|
|
43
47
|
if (options.wait === void 0) {
|
|
@@ -79,6 +83,10 @@ const cache = (options) => {
|
|
|
79
83
|
}
|
|
80
84
|
};
|
|
81
85
|
return async function cache2(c, next) {
|
|
86
|
+
if (c.req.method !== "GET" || c.req.raw.headers.has("Authorization")) {
|
|
87
|
+
await next();
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
82
90
|
let key = c.req.url;
|
|
83
91
|
if (options.keyGenerator) {
|
|
84
92
|
key = await options.keyGenerator(c);
|
|
@@ -45,6 +45,10 @@ const compress = (options) => {
|
|
|
45
45
|
ctx.res = new Response(ctx.res.body.pipeThrough(stream), ctx.res);
|
|
46
46
|
ctx.res.headers.delete("Content-Length");
|
|
47
47
|
ctx.res.headers.set("Content-Encoding", encoding);
|
|
48
|
+
const etag = ctx.res.headers.get("ETag");
|
|
49
|
+
if (etag && !etag.startsWith("W/")) {
|
|
50
|
+
ctx.res.headers.set("ETag", `W/${etag}`);
|
|
51
|
+
}
|
|
48
52
|
};
|
|
49
53
|
};
|
|
50
54
|
const shouldCompress = (res) => {
|
|
@@ -21,14 +21,11 @@ __export(cors_exports, {
|
|
|
21
21
|
});
|
|
22
22
|
module.exports = __toCommonJS(cors_exports);
|
|
23
23
|
const cors = (options) => {
|
|
24
|
-
const
|
|
24
|
+
const opts = {
|
|
25
25
|
origin: "*",
|
|
26
26
|
allowMethods: ["GET", "HEAD", "PUT", "POST", "DELETE", "PATCH"],
|
|
27
27
|
allowHeaders: [],
|
|
28
|
-
exposeHeaders: []
|
|
29
|
-
};
|
|
30
|
-
const opts = {
|
|
31
|
-
...defaults,
|
|
28
|
+
exposeHeaders: [],
|
|
32
29
|
...options
|
|
33
30
|
};
|
|
34
31
|
const findAllowOrigin = ((optsOrigin) => {
|
|
@@ -40,12 +40,17 @@ const buildMatcher = (rules) => {
|
|
|
40
40
|
if (type2 === void 0) {
|
|
41
41
|
throw new TypeError(`Invalid rule: ${rule}`);
|
|
42
42
|
}
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
let isIPv4 = type2 === "IPv4";
|
|
44
|
+
let prefix = parseInt(separatedRule[1]);
|
|
45
45
|
if (isIPv4 ? prefix === 32 : prefix === 128) {
|
|
46
46
|
rule = addrStr;
|
|
47
47
|
} else {
|
|
48
|
-
|
|
48
|
+
let addr = (isIPv4 ? import_ipaddr.convertIPv4ToBinary : import_ipaddr.convertIPv6ToBinary)(addrStr);
|
|
49
|
+
if (type2 === "IPv6" && (0, import_ipaddr.isIPv4MappedIPv6)(addr) && prefix >= 96) {
|
|
50
|
+
isIPv4 = true;
|
|
51
|
+
addr = (0, import_ipaddr.convertIPv4MappedIPv6ToIPv4)(addr);
|
|
52
|
+
prefix -= 96;
|
|
53
|
+
}
|
|
49
54
|
const mask = (1n << BigInt(prefix)) - 1n << BigInt((isIPv4 ? 32 : 128) - prefix);
|
|
50
55
|
cidrRules.push([isIPv4, addr & mask, mask]);
|
|
51
56
|
continue;
|
|
@@ -55,21 +60,38 @@ const buildMatcher = (rules) => {
|
|
|
55
60
|
if (type === void 0) {
|
|
56
61
|
throw new TypeError(`Invalid rule: ${rule}`);
|
|
57
62
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
if (type === "IPv4") {
|
|
64
|
+
staticRules.add(rule);
|
|
65
|
+
staticRules.add(`::ffff:${rule}`);
|
|
66
|
+
} else {
|
|
67
|
+
const ipv6binary = (0, import_ipaddr.convertIPv6ToBinary)(rule);
|
|
68
|
+
const ipv6Addr = (0, import_ipaddr.convertIPv6BinaryToString)(ipv6binary);
|
|
69
|
+
staticRules.add(ipv6Addr);
|
|
70
|
+
if ((0, import_ipaddr.isIPv4MappedIPv6)(ipv6binary)) {
|
|
71
|
+
staticRules.add(ipv6Addr.substring(7));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
62
74
|
}
|
|
63
75
|
}
|
|
64
76
|
return (remote) => {
|
|
65
77
|
if (staticRules.has(remote.addr)) {
|
|
66
78
|
return true;
|
|
67
79
|
}
|
|
80
|
+
const remoteAddr = remote.binaryAddr ||= (remote.isIPv4 ? import_ipaddr.convertIPv4ToBinary : import_ipaddr.convertIPv6ToBinary)(remote.addr);
|
|
81
|
+
const remoteIPv4Addr = remote.isIPv4 || (0, import_ipaddr.isIPv4MappedIPv6)(remoteAddr) ? remote.isIPv4 ? remoteAddr : (0, import_ipaddr.convertIPv4MappedIPv6ToIPv4)(remoteAddr) : void 0;
|
|
68
82
|
for (const [isIPv4, addr, mask] of cidrRules) {
|
|
69
|
-
if (isIPv4
|
|
83
|
+
if (isIPv4) {
|
|
84
|
+
if (remoteIPv4Addr === void 0) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if ((remoteIPv4Addr & mask) === addr) {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (remote.isIPv4) {
|
|
70
93
|
continue;
|
|
71
94
|
}
|
|
72
|
-
const remoteAddr = remote.binaryAddr ||= (isIPv4 ? import_ipaddr.convertIPv4ToBinary : import_ipaddr.convertIPv6ToBinary)(remote.addr);
|
|
73
95
|
if ((remoteAddr & mask) === addr) {
|
|
74
96
|
return true;
|
|
75
97
|
}
|
|
@@ -49,7 +49,7 @@ const methodOverride = (options) => async function methodOverride2(c, next) {
|
|
|
49
49
|
return app.fetch(request, c.env, getExecutionCtx(c));
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
|
-
if (contentType
|
|
52
|
+
if (contentType?.startsWith("application/x-www-form-urlencoded")) {
|
|
53
53
|
const params = await (0, import_body.parseBody)(clonedRequest);
|
|
54
54
|
const method = params[methodFormName];
|
|
55
55
|
if (method) {
|
|
@@ -45,7 +45,7 @@ const serveStatic = (options) => {
|
|
|
45
45
|
} else {
|
|
46
46
|
try {
|
|
47
47
|
filename = (0, import_url.tryDecodeURI)(c.req.path);
|
|
48
|
-
if (/(?:^|[\/\\])
|
|
48
|
+
if (/(?:^|[\/\\])\.{1,2}(?:$|[\/\\])|[\/\\]{2,}/.test(filename)) {
|
|
49
49
|
throw new Error();
|
|
50
50
|
}
|
|
51
51
|
} catch {
|
|
@@ -41,14 +41,14 @@ const trimTrailingSlash = (options) => {
|
|
|
41
41
|
const appendTrailingSlash = (options) => {
|
|
42
42
|
return async function appendTrailingSlash2(c, next) {
|
|
43
43
|
if (options?.alwaysRedirect) {
|
|
44
|
-
if ((c.req.method === "GET" || c.req.method === "HEAD") && c.req.path.at(-1) !== "/") {
|
|
44
|
+
if ((c.req.method === "GET" || c.req.method === "HEAD") && c.req.path.at(-1) !== "/" && !options.skip?.(c.req.path)) {
|
|
45
45
|
const url = new URL(c.req.url);
|
|
46
46
|
url.pathname += "/";
|
|
47
47
|
return c.redirect(url.toString(), 301);
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
await next();
|
|
51
|
-
if (!options?.alwaysRedirect && c.res.status === 404 && (c.req.method === "GET" || c.req.method === "HEAD") && c.req.path.at(-1) !== "/") {
|
|
51
|
+
if (!options?.alwaysRedirect && c.res.status === 404 && (c.req.method === "GET" || c.req.method === "HEAD") && c.req.path.at(-1) !== "/" && !options?.skip?.(c.req.path)) {
|
|
52
52
|
const url = new URL(c.req.url);
|
|
53
53
|
url.pathname += "/";
|
|
54
54
|
c.res = c.redirect(url.toString(), 301);
|
package/dist/cjs/utils/cookie.js
CHANGED
|
@@ -48,23 +48,41 @@ const verifySignature = async (base64Signature, value, secret) => {
|
|
|
48
48
|
};
|
|
49
49
|
const validCookieNameRegEx = /^[\w!#$%&'*.^`|~+-]+$/;
|
|
50
50
|
const validCookieValueRegEx = /^[ !#-:<-[\]-~]*$/;
|
|
51
|
+
const trimCookieWhitespace = (value) => {
|
|
52
|
+
let start = 0;
|
|
53
|
+
let end = value.length;
|
|
54
|
+
while (start < end) {
|
|
55
|
+
const charCode = value.charCodeAt(start);
|
|
56
|
+
if (charCode !== 32 && charCode !== 9) {
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
start++;
|
|
60
|
+
}
|
|
61
|
+
while (end > start) {
|
|
62
|
+
const charCode = value.charCodeAt(end - 1);
|
|
63
|
+
if (charCode !== 32 && charCode !== 9) {
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
end--;
|
|
67
|
+
}
|
|
68
|
+
return start === 0 && end === value.length ? value : value.slice(start, end);
|
|
69
|
+
};
|
|
51
70
|
const parse = (cookie, name) => {
|
|
52
71
|
if (name && cookie.indexOf(name) === -1) {
|
|
53
72
|
return {};
|
|
54
73
|
}
|
|
55
|
-
const pairs = cookie.
|
|
74
|
+
const pairs = cookie.split(";");
|
|
56
75
|
const parsedCookie = {};
|
|
57
|
-
for (
|
|
58
|
-
pairStr = pairStr.trim();
|
|
76
|
+
for (const pairStr of pairs) {
|
|
59
77
|
const valueStartPos = pairStr.indexOf("=");
|
|
60
78
|
if (valueStartPos === -1) {
|
|
61
79
|
continue;
|
|
62
80
|
}
|
|
63
|
-
const cookieName = pairStr.substring(0, valueStartPos)
|
|
81
|
+
const cookieName = trimCookieWhitespace(pairStr.substring(0, valueStartPos));
|
|
64
82
|
if (name && name !== cookieName || !validCookieNameRegEx.test(cookieName)) {
|
|
65
83
|
continue;
|
|
66
84
|
}
|
|
67
|
-
let cookieValue = pairStr.substring(valueStartPos + 1)
|
|
85
|
+
let cookieValue = trimCookieWhitespace(pairStr.substring(valueStartPos + 1));
|
|
68
86
|
if (cookieValue.startsWith('"') && cookieValue.endsWith('"')) {
|
|
69
87
|
cookieValue = cookieValue.slice(1, -1);
|
|
70
88
|
}
|
|
@@ -96,6 +114,9 @@ const parseSigned = async (cookie, secret, name) => {
|
|
|
96
114
|
return parsedCookie;
|
|
97
115
|
};
|
|
98
116
|
const _serialize = (name, value, opt = {}) => {
|
|
117
|
+
if (!validCookieNameRegEx.test(name)) {
|
|
118
|
+
throw new Error("Invalid cookie name");
|
|
119
|
+
}
|
|
99
120
|
let cookie = `${name}=${value}`;
|
|
100
121
|
if (name.startsWith("__Secure-") && !opt.secure) {
|
|
101
122
|
throw new Error("__Secure- Cookie must have Secure attributes");
|
package/dist/cjs/utils/ipaddr.js
CHANGED
|
@@ -18,11 +18,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
18
18
|
var ipaddr_exports = {};
|
|
19
19
|
__export(ipaddr_exports, {
|
|
20
20
|
convertIPv4BinaryToString: () => convertIPv4BinaryToString,
|
|
21
|
+
convertIPv4MappedIPv6ToIPv4: () => convertIPv4MappedIPv6ToIPv4,
|
|
21
22
|
convertIPv4ToBinary: () => convertIPv4ToBinary,
|
|
22
23
|
convertIPv6BinaryToString: () => convertIPv6BinaryToString,
|
|
23
24
|
convertIPv6ToBinary: () => convertIPv6ToBinary,
|
|
24
25
|
distinctRemoteAddr: () => distinctRemoteAddr,
|
|
25
|
-
expandIPv6: () => expandIPv6
|
|
26
|
+
expandIPv6: () => expandIPv6,
|
|
27
|
+
isIPv4MappedIPv6: () => isIPv4MappedIPv6
|
|
26
28
|
});
|
|
27
29
|
module.exports = __toCommonJS(ipaddr_exports);
|
|
28
30
|
const expandIPv6 = (ipV6) => {
|
|
@@ -81,9 +83,11 @@ const convertIPv4BinaryToString = (ipV4) => {
|
|
|
81
83
|
}
|
|
82
84
|
return sections.join(".");
|
|
83
85
|
};
|
|
86
|
+
const isIPv4MappedIPv6 = (ipv6binary) => ipv6binary >> 32n === 0xffffn;
|
|
87
|
+
const convertIPv4MappedIPv6ToIPv4 = (ipv6binary) => ipv6binary & 0xffffffffn;
|
|
84
88
|
const convertIPv6BinaryToString = (ipV6) => {
|
|
85
|
-
if (ipV6
|
|
86
|
-
return `::ffff:${convertIPv4BinaryToString(ipV6
|
|
89
|
+
if (isIPv4MappedIPv6(ipV6)) {
|
|
90
|
+
return `::ffff:${convertIPv4BinaryToString(convertIPv4MappedIPv6ToIPv4(ipV6))}`;
|
|
87
91
|
}
|
|
88
92
|
const sections = [];
|
|
89
93
|
for (let i = 0; i < 8; i++) {
|
|
@@ -121,9 +125,11 @@ const convertIPv6BinaryToString = (ipV6) => {
|
|
|
121
125
|
// Annotate the CommonJS export names for ESM import in node:
|
|
122
126
|
0 && (module.exports = {
|
|
123
127
|
convertIPv4BinaryToString,
|
|
128
|
+
convertIPv4MappedIPv6ToIPv4,
|
|
124
129
|
convertIPv4ToBinary,
|
|
125
130
|
convertIPv6BinaryToString,
|
|
126
131
|
convertIPv6ToBinary,
|
|
127
132
|
distinctRemoteAddr,
|
|
128
|
-
expandIPv6
|
|
133
|
+
expandIPv6,
|
|
134
|
+
isIPv4MappedIPv6
|
|
129
135
|
});
|
|
@@ -36,7 +36,7 @@ async function verifying(publicKey, alg, signature, data) {
|
|
|
36
36
|
return await crypto.subtle.verify(algorithm, cryptoKey, signature, data);
|
|
37
37
|
}
|
|
38
38
|
function pemToBinary(pem) {
|
|
39
|
-
return (0, import_encode.decodeBase64)(pem.replace(/-+(BEGIN|END)
|
|
39
|
+
return (0, import_encode.decodeBase64)(pem.replace(/-+(BEGIN|END).*?-+/g, "").replace(/\s/g, ""));
|
|
40
40
|
}
|
|
41
41
|
async function importPrivateKey(key, alg) {
|
|
42
42
|
if (!crypto.subtle || !crypto.subtle.importKey) {
|
|
@@ -81,14 +81,20 @@ const verify = async (token, publicKey, algOrOptions) => {
|
|
|
81
81
|
throw new import_types.JwtAlgorithmMismatch(alg, header.alg);
|
|
82
82
|
}
|
|
83
83
|
const now = Math.floor(Date.now() / 1e3);
|
|
84
|
-
if (nbf && payload.nbf
|
|
85
|
-
|
|
84
|
+
if (nbf && payload.nbf !== void 0) {
|
|
85
|
+
if (typeof payload.nbf !== "number" || !Number.isFinite(payload.nbf) || payload.nbf > now) {
|
|
86
|
+
throw new import_types.JwtTokenNotBefore(token);
|
|
87
|
+
}
|
|
86
88
|
}
|
|
87
|
-
if (exp && payload.exp
|
|
88
|
-
|
|
89
|
+
if (exp && payload.exp !== void 0) {
|
|
90
|
+
if (typeof payload.exp !== "number" || !Number.isFinite(payload.exp) || payload.exp <= now) {
|
|
91
|
+
throw new import_types.JwtTokenExpired(token);
|
|
92
|
+
}
|
|
89
93
|
}
|
|
90
|
-
if (iat && payload.iat
|
|
91
|
-
|
|
94
|
+
if (iat && payload.iat !== void 0) {
|
|
95
|
+
if (typeof payload.iat !== "number" || !Number.isFinite(payload.iat) || now < payload.iat) {
|
|
96
|
+
throw new import_types.JwtTokenIssuedAt(now, payload.iat);
|
|
97
|
+
}
|
|
92
98
|
}
|
|
93
99
|
if (iss) {
|
|
94
100
|
if (!payload.iss) {
|
|
@@ -21,6 +21,23 @@ var toHash = (str) => {
|
|
|
21
21
|
}
|
|
22
22
|
return "css-" + out;
|
|
23
23
|
};
|
|
24
|
+
var normalizeLabel = (label) => {
|
|
25
|
+
return label.trim().replace(/\s+/g, "-");
|
|
26
|
+
};
|
|
27
|
+
var isValidClassName = (name) => /^-?[_a-zA-Z][_a-zA-Z0-9-]*$/.test(name);
|
|
28
|
+
var RESERVED_KEYFRAME_NAMES = /* @__PURE__ */ new Set([
|
|
29
|
+
"default",
|
|
30
|
+
"inherit",
|
|
31
|
+
"initial",
|
|
32
|
+
"none",
|
|
33
|
+
"revert",
|
|
34
|
+
"revert-layer",
|
|
35
|
+
"unset"
|
|
36
|
+
]);
|
|
37
|
+
var isValidKeyframeName = (name) => isValidClassName(name) && !RESERVED_KEYFRAME_NAMES.has(name.toLowerCase());
|
|
38
|
+
var defaultOnInvalidSlug = (slug) => {
|
|
39
|
+
console.warn(`Invalid slug: ${slug}`);
|
|
40
|
+
};
|
|
24
41
|
var cssStringReStr = [
|
|
25
42
|
'"(?:(?:\\\\[\\s\\S]|[^"\\\\])*)"',
|
|
26
43
|
// double quoted string
|
|
@@ -107,13 +124,26 @@ var buildStyleString = (strings, values) => {
|
|
|
107
124
|
}
|
|
108
125
|
return [label, minify(styleString), selectors, externalClassNames];
|
|
109
126
|
};
|
|
110
|
-
var cssCommon = (strings, values) => {
|
|
127
|
+
var cssCommon = (strings, values, classNameSlug, onInvalidSlug) => {
|
|
111
128
|
let [label, thisStyleString, selectors, externalClassNames] = buildStyleString(strings, values);
|
|
112
129
|
const isPseudoGlobal = isPseudoGlobalSelectorRe.exec(thisStyleString);
|
|
113
130
|
if (isPseudoGlobal) {
|
|
114
131
|
thisStyleString = isPseudoGlobal[1];
|
|
115
132
|
}
|
|
116
|
-
const
|
|
133
|
+
const hash = toHash(label + thisStyleString);
|
|
134
|
+
let customSlug;
|
|
135
|
+
if (classNameSlug) {
|
|
136
|
+
const slug = classNameSlug(hash, normalizeLabel(label), thisStyleString);
|
|
137
|
+
if (slug) {
|
|
138
|
+
if (isValidClassName(slug)) {
|
|
139
|
+
customSlug = slug;
|
|
140
|
+
} else {
|
|
141
|
+
;
|
|
142
|
+
(onInvalidSlug || defaultOnInvalidSlug)(slug);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const selector = (isPseudoGlobal ? PSEUDO_GLOBAL_SELECTOR : "") + (customSlug || hash);
|
|
117
147
|
const className = (isPseudoGlobal ? selectors.map((s) => s[CLASS_NAME]) : [selector, ...externalClassNames]).join(" ");
|
|
118
148
|
return {
|
|
119
149
|
[SELECTOR]: selector,
|
|
@@ -138,24 +168,43 @@ var cxCommon = (args) => {
|
|
|
138
168
|
}
|
|
139
169
|
return args;
|
|
140
170
|
};
|
|
141
|
-
var keyframesCommon = (strings,
|
|
171
|
+
var keyframesCommon = (strings, values, classNameSlug, onInvalidSlug) => {
|
|
142
172
|
const [label, styleString] = buildStyleString(strings, values);
|
|
173
|
+
const hash = toHash(label + styleString);
|
|
174
|
+
let customSlug;
|
|
175
|
+
if (classNameSlug) {
|
|
176
|
+
const slug = classNameSlug(hash, normalizeLabel(label), styleString);
|
|
177
|
+
if (slug) {
|
|
178
|
+
if (isValidKeyframeName(slug)) {
|
|
179
|
+
customSlug = slug;
|
|
180
|
+
} else {
|
|
181
|
+
;
|
|
182
|
+
(onInvalidSlug || defaultOnInvalidSlug)(slug);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
143
186
|
return {
|
|
144
187
|
[SELECTOR]: "",
|
|
145
|
-
[CLASS_NAME]: `@keyframes ${
|
|
188
|
+
[CLASS_NAME]: `@keyframes ${customSlug || hash}`,
|
|
146
189
|
[STYLE_STRING]: styleString,
|
|
147
190
|
[SELECTORS]: [],
|
|
148
191
|
[EXTERNAL_CLASS_NAMES]: []
|
|
149
192
|
};
|
|
150
193
|
};
|
|
151
194
|
var viewTransitionNameIndex = 0;
|
|
152
|
-
var viewTransitionCommon = ((strings, values) => {
|
|
195
|
+
var viewTransitionCommon = ((strings, values, classNameSlug, onInvalidSlug) => {
|
|
153
196
|
if (!strings) {
|
|
154
197
|
strings = [`/* h-v-t ${viewTransitionNameIndex++} */`];
|
|
155
198
|
}
|
|
156
|
-
const content = Array.isArray(strings) ? cssCommon(strings, values) : strings;
|
|
199
|
+
const content = Array.isArray(strings) ? cssCommon(strings, values, classNameSlug, onInvalidSlug) : strings;
|
|
157
200
|
const transitionName = content[CLASS_NAME];
|
|
158
|
-
const res = cssCommon(
|
|
201
|
+
const res = cssCommon(
|
|
202
|
+
["view-transition-name:", ""],
|
|
203
|
+
// eslint-disable-line @typescript-eslint/no-explicit-any
|
|
204
|
+
[transitionName],
|
|
205
|
+
classNameSlug,
|
|
206
|
+
onInvalidSlug
|
|
207
|
+
);
|
|
159
208
|
content[CLASS_NAME] = PSEUDO_GLOBAL_SELECTOR + content[CLASS_NAME];
|
|
160
209
|
content[STYLE_STRING] = content[STYLE_STRING].replace(
|
|
161
210
|
/(?<=::view-transition(?:[a-z-]*)\()(?=\))/g,
|
package/dist/helper/css/index.js
CHANGED
|
@@ -15,7 +15,11 @@ import {
|
|
|
15
15
|
viewTransitionCommon
|
|
16
16
|
} from "./common.js";
|
|
17
17
|
import { rawCssString } from "./common.js";
|
|
18
|
-
var createCssContext = ({
|
|
18
|
+
var createCssContext = ({
|
|
19
|
+
id,
|
|
20
|
+
classNameSlug,
|
|
21
|
+
onInvalidSlug
|
|
22
|
+
}) => {
|
|
19
23
|
const [cssJsxDomObject, StyleRenderToDom] = createCssJsxDomObjects({ id });
|
|
20
24
|
const contextMap = /* @__PURE__ */ new WeakMap();
|
|
21
25
|
const nonceMap = /* @__PURE__ */ new WeakMap();
|
|
@@ -78,15 +82,18 @@ var createCssContext = ({ id }) => {
|
|
|
78
82
|
return promise;
|
|
79
83
|
};
|
|
80
84
|
const css2 = (strings, ...values) => {
|
|
81
|
-
return newCssClassNameObject(cssCommon(strings, values));
|
|
85
|
+
return newCssClassNameObject(cssCommon(strings, values, classNameSlug, onInvalidSlug));
|
|
82
86
|
};
|
|
83
87
|
const cx2 = (...args) => {
|
|
84
88
|
args = cxCommon(args);
|
|
85
89
|
return css2(Array(args.length).fill(""), ...args);
|
|
86
90
|
};
|
|
87
|
-
const keyframes2 = keyframesCommon;
|
|
91
|
+
const keyframes2 = (strings, ...values) => keyframesCommon(strings, values, classNameSlug, onInvalidSlug);
|
|
88
92
|
const viewTransition2 = ((strings, ...values) => {
|
|
89
|
-
return newCssClassNameObject(
|
|
93
|
+
return newCssClassNameObject(
|
|
94
|
+
viewTransitionCommon(strings, values, classNameSlug, onInvalidSlug)
|
|
95
|
+
// eslint-disable-line @typescript-eslint/no-explicit-any
|
|
96
|
+
);
|
|
90
97
|
});
|
|
91
98
|
const Style2 = ({ children, nonce } = {}) => raw(
|
|
92
99
|
`<style id="${id}"${nonce ? ` nonce="${nonce}"` : ""}>${children ? children[STYLE_STRING] : ""}</style>`,
|
package/dist/helper/ssg/ssg.js
CHANGED
|
@@ -4,22 +4,30 @@ import { createPool } from "../../utils/concurrent.js";
|
|
|
4
4
|
import { getExtension } from "../../utils/mime.js";
|
|
5
5
|
import { SSG_CONTEXT, X_HONO_DISABLE_SSG_HEADER_KEY } from "./middleware.js";
|
|
6
6
|
import { defaultPlugin } from "./plugins.js";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
dirname,
|
|
9
|
+
ensureWithinOutDir,
|
|
10
|
+
filterStaticGenerateRoutes,
|
|
11
|
+
isDynamicRoute,
|
|
12
|
+
joinPaths
|
|
13
|
+
} from "./utils.js";
|
|
8
14
|
var DEFAULT_CONCURRENCY = 2;
|
|
9
15
|
var DEFAULT_CONTENT_TYPE = "text/plain";
|
|
10
16
|
var DEFAULT_OUTPUT_DIR = "./static";
|
|
11
17
|
var generateFilePath = (routePath, outDir, mimeType, extensionMap) => {
|
|
12
18
|
const extension = determineExtension(mimeType, extensionMap);
|
|
19
|
+
let filePath;
|
|
13
20
|
if (routePath.endsWith(`.${extension}`)) {
|
|
14
|
-
|
|
21
|
+
filePath = joinPaths(outDir, routePath);
|
|
22
|
+
} else if (routePath === "/") {
|
|
23
|
+
filePath = joinPaths(outDir, `index.${extension}`);
|
|
24
|
+
} else if (routePath.endsWith("/")) {
|
|
25
|
+
filePath = joinPaths(outDir, routePath, `index.${extension}`);
|
|
26
|
+
} else {
|
|
27
|
+
filePath = joinPaths(outDir, `${routePath}.${extension}`);
|
|
15
28
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
if (routePath.endsWith("/")) {
|
|
20
|
-
return joinPaths(outDir, routePath, `index.${extension}`);
|
|
21
|
-
}
|
|
22
|
-
return joinPaths(outDir, `${routePath}.${extension}`);
|
|
29
|
+
ensureWithinOutDir(outDir, filePath);
|
|
30
|
+
return filePath;
|
|
23
31
|
};
|
|
24
32
|
var parseResponseContent = async (response) => {
|
|
25
33
|
const contentType = response.headers.get("Content-Type");
|
|
@@ -39,6 +47,8 @@ var defaultExtensionMap = {
|
|
|
39
47
|
"text/html": "html",
|
|
40
48
|
"text/xml": "xml",
|
|
41
49
|
"application/xml": "xml",
|
|
50
|
+
"application/atom+xml": "xml",
|
|
51
|
+
"application/rss+xml": "xml",
|
|
42
52
|
"application/yaml": "yaml"
|
|
43
53
|
};
|
|
44
54
|
var determineExtension = (mimeType, userExtensionMap) => {
|
package/dist/helper/ssg/utils.js
CHANGED
|
@@ -51,8 +51,16 @@ var filterStaticGenerateRoutes = (hono) => {
|
|
|
51
51
|
var isDynamicRoute = (path) => {
|
|
52
52
|
return path.split("/").some((segment) => segment.startsWith(":") || segment.includes("*"));
|
|
53
53
|
};
|
|
54
|
+
var ensureWithinOutDir = (outDir, filePath) => {
|
|
55
|
+
const normalizedOutDir = joinPaths("/", outDir);
|
|
56
|
+
const normalizedFilePath = joinPaths("/", filePath);
|
|
57
|
+
if (normalizedFilePath !== normalizedOutDir && !normalizedFilePath.startsWith(`${normalizedOutDir}/`)) {
|
|
58
|
+
throw new Error(`Path traversal detected: "${filePath}" is outside the output directory`);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
54
61
|
export {
|
|
55
62
|
dirname,
|
|
63
|
+
ensureWithinOutDir,
|
|
56
64
|
filterStaticGenerateRoutes,
|
|
57
65
|
isDynamicRoute,
|
|
58
66
|
joinPaths
|
package/dist/jsx/base.js
CHANGED
|
@@ -5,7 +5,12 @@ import { DOM_RENDERER, DOM_MEMO } from "./constants.js";
|
|
|
5
5
|
import { createContext, globalContexts, useContext } from "./context.js";
|
|
6
6
|
import { domRenderers } from "./intrinsic-element/common.js";
|
|
7
7
|
import * as intrinsicElementTags from "./intrinsic-element/components.js";
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
isValidAttributeName,
|
|
10
|
+
isValidTagName,
|
|
11
|
+
normalizeIntrinsicElementKey,
|
|
12
|
+
styleObjectForEach
|
|
13
|
+
} from "./utils.js";
|
|
9
14
|
var nameSpaceContext = void 0;
|
|
10
15
|
var getNameSpaceContext = () => nameSpaceContext;
|
|
11
16
|
var toSVGAttributeName = (key) => /[A-Z]/.test(key) && // Presentation attributes are findable in style object. "clip-path", "font-size", "stroke-width", etc.
|
|
@@ -85,6 +90,9 @@ var JSXNode = class {
|
|
|
85
90
|
isEscaped = true;
|
|
86
91
|
localContexts;
|
|
87
92
|
constructor(tag, props, children) {
|
|
93
|
+
if (typeof tag !== "function" && !isValidTagName(tag)) {
|
|
94
|
+
throw new Error(`Invalid JSX tag name: ${tag}`);
|
|
95
|
+
}
|
|
88
96
|
this.tag = tag;
|
|
89
97
|
this.props = props;
|
|
90
98
|
this.children = children;
|
|
@@ -116,9 +124,12 @@ var JSXNode = class {
|
|
|
116
124
|
const props = this.props;
|
|
117
125
|
let { children } = this;
|
|
118
126
|
buffer[0] += `<${tag}`;
|
|
119
|
-
const normalizeKey = nameSpaceContext && useContext(nameSpaceContext) === "svg" ? (key) => toSVGAttributeName(normalizeIntrinsicElementKey(key)) : (key) => normalizeIntrinsicElementKey(key);
|
|
127
|
+
const normalizeKey = tag === "svg" || nameSpaceContext && useContext(nameSpaceContext) === "svg" ? (key) => toSVGAttributeName(normalizeIntrinsicElementKey(key)) : (key) => normalizeIntrinsicElementKey(key);
|
|
120
128
|
for (let [key, v] of Object.entries(props)) {
|
|
121
129
|
key = normalizeKey(key);
|
|
130
|
+
if (!isValidAttributeName(key)) {
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
122
133
|
if (key === "children") {
|
|
123
134
|
} else if (key === "style" && typeof v === "object") {
|
|
124
135
|
let styleStr = "";
|
package/dist/jsx/dom/css.js
CHANGED
|
@@ -100,22 +100,29 @@ var createCssJsxDomObjects = ({ id }) => {
|
|
|
100
100
|
});
|
|
101
101
|
return [cssObject, Style2];
|
|
102
102
|
};
|
|
103
|
-
var createCssContext = ({
|
|
103
|
+
var createCssContext = ({
|
|
104
|
+
id,
|
|
105
|
+
classNameSlug,
|
|
106
|
+
onInvalidSlug
|
|
107
|
+
}) => {
|
|
104
108
|
const [cssObject, Style2] = createCssJsxDomObjects({ id });
|
|
105
109
|
const newCssClassNameObject = (cssClassName) => {
|
|
106
110
|
cssClassName.toString = cssObject.toString;
|
|
107
111
|
return cssClassName;
|
|
108
112
|
};
|
|
109
113
|
const css2 = (strings, ...values) => {
|
|
110
|
-
return newCssClassNameObject(cssCommon(strings, values));
|
|
114
|
+
return newCssClassNameObject(cssCommon(strings, values, classNameSlug, onInvalidSlug));
|
|
111
115
|
};
|
|
112
116
|
const cx2 = (...args) => {
|
|
113
117
|
args = cxCommon(args);
|
|
114
118
|
return css2(Array(args.length).fill(""), ...args);
|
|
115
119
|
};
|
|
116
|
-
const keyframes2 = keyframesCommon;
|
|
120
|
+
const keyframes2 = (strings, ...values) => keyframesCommon(strings, values, classNameSlug, onInvalidSlug);
|
|
117
121
|
const viewTransition2 = ((strings, ...values) => {
|
|
118
|
-
return newCssClassNameObject(
|
|
122
|
+
return newCssClassNameObject(
|
|
123
|
+
viewTransitionCommon(strings, values, classNameSlug, onInvalidSlug)
|
|
124
|
+
// eslint-disable-line @typescript-eslint/no-explicit-any
|
|
125
|
+
);
|
|
119
126
|
});
|
|
120
127
|
return {
|
|
121
128
|
css: css2,
|