UNPKG

hono

Version:

Web framework built on Web Standards

109 lines (108 loc) 3.3 kB
// src/router/reg-exp-router/node.ts var LABEL_REG_EXP_STR = "[^/]+"; var ONLY_WILDCARD_REG_EXP_STR = ".*"; var TAIL_WILDCARD_REG_EXP_STR = "(?:|/.*)"; var PATH_ERROR = Symbol(); var regExpMetaChars = new Set(".\\+*[^]$()"); function compareKey(a, b) { if (a.length === 1) { return b.length === 1 ? a < b ? -1 : 1 : -1; } if (b.length === 1) { return 1; } if (a === ONLY_WILDCARD_REG_EXP_STR || a === TAIL_WILDCARD_REG_EXP_STR) { return 1; } else if (b === ONLY_WILDCARD_REG_EXP_STR || b === TAIL_WILDCARD_REG_EXP_STR) { return -1; } if (a === LABEL_REG_EXP_STR) { return 1; } else if (b === LABEL_REG_EXP_STR) { return -1; } return a.length === b.length ? a < b ? -1 : 1 : b.length - a.length; } var Node = class { index; varIndex; children = /* @__PURE__ */ Object.create(null); insert(tokens, index, paramMap, context, pathErrorCheckOnly) { if (tokens.length === 0) { if (this.index !== void 0) { throw PATH_ERROR; } if (pathErrorCheckOnly) { return; } this.index = index; return; } const [token, ...restTokens] = tokens; const pattern = token === "*" ? restTokens.length === 0 ? ["", "", ONLY_WILDCARD_REG_EXP_STR] : ["", "", LABEL_REG_EXP_STR] : token === "/*" ? ["", "", TAIL_WILDCARD_REG_EXP_STR] : token.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/); let node; if (pattern) { const name = pattern[1]; let regexpStr = pattern[2] || LABEL_REG_EXP_STR; if (name && pattern[2]) { regexpStr = regexpStr.replace(/^\((?!\?:)(?=[^)]+\)$)/, "(?:"); if (/\((?!\?:)/.test(regexpStr)) { throw PATH_ERROR; } } node = this.children[regexpStr]; if (!node) { if (Object.keys(this.children).some( (k) => k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR )) { throw PATH_ERROR; } if (pathErrorCheckOnly) { return; } node = this.children[regexpStr] = new Node(); if (name !== "") { node.varIndex = context.varIndex++; } } if (!pathErrorCheckOnly && name !== "") { paramMap.push([name, node.varIndex]); } } else { node = this.children[token]; if (!node) { if (Object.keys(this.children).some( (k) => k.length > 1 && k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR )) { throw PATH_ERROR; } if (pathErrorCheckOnly) { return; } node = this.children[token] = new Node(); } } node.insert(restTokens, index, paramMap, context, pathErrorCheckOnly); } buildRegExpStr() { const childKeys = Object.keys(this.children).sort(compareKey); const strList = childKeys.map((k) => { const c = this.children[k]; return (typeof c.varIndex === "number" ? `(${k})@${c.varIndex}` : regExpMetaChars.has(k) ? `\\${k}` : k) + c.buildRegExpStr(); }); if (typeof this.index === "number") { strList.unshift(`#${this.index}`); } if (strList.length === 0) { return ""; } if (strList.length === 1) { return strList[0]; } return "(?:" + strList.join("|") + ")"; } }; export { Node, PATH_ERROR };