UNPKG

react-xml-viewer

Version:
1,428 lines 68.8 kB
import { jsx as f, jsxs as w, Fragment as se } from "react/jsx-runtime"; import * as J from "react"; import { useRef as $, useEffect as x, useCallback as L, createContext as ie, useState as _, useMemo as k, useContext as oe, memo as Se } from "react"; const Q = ":@", R = "#text", K = "#comment", Z = "#cdata", ae = "DECLARATION_TAG", xe = "TAG", F = { tagColor: "#d43900", textColor: "#333", attributeKeyColor: "#2a7ab0", attributeValueColor: "#008000", separatorColor: "#333", commentColor: "#aaa", cdataColor: "#1d781d", fontFamily: "monospace", lineNumberBackground: "#eee", lineNumberColor: "#222" }; function le(n, e) { const t = $(n), r = $(); return x(() => { t.current = n; }, [n]), x(() => () => { r.current && clearTimeout(r.current); }, []), L( (...i) => { r.current && clearTimeout(r.current), r.current = setTimeout(() => { t.current(...i); }, e); }, [e] ); } const Ae = { lines: {}, push: () => { } }, ue = ie(Ae), Pe = ({ children: n, enabled: e = !1 }) => { const [t, r] = _({}), i = $({}), s = L(() => { r(i.current); }, []), l = le(s, 100), a = L((c, u) => { var h; e && (((h = i.current[c]) == null ? void 0 : h.element) !== u.element && (i.current[c] = u), l()); }, []), o = k(() => ({ lines: t, push: a }), [t, a, e]); return /* @__PURE__ */ f(ue.Provider, { value: o, children: n }); }, ce = () => oe(ue), Oe = { theme: F, collapsible: !1, indentSize: 2 }, he = ie(Oe), T = () => oe(he); function $e(n, e) { return new Array(e * n + 1).join(" "); } function fe(n) { return typeof n == "string" && n.includes(` `); } function _e(n) { return typeof n == "string" ? !1 : n.length === 1 && R in n[0] && !fe(n[0][R]); } function ke(n) { switch (n) { case R: case Z: case K: return n; default: return n.startsWith("?") ? ae : xe; } } function Me(n, e) { const t = {}; for (const r in n) r !== e && (t[r] = n[r]); return t; } function Ve(n) { const e = n[Q], t = Me(n, Q), [[r, i]] = Object.entries(t), s = ke(r); return { attributes: e, tagKey: r, subElements: i, type: s }; } function Le(n, e) { return Object.keys(F).every((r) => n[r] === e[r]); } const de = ":A-Za-z_\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD", Re = de + "\\-.\\d\\u00B7\\u0300-\\u036F\\u203F-\\u2040", Fe = "[" + de + "][" + Re + "]*", je = new RegExp("^" + Fe + "$"); function pe(n, e) { const t = []; let r = e.exec(n); for (; r; ) { const i = []; i.startIndex = e.lastIndex - r[0].length; const s = r.length; for (let l = 0; l < s; l++) i.push(r[l]); t.push(i), r = e.exec(n); } return t; } const U = function(n) { const e = je.exec(n); return !(e === null || typeof e > "u"); }; function Ue(n) { return typeof n < "u"; } const q = [ // '__proto__', // 'constructor', // 'prototype', "hasOwnProperty", "toString", "valueOf", "__defineGetter__", "__defineSetter__", "__lookupGetter__", "__lookupSetter__" ], ge = ["__proto__", "constructor", "prototype"], Be = { allowBooleanAttributes: !1, //A tag can have attributes without any value unpairedTags: [] }; function be(n, e) { e = Object.assign({}, Be, e); const t = []; let r = !1, i = !1; n[0] === "\uFEFF" && (n = n.substr(1)); for (let s = 0; s < n.length; s++) if (n[s] === "<" && n[s + 1] === "?") { if (s += 2, s = D(n, s), s.err) return s; } else if (n[s] === "<") { let l = s; if (s++, n[s] === "!") { s = ee(n, s); continue; } else { let a = !1; n[s] === "/" && (a = !0, s++); let o = ""; for (; s < n.length && n[s] !== ">" && n[s] !== " " && n[s] !== " " && n[s] !== ` ` && n[s] !== "\r"; s++) o += n[s]; if (o = o.trim(), o[o.length - 1] === "/" && (o = o.substring(0, o.length - 1), s--), !qe(o)) { let h; return o.trim().length === 0 ? h = "Invalid space after '<'." : h = "Tag '" + o + "' is an invalid name.", b("InvalidTag", h, m(n, s)); } const c = Ye(n, s); if (c === !1) return b("InvalidAttr", "Attributes for '" + o + "' have open quote.", m(n, s)); let u = c.value; if (s = c.index, u[u.length - 1] === "/") { const h = s - u.length; u = u.substring(0, u.length - 1); const d = te(u, e); if (d === !0) r = !0; else return b(d.err.code, d.err.msg, m(n, h + d.err.line)); } else if (a) if (c.tagClosed) { if (u.trim().length > 0) return b("InvalidTag", "Closing tag '" + o + "' can't have attributes or invalid starting.", m(n, l)); if (t.length === 0) return b("InvalidTag", "Closing tag '" + o + "' has not been opened.", m(n, l)); { const h = t.pop(); if (o !== h.tagName) { let d = m(n, h.tagStartPos); return b( "InvalidTag", "Expected closing tag '" + h.tagName + "' (opened in line " + d.line + ", col " + d.col + ") instead of closing tag '" + o + "'.", m(n, l) ); } t.length == 0 && (i = !0); } } else return b("InvalidTag", "Closing tag '" + o + "' doesn't have proper closing.", m(n, s)); else { const h = te(u, e); if (h !== !0) return b(h.err.code, h.err.msg, m(n, s - u.length + h.err.line)); if (i === !0) return b("InvalidXml", "Multiple possible root nodes found.", m(n, s)); e.unpairedTags.indexOf(o) !== -1 || t.push({ tagName: o, tagStartPos: l }), r = !0; } for (s++; s < n.length; s++) if (n[s] === "<") if (n[s + 1] === "!") { s++, s = ee(n, s); continue; } else if (n[s + 1] === "?") { if (s = D(n, ++s), s.err) return s; } else break; else if (n[s] === "&") { const h = Ke(n, s); if (h == -1) return b("InvalidChar", "char '&' is not expected.", m(n, s)); s = h; } else if (i === !0 && !H(n[s])) return b("InvalidXml", "Extra text at the end", m(n, s)); n[s] === "<" && s--; } } else { if (H(n[s])) continue; return b("InvalidChar", "char '" + n[s] + "' is not expected.", m(n, s)); } if (r) { if (t.length == 1) return b("InvalidTag", "Unclosed tag '" + t[0].tagName + "'.", m(n, t[0].tagStartPos)); if (t.length > 0) return b("InvalidXml", "Invalid '" + JSON.stringify(t.map((s) => s.tagName), null, 4).replace(/\r?\n/g, "") + "' found.", { line: 1, col: 1 }); } else return b("InvalidXml", "Start tag expected.", 1); return !0; } function H(n) { return n === " " || n === " " || n === ` ` || n === "\r"; } function D(n, e) { const t = e; for (; e < n.length; e++) if (n[e] == "?" || n[e] == " ") { const r = n.substr(t, e - t); if (e > 5 && r === "xml") return b("InvalidXml", "XML declaration allowed only at the start of the document.", m(n, e)); if (n[e] == "?" && n[e + 1] == ">") { e++; break; } else continue; } return e; } function ee(n, e) { if (n.length > e + 5 && n[e + 1] === "-" && n[e + 2] === "-") { for (e += 3; e < n.length; e++) if (n[e] === "-" && n[e + 1] === "-" && n[e + 2] === ">") { e += 2; break; } } else if (n.length > e + 8 && n[e + 1] === "D" && n[e + 2] === "O" && n[e + 3] === "C" && n[e + 4] === "T" && n[e + 5] === "Y" && n[e + 6] === "P" && n[e + 7] === "E") { let t = 1; for (e += 8; e < n.length; e++) if (n[e] === "<") t++; else if (n[e] === ">" && (t--, t === 0)) break; } else if (n.length > e + 9 && n[e + 1] === "[" && n[e + 2] === "C" && n[e + 3] === "D" && n[e + 4] === "A" && n[e + 5] === "T" && n[e + 6] === "A" && n[e + 7] === "[") { for (e += 8; e < n.length; e++) if (n[e] === "]" && n[e + 1] === "]" && n[e + 2] === ">") { e += 2; break; } } return e; } const Xe = '"', ze = "'"; function Ye(n, e) { let t = "", r = "", i = !1; for (; e < n.length; e++) { if (n[e] === Xe || n[e] === ze) r === "" ? r = n[e] : r !== n[e] || (r = ""); else if (n[e] === ">" && r === "") { i = !0; break; } t += n[e]; } return r !== "" ? !1 : { value: t, index: e, tagClosed: i }; } const We = new RegExp(`(\\s*)([^\\s=]+)(\\s*=)?(\\s*(['"])(([\\s\\S])*?)\\5)?`, "g"); function te(n, e) { const t = pe(n, We), r = {}; for (let i = 0; i < t.length; i++) { if (t[i][1].length === 0) return b("InvalidAttr", "Attribute '" + t[i][2] + "' has no space in starting.", P(t[i])); if (t[i][3] !== void 0 && t[i][4] === void 0) return b("InvalidAttr", "Attribute '" + t[i][2] + "' is without value.", P(t[i])); if (t[i][3] === void 0 && !e.allowBooleanAttributes) return b("InvalidAttr", "boolean attribute '" + t[i][2] + "' is not allowed.", P(t[i])); const s = t[i][2]; if (!Ze(s)) return b("InvalidAttr", "Attribute '" + s + "' is an invalid name.", P(t[i])); if (!Object.prototype.hasOwnProperty.call(r, s)) r[s] = 1; else return b("InvalidAttr", "Attribute '" + s + "' is repeated.", P(t[i])); } return !0; } function Ge(n, e) { let t = /\d/; for (n[e] === "x" && (e++, t = /[\da-fA-F]/); e < n.length; e++) { if (n[e] === ";") return e; if (!n[e].match(t)) break; } return -1; } function Ke(n, e) { if (e++, n[e] === ";") return -1; if (n[e] === "#") return e++, Ge(n, e); let t = 0; for (; e < n.length; e++, t++) if (!(n[e].match(/\w/) && t < 20)) { if (n[e] === ";") break; return -1; } return e; } function b(n, e, t) { return { err: { code: n, msg: e, line: t.line || t, col: t.col } }; } function Ze(n) { return U(n); } function qe(n) { return U(n); } function m(n, e) { const t = n.substring(0, e).split(/\r?\n/); return { line: t.length, // column number is last line's length + 1, because column numbering starts at 1: col: t[t.length - 1].length + 1 }; } function P(n) { return n.startIndex + n[1].length; } const Ee = (n) => q.includes(n) ? "__" + n : n, Je = { preserveOrder: !1, attributeNamePrefix: "@_", attributesGroupName: !1, textNodeName: "#text", ignoreAttributes: !0, removeNSPrefix: !1, // remove NS from tag name or attribute name if true allowBooleanAttributes: !1, //a tag can have attributes without any value //ignoreRootElement : false, parseTagValue: !0, parseAttributeValue: !1, trimValues: !0, //Trim string values of tag and attributes cdataPropName: !1, numberParseOptions: { hex: !0, leadingZeros: !0, eNotation: !0 }, tagValueProcessor: function(n, e) { return e; }, attributeValueProcessor: function(n, e) { return e; }, stopNodes: [], //nested tags will not be parsed even for errors alwaysCreateTextNode: !1, isArray: () => !1, commentPropName: !1, unpairedTags: [], processEntities: !0, htmlEntities: !1, ignoreDeclaration: !1, ignorePiTags: !1, transformTagName: !1, transformAttributeName: !1, updateTag: function(n, e, t) { return n; }, // skipEmptyListItem: false captureMetaData: !1, maxNestedTags: 100, strictReservedNames: !0, jPath: !0, // if true, pass jPath string to callbacks; if false, pass matcher instance onDangerousProperty: Ee }; function Qe(n, e) { if (typeof n != "string") return; const t = n.toLowerCase(); if (q.some((r) => t === r.toLowerCase())) throw new Error( `[SECURITY] Invalid ${e}: "${n}" is a reserved JavaScript keyword that could cause prototype pollution` ); if (ge.some((r) => t === r.toLowerCase())) throw new Error( `[SECURITY] Invalid ${e}: "${n}" is a reserved JavaScript keyword that could cause prototype pollution` ); } function me(n) { return typeof n == "boolean" ? { enabled: n, // true or false maxEntitySize: 1e4, maxExpansionDepth: 10, maxTotalExpansions: 1e3, maxExpandedLength: 1e5, maxEntityCount: 100, allowedTags: null, tagFilter: null } : typeof n == "object" && n !== null ? { enabled: n.enabled !== !1, maxEntitySize: Math.max(1, n.maxEntitySize ?? 1e4), maxExpansionDepth: Math.max(1, n.maxExpansionDepth ?? 10), maxTotalExpansions: Math.max(1, n.maxTotalExpansions ?? 1e3), maxExpandedLength: Math.max(1, n.maxExpandedLength ?? 1e5), maxEntityCount: Math.max(1, n.maxEntityCount ?? 100), allowedTags: n.allowedTags ?? null, tagFilter: n.tagFilter ?? null } : me(!0); } const He = function(n) { const e = Object.assign({}, Je, n), t = [ { value: e.attributeNamePrefix, name: "attributeNamePrefix" }, { value: e.attributesGroupName, name: "attributesGroupName" }, { value: e.textNodeName, name: "textNodeName" }, { value: e.cdataPropName, name: "cdataPropName" }, { value: e.commentPropName, name: "commentPropName" } ]; for (const { value: r, name: i } of t) r && Qe(r, i); return e.onDangerousProperty === null && (e.onDangerousProperty = Ee), e.processEntities = me(e.processEntities), e.stopNodes && Array.isArray(e.stopNodes) && (e.stopNodes = e.stopNodes.map((r) => typeof r == "string" && r.startsWith("*.") ? ".." + r.substring(2) : r)), e; }; let j; typeof Symbol != "function" ? j = "@@xmlMetadata" : j = Symbol("XML Node Metadata"); class C { constructor(e) { this.tagname = e, this.child = [], this[":@"] = /* @__PURE__ */ Object.create(null); } add(e, t) { e === "__proto__" && (e = "#__proto__"), this.child.push({ [e]: t }); } addChild(e, t) { e.tagname === "__proto__" && (e.tagname = "#__proto__"), e[":@"] && Object.keys(e[":@"]).length > 0 ? this.child.push({ [e.tagname]: e.child, ":@": e[":@"] }) : this.child.push({ [e.tagname]: e.child }), t !== void 0 && (this.child[this.child.length - 1][j] = { startIndex: t }); } /** symbol used for metadata */ static getMetaDataSymbol() { return j; } } class De { constructor(e) { this.suppressValidationErr = !e, this.options = e; } readDocType(e, t) { const r = /* @__PURE__ */ Object.create(null); let i = 0; if (e[t + 3] === "O" && e[t + 4] === "C" && e[t + 5] === "T" && e[t + 6] === "Y" && e[t + 7] === "P" && e[t + 8] === "E") { t = t + 9; let s = 1, l = !1, a = !1, o = ""; for (; t < e.length; t++) if (e[t] === "<" && !a) { if (l && v(e, "!ENTITY", t)) { t += 7; let c, u; if ([c, u, t] = this.readEntityExp(e, t + 1, this.suppressValidationErr), u.indexOf("&") === -1) { if (this.options.enabled !== !1 && this.options.maxEntityCount != null && i >= this.options.maxEntityCount) throw new Error( `Entity count (${i + 1}) exceeds maximum allowed (${this.options.maxEntityCount})` ); const h = c.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); r[c] = { regx: RegExp(`&${h};`, "g"), val: u }, i++; } } else if (l && v(e, "!ELEMENT", t)) { t += 8; const { index: c } = this.readElementExp(e, t + 1); t = c; } else if (l && v(e, "!ATTLIST", t)) t += 8; else if (l && v(e, "!NOTATION", t)) { t += 9; const { index: c } = this.readNotationExp(e, t + 1, this.suppressValidationErr); t = c; } else if (v(e, "!--", t)) a = !0; else throw new Error("Invalid DOCTYPE"); s++, o = ""; } else if (e[t] === ">") { if (a ? e[t - 1] === "-" && e[t - 2] === "-" && (a = !1, s--) : s--, s === 0) break; } else e[t] === "[" ? l = !0 : o += e[t]; if (s !== 0) throw new Error("Unclosed DOCTYPE"); } else throw new Error("Invalid Tag instead of DOCTYPE"); return { entities: r, i: t }; } readEntityExp(e, t) { t = N(e, t); const r = t; for (; t < e.length && !/\s/.test(e[t]) && e[t] !== '"' && e[t] !== "'"; ) t++; let i = e.substring(r, t); if (O(i), t = N(e, t), !this.suppressValidationErr) { if (e.substring(t, t + 6).toUpperCase() === "SYSTEM") throw new Error("External entities are not supported"); if (e[t] === "%") throw new Error("Parameter entities are not supported"); } let s = ""; if ([t, s] = this.readIdentifierVal(e, t, "entity"), this.options.enabled !== !1 && this.options.maxEntitySize != null && s.length > this.options.maxEntitySize) throw new Error( `Entity "${i}" size (${s.length}) exceeds maximum allowed size (${this.options.maxEntitySize})` ); return t--, [i, s, t]; } readNotationExp(e, t) { t = N(e, t); const r = t; for (; t < e.length && !/\s/.test(e[t]); ) t++; let i = e.substring(r, t); !this.suppressValidationErr && O(i), t = N(e, t); const s = e.substring(t, t + 6).toUpperCase(); if (!this.suppressValidationErr && s !== "SYSTEM" && s !== "PUBLIC") throw new Error(`Expected SYSTEM or PUBLIC, found "${s}"`); t += s.length, t = N(e, t); let l = null, a = null; if (s === "PUBLIC") [t, l] = this.readIdentifierVal(e, t, "publicIdentifier"), t = N(e, t), (e[t] === '"' || e[t] === "'") && ([t, a] = this.readIdentifierVal(e, t, "systemIdentifier")); else if (s === "SYSTEM" && ([t, a] = this.readIdentifierVal(e, t, "systemIdentifier"), !this.suppressValidationErr && !a)) throw new Error("Missing mandatory system identifier for SYSTEM notation"); return { notationName: i, publicIdentifier: l, systemIdentifier: a, index: --t }; } readIdentifierVal(e, t, r) { let i = ""; const s = e[t]; if (s !== '"' && s !== "'") throw new Error(`Expected quoted string, found "${s}"`); t++; const l = t; for (; t < e.length && e[t] !== s; ) t++; if (i = e.substring(l, t), e[t] !== s) throw new Error(`Unterminated ${r} value`); return t++, [t, i]; } readElementExp(e, t) { t = N(e, t); const r = t; for (; t < e.length && !/\s/.test(e[t]); ) t++; let i = e.substring(r, t); if (!this.suppressValidationErr && !U(i)) throw new Error(`Invalid element name: "${i}"`); t = N(e, t); let s = ""; if (e[t] === "E" && v(e, "MPTY", t)) t += 4; else if (e[t] === "A" && v(e, "NY", t)) t += 2; else if (e[t] === "(") { t++; const l = t; for (; t < e.length && e[t] !== ")"; ) t++; if (s = e.substring(l, t), e[t] !== ")") throw new Error("Unterminated content model"); } else if (!this.suppressValidationErr) throw new Error(`Invalid Element Expression, found "${e[t]}"`); return { elementName: i, contentModel: s.trim(), index: t }; } readAttlistExp(e, t) { t = N(e, t); let r = t; for (; t < e.length && !/\s/.test(e[t]); ) t++; let i = e.substring(r, t); for (O(i), t = N(e, t), r = t; t < e.length && !/\s/.test(e[t]); ) t++; let s = e.substring(r, t); if (!O(s)) throw new Error(`Invalid attribute name: "${s}"`); t = N(e, t); let l = ""; if (e.substring(t, t + 8).toUpperCase() === "NOTATION") { if (l = "NOTATION", t += 8, t = N(e, t), e[t] !== "(") throw new Error(`Expected '(', found "${e[t]}"`); t++; let o = []; for (; t < e.length && e[t] !== ")"; ) { const c = t; for (; t < e.length && e[t] !== "|" && e[t] !== ")"; ) t++; let u = e.substring(c, t); if (u = u.trim(), !O(u)) throw new Error(`Invalid notation name: "${u}"`); o.push(u), e[t] === "|" && (t++, t = N(e, t)); } if (e[t] !== ")") throw new Error("Unterminated list of notations"); t++, l += " (" + o.join("|") + ")"; } else { const o = t; for (; t < e.length && !/\s/.test(e[t]); ) t++; l += e.substring(o, t); const c = ["CDATA", "ID", "IDREF", "IDREFS", "ENTITY", "ENTITIES", "NMTOKEN", "NMTOKENS"]; if (!this.suppressValidationErr && !c.includes(l.toUpperCase())) throw new Error(`Invalid attribute type: "${l}"`); } t = N(e, t); let a = ""; return e.substring(t, t + 8).toUpperCase() === "#REQUIRED" ? (a = "#REQUIRED", t += 8) : e.substring(t, t + 7).toUpperCase() === "#IMPLIED" ? (a = "#IMPLIED", t += 7) : [t, a] = this.readIdentifierVal(e, t, "ATTLIST"), { elementName: i, attributeName: s, attributeType: l, defaultValue: a, index: t }; } } const N = (n, e) => { for (; e < n.length && /\s/.test(n[e]); ) e++; return e; }; function v(n, e, t) { for (let r = 0; r < e.length; r++) if (e[r] !== n[t + r + 1]) return !1; return !0; } function O(n) { if (U(n)) return n; throw new Error(`Invalid entity name ${n}`); } const et = /^[-+]?0x[a-fA-F0-9]+$/, tt = /^([\-\+])?(0*)([0-9]*(\.[0-9]*)?)$/, nt = { hex: !0, // oct: false, leadingZeros: !0, decimalPoint: ".", eNotation: !0, //skipLike: /regex/, infinity: "original" // "null", "infinity" (Infinity type), "string" ("Infinity" (the string literal)) }; function rt(n, e = {}) { if (e = Object.assign({}, nt, e), !n || typeof n != "string") return n; let t = n.trim(); if (t.length === 0) return n; if (e.skipLike !== void 0 && e.skipLike.test(t)) return n; if (t === "0") return 0; if (e.hex && et.test(t)) return at(t, 16); if (isFinite(t)) { if (t.includes("e") || t.includes("E")) return it(n, t, e); { const r = tt.exec(t); if (r) { const i = r[1] || "", s = r[2]; let l = ot(r[3]); const a = i ? ( // 0., -00., 000. n[s.length + 1] === "." ) : n[s.length] === "."; if (!e.leadingZeros && (s.length > 1 || s.length === 1 && !a)) return n; { const o = Number(t), c = String(o); if (o === 0) return o; if (c.search(/[eE]/) !== -1) return e.eNotation ? o : n; if (t.indexOf(".") !== -1) return c === "0" || c === l || c === `${i}${l}` ? o : n; let u = s ? l : t; return s ? u === c || i + u === c ? o : n : u === c || u === i + c ? o : n; } } else return n; } } else return lt(n, Number(t), e); } const st = /^([-+])?(0*)(\d*(\.\d*)?[eE][-\+]?\d+)$/; function it(n, e, t) { if (!t.eNotation) return n; const r = e.match(st); if (r) { let i = r[1] || ""; const s = r[3].indexOf("e") === -1 ? "E" : "e", l = r[2], a = i ? ( // 0E. n[l.length + 1] === s ) : n[l.length] === s; return l.length > 1 && a ? n : l.length === 1 && (r[3].startsWith(`.${s}`) || r[3][0] === s) ? Number(e) : l.length > 0 ? t.leadingZeros && !a ? (e = (r[1] || "") + r[3], Number(e)) : n : Number(e); } else return n; } function ot(n) { return n && n.indexOf(".") !== -1 && (n = n.replace(/0+$/, ""), n === "." ? n = "0" : n[0] === "." ? n = "0" + n : n[n.length - 1] === "." && (n = n.substring(0, n.length - 1))), n; } function at(n, e) { if (parseInt) return parseInt(n, e); if (Number.parseInt) return Number.parseInt(n, e); if (window && window.parseInt) return window.parseInt(n, e); throw new Error("parseInt, Number.parseInt, window.parseInt are not supported"); } function lt(n, e, t) { const r = e === 1 / 0; switch (t.infinity.toLowerCase()) { case "null": return null; case "infinity": return e; case "string": return r ? "Infinity" : "-Infinity"; case "original": default: return n; } } function ut(n) { return typeof n == "function" ? n : Array.isArray(n) ? (e) => { for (const t of n) if (typeof t == "string" && e === t || t instanceof RegExp && t.test(e)) return !0; } : () => !1; } class ne { /** * Create a new Expression * @param {string} pattern - Pattern string (e.g., "root.users.user", "..user[id]") * @param {Object} options - Configuration options * @param {string} options.separator - Path separator (default: '.') */ constructor(e, t = {}) { this.pattern = e, this.separator = t.separator || ".", this.segments = this._parse(e), this._hasDeepWildcard = this.segments.some((r) => r.type === "deep-wildcard"), this._hasAttributeCondition = this.segments.some((r) => r.attrName !== void 0), this._hasPositionSelector = this.segments.some((r) => r.position !== void 0); } /** * Parse pattern string into segments * @private * @param {string} pattern - Pattern to parse * @returns {Array} Array of segment objects */ _parse(e) { const t = []; let r = 0, i = ""; for (; r < e.length; ) e[r] === this.separator ? r + 1 < e.length && e[r + 1] === this.separator ? (i.trim() && (t.push(this._parseSegment(i.trim())), i = ""), t.push({ type: "deep-wildcard" }), r += 2) : (i.trim() && t.push(this._parseSegment(i.trim())), i = "", r++) : (i += e[r], r++); return i.trim() && t.push(this._parseSegment(i.trim())), t; } /** * Parse a single segment * @private * @param {string} part - Segment string (e.g., "user", "ns::user", "user[id]", "ns::user:first") * @returns {Object} Segment object */ _parseSegment(e) { const t = { type: "tag" }; let r = null, i = e; const s = e.match(/^([^\[]+)(\[[^\]]*\])(.*)$/); if (s && (i = s[1] + s[3], s[2])) { const u = s[2].slice(1, -1); u && (r = u); } let l, a = i; if (i.includes("::")) { const u = i.indexOf("::"); if (l = i.substring(0, u).trim(), a = i.substring(u + 2).trim(), !l) throw new Error(`Invalid namespace in pattern: ${e}`); } let o, c = null; if (a.includes(":")) { const u = a.lastIndexOf(":"), h = a.substring(0, u).trim(), d = a.substring(u + 1).trim(); ["first", "last", "odd", "even"].includes(d) || /^nth\(\d+\)$/.test(d) ? (o = h, c = d) : o = a; } else o = a; if (!o) throw new Error(`Invalid segment pattern: ${e}`); if (t.tag = o, l && (t.namespace = l), r) if (r.includes("=")) { const u = r.indexOf("="); t.attrName = r.substring(0, u).trim(), t.attrValue = r.substring(u + 1).trim(); } else t.attrName = r.trim(); if (c) { const u = c.match(/^nth\((\d+)\)$/); u ? (t.position = "nth", t.positionValue = parseInt(u[1], 10)) : t.position = c; } return t; } /** * Get the number of segments * @returns {number} */ get length() { return this.segments.length; } /** * Check if expression contains deep wildcard * @returns {boolean} */ hasDeepWildcard() { return this._hasDeepWildcard; } /** * Check if expression has attribute conditions * @returns {boolean} */ hasAttributeCondition() { return this._hasAttributeCondition; } /** * Check if expression has position selectors * @returns {boolean} */ hasPositionSelector() { return this._hasPositionSelector; } /** * Get string representation * @returns {string} */ toString() { return this.pattern; } } const ct = /* @__PURE__ */ new Set(["push", "pop", "reset", "updateCurrent", "restore"]); class ht { /** * Create a new Matcher * @param {Object} options - Configuration options * @param {string} options.separator - Default path separator (default: '.') */ constructor(e = {}) { this.separator = e.separator || ".", this.path = [], this.siblingStacks = []; } /** * Push a new tag onto the path * @param {string} tagName - Name of the tag * @param {Object} attrValues - Attribute key-value pairs for current node (optional) * @param {string} namespace - Namespace for the tag (optional) */ push(e, t = null, r = null) { if (this.path.length > 0) { const u = this.path[this.path.length - 1]; u.values = void 0; } const i = this.path.length; this.siblingStacks[i] || (this.siblingStacks[i] = /* @__PURE__ */ new Map()); const s = this.siblingStacks[i], l = r ? `${r}:${e}` : e, a = s.get(l) || 0; let o = 0; for (const u of s.values()) o += u; s.set(l, a + 1); const c = { tag: e, position: o, counter: a }; r != null && (c.namespace = r), t != null && (c.values = t), this.path.push(c); } /** * Pop the last tag from the path * @returns {Object|undefined} The popped node */ pop() { if (this.path.length === 0) return; const e = this.path.pop(); return this.siblingStacks.length > this.path.length + 1 && (this.siblingStacks.length = this.path.length + 1), e; } /** * Update current node's attribute values * Useful when attributes are parsed after push * @param {Object} attrValues - Attribute values */ updateCurrent(e) { if (this.path.length > 0) { const t = this.path[this.path.length - 1]; e != null && (t.values = e); } } /** * Get current tag name * @returns {string|undefined} */ getCurrentTag() { return this.path.length > 0 ? this.path[this.path.length - 1].tag : void 0; } /** * Get current namespace * @returns {string|undefined} */ getCurrentNamespace() { return this.path.length > 0 ? this.path[this.path.length - 1].namespace : void 0; } /** * Get current node's attribute value * @param {string} attrName - Attribute name * @returns {*} Attribute value or undefined */ getAttrValue(e) { var r; return this.path.length === 0 || (r = this.path[this.path.length - 1].values) == null ? void 0 : r[e]; } /** * Check if current node has an attribute * @param {string} attrName - Attribute name * @returns {boolean} */ hasAttr(e) { if (this.path.length === 0) return !1; const t = this.path[this.path.length - 1]; return t.values !== void 0 && e in t.values; } /** * Get current node's sibling position (child index in parent) * @returns {number} */ getPosition() { return this.path.length === 0 ? -1 : this.path[this.path.length - 1].position ?? 0; } /** * Get current node's repeat counter (occurrence count of this tag name) * @returns {number} */ getCounter() { return this.path.length === 0 ? -1 : this.path[this.path.length - 1].counter ?? 0; } /** * Get current node's sibling index (alias for getPosition for backward compatibility) * @returns {number} * @deprecated Use getPosition() or getCounter() instead */ getIndex() { return this.getPosition(); } /** * Get current path depth * @returns {number} */ getDepth() { return this.path.length; } /** * Get path as string * @param {string} separator - Optional separator (uses default if not provided) * @param {boolean} includeNamespace - Whether to include namespace in output (default: true) * @returns {string} */ toString(e, t = !0) { const r = e || this.separator; return this.path.map((i) => t && i.namespace ? `${i.namespace}:${i.tag}` : i.tag).join(r); } /** * Get path as array of tag names * @returns {string[]} */ toArray() { return this.path.map((e) => e.tag); } /** * Reset the path to empty */ reset() { this.path = [], this.siblingStacks = []; } /** * Match current path against an Expression * @param {Expression} expression - The expression to match against * @returns {boolean} True if current path matches the expression */ matches(e) { const t = e.segments; return t.length === 0 ? !1 : e.hasDeepWildcard() ? this._matchWithDeepWildcard(t) : this._matchSimple(t); } /** * Match simple path (no deep wildcards) * @private */ _matchSimple(e) { if (this.path.length !== e.length) return !1; for (let t = 0; t < e.length; t++) { const r = e[t], i = this.path[t], s = t === this.path.length - 1; if (!this._matchSegment(r, i, s)) return !1; } return !0; } /** * Match path with deep wildcards * @private */ _matchWithDeepWildcard(e) { let t = this.path.length - 1, r = e.length - 1; for (; r >= 0 && t >= 0; ) { const i = e[r]; if (i.type === "deep-wildcard") { if (r--, r < 0) return !0; const s = e[r]; let l = !1; for (let a = t; a >= 0; a--) { const o = a === this.path.length - 1; if (this._matchSegment(s, this.path[a], o)) { t = a - 1, r--, l = !0; break; } } if (!l) return !1; } else { const s = t === this.path.length - 1; if (!this._matchSegment(i, this.path[t], s)) return !1; t--, r--; } } return r < 0; } /** * Match a single segment against a node * @private * @param {Object} segment - Segment from Expression * @param {Object} node - Node from path * @param {boolean} isCurrentNode - Whether this is the current (last) node * @returns {boolean} */ _matchSegment(e, t, r) { if (e.tag !== "*" && e.tag !== t.tag || e.namespace !== void 0 && e.namespace !== "*" && e.namespace !== t.namespace) return !1; if (e.attrName !== void 0) { if (!r || !t.values || !(e.attrName in t.values)) return !1; if (e.attrValue !== void 0) { const i = t.values[e.attrName]; if (String(i) !== String(e.attrValue)) return !1; } } if (e.position !== void 0) { if (!r) return !1; const i = t.counter ?? 0; if (e.position === "first" && i !== 0) return !1; if (e.position === "odd" && i % 2 !== 1) return !1; if (e.position === "even" && i % 2 !== 0) return !1; if (e.position === "nth" && i !== e.positionValue) return !1; } return !0; } /** * Create a snapshot of current state * @returns {Object} State snapshot */ snapshot() { return { path: this.path.map((e) => ({ ...e })), siblingStacks: this.siblingStacks.map((e) => new Map(e)) }; } /** * Restore state from snapshot * @param {Object} snapshot - State snapshot */ restore(e) { this.path = e.path.map((t) => ({ ...t })), this.siblingStacks = e.siblingStacks.map((t) => new Map(t)); } /** * Return a read-only view of this matcher. * * The returned object exposes all query/inspection methods but throws a * TypeError if any state-mutating method is called (`push`, `pop`, `reset`, * `updateCurrent`, `restore`). Property reads (e.g. `.path`, `.separator`) * are allowed but the returned arrays/objects are frozen so callers cannot * mutate internal state through them either. * * @returns {ReadOnlyMatcher} A proxy that forwards read operations and blocks writes. * * @example * const matcher = new Matcher(); * matcher.push("root", {}); * * const ro = matcher.readOnly(); * ro.matches(expr); // ✓ works * ro.getCurrentTag(); // ✓ works * ro.push("child", {}); // ✗ throws TypeError * ro.reset(); // ✗ throws TypeError */ readOnly() { const e = this; return new Proxy(e, { get(t, r, i) { if (ct.has(r)) return () => { throw new TypeError( `Cannot call '${r}' on a read-only Matcher. Obtain a writable instance to mutate state.` ); }; const s = Reflect.get(t, r, i); return r === "path" || r === "siblingStacks" ? Object.freeze( Array.isArray(s) ? s.map( (l) => l instanceof Map ? Object.freeze(new Map(l)) : Object.freeze({ ...l }) // freeze a copy of each node ) : s ) : typeof s == "function" ? s.bind(t) : s; }, // Prevent any property assignment on the read-only view set(t, r) { throw new TypeError( `Cannot set property '${String(r)}' on a read-only Matcher.` ); }, // Prevent property deletion deleteProperty(t, r) { throw new TypeError( `Cannot delete property '${String(r)}' from a read-only Matcher.` ); } }); } } function ft(n, e) { if (!n) return {}; const t = e.attributesGroupName ? n[e.attributesGroupName] : n; if (!t) return {}; const r = {}; for (const i in t) if (i.startsWith(e.attributeNamePrefix)) { const s = i.substring(e.attributeNamePrefix.length); r[s] = t[i]; } else r[i] = t[i]; return r; } function dt(n) { if (!n || typeof n != "string") return; const e = n.indexOf(":"); if (e !== -1 && e > 0) { const t = n.substring(0, e); if (t !== "xmlns") return t; } } class pt { constructor(e) { if (this.options = e, this.currentNode = null, this.tagsNodeStack = [], this.docTypeEntities = {}, this.lastEntities = { apos: { regex: /&(apos|#39|#x27);/g, val: "'" }, gt: { regex: /&(gt|#62|#x3E);/g, val: ">" }, lt: { regex: /&(lt|#60|#x3C);/g, val: "<" }, quot: { regex: /&(quot|#34|#x22);/g, val: '"' } }, this.ampEntity = { regex: /&(amp|#38|#x26);/g, val: "&" }, this.htmlEntities = { space: { regex: /&(nbsp|#160);/g, val: " " }, // "lt" : { regex: /&(lt|#60);/g, val: "<" }, // "gt" : { regex: /&(gt|#62);/g, val: ">" }, // "amp" : { regex: /&(amp|#38);/g, val: "&" }, // "quot" : { regex: /&(quot|#34);/g, val: "\"" }, // "apos" : { regex: /&(apos|#39);/g, val: "'" }, cent: { regex: /&(cent|#162);/g, val: "¢" }, pound: { regex: /&(pound|#163);/g, val: "£" }, yen: { regex: /&(yen|#165);/g, val: "¥" }, euro: { regex: /&(euro|#8364);/g, val: "€" }, copyright: { regex: /&(copy|#169);/g, val: "©" }, reg: { regex: /&(reg|#174);/g, val: "®" }, inr: { regex: /&(inr|#8377);/g, val: "₹" }, num_dec: { regex: /&#([0-9]{1,7});/g, val: (t, r) => re(r, 10, "&#") }, num_hex: { regex: /&#x([0-9a-fA-F]{1,6});/g, val: (t, r) => re(r, 16, "&#x") } }, this.addExternalEntities = gt, this.parseXml = Nt, this.parseTextData = bt, this.resolveNameSpace = Et, this.buildAttributesMap = yt, this.isItStopNode = It, this.replaceEntitiesValue = wt, this.readStopNodeData = St, this.saveTextToParentTag = Ct, this.addChild = Tt, this.ignoreAttributesFn = ut(this.options.ignoreAttributes), this.entityExpansionCount = 0, this.currentExpandedLength = 0, this.matcher = new ht(), this.isCurrentNodeStopNode = !1, this.options.stopNodes && this.options.stopNodes.length > 0) { this.stopNodeExpressions = []; for (let t = 0; t < this.options.stopNodes.length; t++) { const r = this.options.stopNodes[t]; typeof r == "string" ? this.stopNodeExpressions.push(new ne(r)) : r instanceof ne && this.stopNodeExpressions.push(r); } } } } function gt(n) { const e = Object.keys(n); for (let t = 0; t < e.length; t++) { const r = e[t], i = r.replace(/[.\-+*:]/g, "\\."); this.lastEntities[r] = { regex: new RegExp("&" + i + ";", "g"), val: n[r] }; } } function bt(n, e, t, r, i, s, l) { if (n !== void 0 && (this.options.trimValues && !r && (n = n.trim()), n.length > 0)) { l || (n = this.replaceEntitiesValue(n, e, t)); const a = this.options.jPath ? t.toString() : t, o = this.options.tagValueProcessor(e, n, a, i, s); return o == null ? n : typeof o != typeof n || o !== n ? o : this.options.trimValues ? G(n, this.options.parseTagValue, this.options.numberParseOptions) : n.trim() === n ? G(n, this.options.parseTagValue, this.options.numberParseOptions) : n; } } function Et(n) { if (this.options.removeNSPrefix) { const e = n.split(":"), t = n.charAt(0) === "/" ? "/" : ""; if (e[0] === "xmlns") return ""; e.length === 2 && (n = t + e[1]); } return n; } const mt = new RegExp(`([^\\s=]+)\\s*(=\\s*(['"])([\\s\\S]*?)\\3)?`, "gm"); function yt(n, e, t) { if (this.options.ignoreAttributes !== !0 && typeof n == "string") { const r = pe(n, mt), i = r.length, s = {}, l = {}; for (let a = 0; a < i; a++) { const o = this.resolveNameSpace(r[a][1]), c = r[a][4]; if (o.length && c !== void 0) { let u = c; this.options.trimValues && (u = u.trim()), u = this.replaceEntitiesValue(u, t, e), l[o] = u; } } Object.keys(l).length > 0 && typeof e == "object" && e.updateCurrent && e.updateCurrent(l); for (let a = 0; a < i; a++) { const o = this.resolveNameSpace(r[a][1]), c = this.options.jPath ? e.toString() : e; if (this.ignoreAttributesFn(o, c)) continue; let u = r[a][4], h = this.options.attributeNamePrefix + o; if (o.length) if (this.options.transformAttributeName && (h = this.options.transformAttributeName(h)), h = ye(h, this.options), u !== void 0) { this.options.trimValues && (u = u.trim()), u = this.replaceEntitiesValue(u, t, e); const d = this.options.jPath ? e.toString() : e, p = this.options.attributeValueProcessor(o, u, d); p == null ? s[h] = u : typeof p != typeof u || p !== u ? s[h] = p : s[h] = G( u, this.options.parseAttributeValue, this.options.numberParseOptions ); } else this.options.allowBooleanAttributes && (s[h] = !0); } if (!Object.keys(s).length) return; if (this.options.attributesGroupName) { const a = {}; return a[this.options.attributesGroupName] = s, a; } return s; } } const Nt = function(n) { n = n.replace(/\r\n?/g, ` `); const e = new C("!xml"); let t = e, r = ""; this.matcher.reset(), this.entityExpansionCount = 0, this.currentExpandedLength = 0; const i = new De(this.options.processEntities); for (let s = 0; s < n.length; s++) if (n[s] === "<") if (n[s + 1] === "/") { const a = S(n, ">", s, "Closing Tag is not closed."); let o = n.substring(s + 2, a).trim(); if (this.options.removeNSPrefix) { const u = o.indexOf(":"); u !== -1 && (o = o.substr(u + 1)); } o = z(this.options.transformTagName, o, "", this.options).tagName, t && (r = this.saveTextToParentTag(r, t, this.matcher)); const c = this.matcher.getCurrentTag(); if (o && this.options.unpairedTags.indexOf(o) !== -1) throw new Error(`Unpaired tag can not be used as closing tag: </${o}>`); c && this.options.unpairedTags.indexOf(c) !== -1 && (this.matcher.pop(), this.tagsNodeStack.pop()), this.matcher.pop(), this.isCurrentNodeStopNode = !1, t = this.tagsNodeStack.pop(), r = "", s = a; } else if (n[s + 1] === "?") { let a = W(n, s, !1, "?>"); if (!a) throw new Error("Pi Tag is not closed."); if (r = this.saveTextToParentTag(r, t, this.matcher), !(this.options.ignoreDeclaration && a.tagName === "?xml" || this.options.ignorePiTags)) { const o = new C(a.tagName); o.add(this.options.textNodeName, ""), a.tagName !== a.tagExp && a.attrExpPresent && (o[":@"] = this.buildAttributesMap(a.tagExp, this.matcher, a.tagName)), this.addChild(t, o, this.matcher, s); } s = a.closeIndex + 1; } else if (n.substr(s + 1, 3) === "!--") { const a = S(n, "-->", s + 4, "Comment is not closed."); if (this.options.commentPropName) { const o = n.substring(s + 4, a - 2); r = this.saveTextToParentTag(r, t, this.matcher), t.add(this.options.commentPropName, [{ [this.options.textNodeName]: o }]); } s = a; } else if (n.substr(s + 1, 2) === "!D") { const a = i.readDocType(n, s); this.docTypeEntities = a.entities, s = a.i; } else if (n.substr(s + 1, 2) === "![") { const a = S(n, "]]>", s, "CDATA is not closed.") - 2, o = n.substring(s + 9, a); r = this.saveTextToParentTag(r, t, this.matcher); let c = this.parseTextData(o, t.tagname, this.matcher, !0, !1, !0, !0); c == null && (c = ""), this.options.cdataPropName ? t.add(this.options.cdataPropName, [{ [this.options.textNodeName]: o }]) : t.add(this.options.textNodeName, c), s = a + 2; } else { let a = W(n, s, this.options.removeNSPrefix); if (!a) { const y = n.substring(Math.max(0, s - 50), Math.min(n.length, s + 50)); throw new Error(`readTagExp returned undefined at position ${s}. Context: "${y}"`); } let o = a.tagName; const c = a.rawTagName; let u = a.tagExp, h = a.attrExpPresent, d = a.closeIndex; if ({ tagName: o, tagExp: u } = z(this.options.transformTagName, o, u, this.options), this.options.strictReservedNames && (o === this.options.commentPropName || o === this.options.cdataPropName || o === this.options.textNodeName || o === this.options.attributesGroupName)) throw new Error(`Invalid tag name: ${o}`); t && r && t.tagname !== "!xml" && (r = this.saveTextToParentTag(r, t, this.matcher, !1)); const p = t; p && this.options.unpairedTags.indexOf(p.tagname) !== -1 && (t = this.tagsNodeStack.pop(), this.matcher.pop()); let g = !1; u.length > 0 && u.lastIndexOf("/") === u.length - 1 && (g = !0, o[o.length - 1] === "/" ? (o = o.substr(0, o.length - 1), u = o) : u = u.substr(0, u.length - 1), h = o !== u); let E = null, A; A = dt(c), o !== e.tagname && this.matcher.push(o, {}, A), o !== u && h && (E = this.buildAttributesMap(u, this.matcher, o), E && ft(E, this.options)), o !== e.tagname && (this.isCurrentNodeStopNode = this.isItStopNode(this.stopNodeExpressions, this.matcher)); const M = s; if (this.isCurrentNodeStopNode) { let y = ""; if (g) s = a.closeIndex; else if (this.options.unpairedTags.indexOf(o) !== -1) s = a.closeIndex; else { const X = this.readStopNodeData(n, c, d + 1); if (!X) throw new Error(`Unexpected end of ${c}`); s = X.i, y = X.tagContent; } const B = new C(o); E && (B[":@"] = E), B.add(this.options.textNodeName, y), this.matcher.pop(), this.isCurrentNodeStopNode = !1, this.addChild(t, B, this.matcher, M); } else { if (g) { ({ tagName: o, tagExp: u } = z(this.options.transformTagName, o, u, this.options)); const y = new C(o); E && (y[":@"] = E), this.addChild(t, y, this.matcher, M), this.matcher.pop(), this.isCurrentNodeStopNode = !1; } else if (this.options.unpairedTags.indexOf(o) !== -1) { const y = new C(o); E && (y[":@"] = E), this.addChild(t, y, this.matcher, M), this.matcher.pop(), this.isCurrentNodeStopNode = !1, s = a.closeIndex; continue; } else { const y = new C(o); if (this.tagsNodeStack.length > this.options.maxNestedTags) throw new Error("Maximum nested tags exceeded"); this.tagsNodeStack.push(t), E && (y[":@"] = E), this.addChild(t, y, this.matcher, M), t = y; } r = "", s = d; } } else r += n[s]; return e.child; }; function Tt(n, e, t, r) { this.options.captureMetaData || (r = void 0); const i = this.options.jPath ? t.toString() : t, s = this.options.updateTag(e.tagname, i, e[":@"]); s === !1 || (typeof s == "string" && (e.tagname = s), n.addChild(e, r)); } function wt(n, e, t) { const r = this.options.processEntities; if (!r || !r.enabled) return n; if (r.allowedTags) { const i = this.options.jPath ? t.toString() : t; if (!(Array.isArray(r.allowedTags) ? r.allowedTags.includes(e) : r.allowedTags(e, i))) return n; } if (r.tagFilter) { const i = this.options.jPath ? t.toString() : t; if (!r.tagFilter(e, i)) return n; } for (const i of Object.keys(this.docTypeEntities)) { const s = this.docTypeEntities[i], l = n.match(s.regx); if (l) { if (this.entityExpansionCount += l.length, r.maxTotalExpansions && this.entityExpansionCount > r.maxTotalExpansions) throw new Error( `Entity expansion limit exceeded: ${this.entityExpansionCount} > ${r.maxTotalExpansions}` ); const a = n.length; if (n = n.replace(s.regx, s.val), r.maxExpandedLength && (this.currentExpandedLength += n.length - a, this.currentExpandedLength > r.maxExpandedLength)) throw new Error( `Total expanded content size exceeded: ${this.currentExpandedLength} > ${r.maxExpandedLength}` ); } } for (const i of Object.keys(this.lastEntities)) { const s = this.lastEntities[i], l = n.match(s.regex); if (l && (this.entityExpansionCount += l.length, r.maxTotalExpansions && this.entityExpansionCount > r.maxTotalExpansions)) throw new Error( `Entity expansion limit exceeded: ${this.entityExpansionCount} > ${r.maxTotalExpansions}` ); n = n.replace(s.regex, s.val); } if (n.indexOf("&") === -1) return n; if (this.options.htmlEntities) for (const i of Object.keys(this.htmlEntities)) { const s = this.htmlEntities[i], l = n.match(s.regex); if (l && (this.entityExpansionCount += l.length, r.maxTotalExpansions && this.entityExpansionCount > r.maxTotalExpansions)) thro