UNPKG

hono

Version:

Web framework built on Web Standards

230 lines (229 loc) 6.09 kB
// src/utils/url.ts var splitPath = (path) => { const paths = path.split("/"); if (paths[0] === "") { paths.shift(); } return paths; }; var splitRoutingPath = (routePath) => { const { groups, path } = extractGroupsFromPath(routePath); const paths = splitPath(path); return replaceGroupMarks(paths, groups); }; var extractGroupsFromPath = (path) => { const groups = []; path = path.replace(/\{[^}]+\}/g, (match, index) => { const mark = `@${index}`; groups.push([mark, match]); return mark; }); return { groups, path }; }; var replaceGroupMarks = (paths, groups) => { for (let i = groups.length - 1; i >= 0; i--) { const [mark] = groups[i]; for (let j = paths.length - 1; j >= 0; j--) { if (paths[j].includes(mark)) { paths[j] = paths[j].replace(mark, groups[i][1]); break; } } } return paths; }; var patternCache = {}; var getPattern = (label) => { if (label === "*") { return "*"; } const match = label.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/); if (match) { if (!patternCache[label]) { if (match[2]) { patternCache[label] = [label, match[1], new RegExp("^" + match[2] + "$")]; } else { patternCache[label] = [label, match[1], true]; } } return patternCache[label]; } return null; }; var tryDecodeURI = (str) => { try { return decodeURI(str); } catch { return str.replace(/(?:%[0-9A-Fa-f]{2})+/g, (match) => { try { return decodeURI(match); } catch { return match; } }); } }; var getPath = (request) => { const url = request.url; const start = url.indexOf("/", 8); let i = start; for (; i < url.length; i++) { const charCode = url.charCodeAt(i); if (charCode === 37) { const queryIndex = url.indexOf("?", i); const path = url.slice(start, queryIndex === -1 ? void 0 : queryIndex); return tryDecodeURI(path.includes("%25") ? path.replace(/%25/g, "%2525") : path); } else if (charCode === 63) { break; } } return url.slice(start, i); }; var getQueryStrings = (url) => { const queryIndex = url.indexOf("?", 8); return queryIndex === -1 ? "" : "?" + url.slice(queryIndex + 1); }; var getPathNoStrict = (request) => { const result = getPath(request); return result.length > 1 && result[result.length - 1] === "/" ? result.slice(0, -1) : result; }; var mergePath = (...paths) => { let p = ""; let endsWithSlash = false; for (let path of paths) { if (p[p.length - 1] === "/") { p = p.slice(0, -1); endsWithSlash = true; } if (path[0] !== "/") { path = `/${path}`; } if (path === "/" && endsWithSlash) { p = `${p}/`; } else if (path !== "/") { p = `${p}${path}`; } if (path === "/" && p === "") { p = "/"; } } return p; }; var checkOptionalParameter = (path) => { if (!path.match(/\:.+\?$/)) { return null; } const segments = path.split("/"); const results = []; let basePath = ""; segments.forEach((segment) => { if (segment !== "" && !/\:/.test(segment)) { basePath += "/" + segment; } else if (/\:/.test(segment)) { if (/\?/.test(segment)) { if (results.length === 0 && basePath === "") { results.push("/"); } else { results.push(basePath); } const optionalSegment = segment.replace("?", ""); basePath += "/" + optionalSegment; results.push(basePath); } else { basePath += "/" + segment; } } }); return results.filter((v, i, a) => a.indexOf(v) === i); }; var _decodeURI = (value) => { if (!/[%+]/.test(value)) { return value; } if (value.indexOf("+") !== -1) { value = value.replace(/\+/g, " "); } return /%/.test(value) ? decodeURIComponent_(value) : value; }; var _getQueryParam = (url, key, multiple) => { let encoded; if (!multiple && key && !/[%+]/.test(key)) { let keyIndex2 = url.indexOf(`?${key}`, 8); if (keyIndex2 === -1) { keyIndex2 = url.indexOf(`&${key}`, 8); } while (keyIndex2 !== -1) { const trailingKeyCode = url.charCodeAt(keyIndex2 + key.length + 1); if (trailingKeyCode === 61) { const valueIndex = keyIndex2 + key.length + 2; const endIndex = url.indexOf("&", valueIndex); return _decodeURI(url.slice(valueIndex, endIndex === -1 ? void 0 : endIndex)); } else if (trailingKeyCode == 38 || isNaN(trailingKeyCode)) { return ""; } keyIndex2 = url.indexOf(`&${key}`, keyIndex2 + 1); } encoded = /[%+]/.test(url); if (!encoded) { return void 0; } } const results = {}; encoded ??= /[%+]/.test(url); let keyIndex = url.indexOf("?", 8); while (keyIndex !== -1) { const nextKeyIndex = url.indexOf("&", keyIndex + 1); let valueIndex = url.indexOf("=", keyIndex); if (valueIndex > nextKeyIndex && nextKeyIndex !== -1) { valueIndex = -1; } let name = url.slice( keyIndex + 1, valueIndex === -1 ? nextKeyIndex === -1 ? void 0 : nextKeyIndex : valueIndex ); if (encoded) { name = _decodeURI(name); } keyIndex = nextKeyIndex; if (name === "") { continue; } let value; if (valueIndex === -1) { value = ""; } else { value = url.slice(valueIndex + 1, nextKeyIndex === -1 ? void 0 : nextKeyIndex); if (encoded) { value = _decodeURI(value); } } if (multiple) { if (!(results[name] && Array.isArray(results[name]))) { results[name] = []; } ; results[name].push(value); } else { results[name] ??= value; } } return key ? results[key] : results; }; var getQueryParam = _getQueryParam; var getQueryParams = (url, key) => { return _getQueryParam(url, key, true); }; var decodeURIComponent_ = decodeURIComponent; export { checkOptionalParameter, decodeURIComponent_, getPath, getPathNoStrict, getPattern, getQueryParam, getQueryParams, getQueryStrings, mergePath, splitPath, splitRoutingPath };