- Add debounced state updates for title and content (500ms delay) - Immediate UI updates with delayed history saving - Prevent one-letter-per-undo issue - Add cleanup for debounce timers on unmount
112 lines
3.3 KiB
JavaScript
112 lines
3.3 KiB
JavaScript
// 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 = /* @__PURE__ */ 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 _Node {
|
|
#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]) {
|
|
if (regexpStr === ".*") {
|
|
throw PATH_ERROR;
|
|
}
|
|
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
|
|
};
|