@nodable/flexible-xml-parser 1.1.1 → 1.2.1

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/CHANGELOG.md CHANGED
@@ -0,0 +1,13 @@
1
+
2
+ **1.2.1 (2026-05-28)**
3
+ - update dependencies to fix duplicate entites
4
+ - include fxp.cjs in npm package
5
+
6
+
7
+ **1.2.0 (2026-05-13)**
8
+ - fix: Tag name can be separated with rest of the tag expression by any type of spaces.
9
+ - fix: parser should not fail when tag expresison is very long
10
+ - fix: stop node with namespace should work
11
+ - support `feedable.bufferSize` option to improve/speed up feed method.
12
+ - integrate `xml-naming` library that would also consider xml version
13
+
package/lib/fxp.cjs ADDED
@@ -0,0 +1 @@
1
+ (()=>{"use strict";var t={d:(e,s)=>{for(var r in s)t.o(s,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:s[r]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{ErrorCode:()=>V,ParseError:()=>R,XMLParser:()=>Lt,default:()=>Lt,quoteEnclosures:()=>_t,xmlEnclosures:()=>gt});const s={nameFor:{text:"#text",comment:"",cdata:""},skip:{declaration:!1,pi:!1,attributes:!0,cdata:!1,comment:!1,nsPrefix:!1,tags:!1},tags:{valueParsers:[],stopNodes:[]},attributes:{prefix:"@_",suffix:"",groupBy:"",valueParsers:[]}},r=["trim","number","boolean","entity"],n=["trim","number","boolean","entity"];function i(t){const e=o(s);return t&&void 0!==t.tags?.valueParsers||(e.tags.valueParsers=[...r]),t&&void 0!==t.attributes?.valueParsers||(e.attributes.valueParsers=[...n]),t&&a(e,t),e}function o(t){if(null===t||"object"!=typeof t)return t;if(Array.isArray(t))return t.map(o);const e={};for(const s of Object.keys(t))e[s]=o(t[s]);return e}function a(t,e){for(const s of Object.keys(e))"__proto__"!==s&&"constructor"!==s&&"prototype"!==s&&("function"==typeof e[s]||Array.isArray(e[s])?t[s]=e[s]:"object"==typeof e[s]&&null!==e[s]?("object"==typeof t[s]&&null!==t[s]||(t[s]={}),a(t[s],e[s])):t[s]=e[s])}const h=/^[-+]?0x[a-fA-F0-9]+$/,c=/^([\-\+])?(0*)([0-9]*(\.[0-9]*)?)$/,l={hex:!0,leadingZeros:!0,decimalPoint:".",eNotation:!0,infinity:"original"};const u=/^([-+])?(0*)(\d*(\.\d*)?[eE][-\+]?\d+)$/,d={amp:"&",apos:"'",gt:">",lt:"<",quot:'"'},f=new Set("!?\\\\/[]$%{}^&*()<>|+");function p(t){if("#"===t[0])throw new Error(`[EntityReplacer] Invalid character '#' in entity name: "${t}"`);for(const e of t)if(f.has(e))throw new Error(`[EntityReplacer] Invalid character '${e}' in entity name: "${t}"`);return t}function g(...t){const e=Object.create(null);for(const s of t)if(s)for(const t of Object.keys(s)){const r=s[t];if("string"==typeof r)e[t]=r;else if(r&&"object"==typeof r&&void 0!==r.val){const s=r.val;"string"==typeof s&&(e[t]=s)}}return e}const _="external",E="base",m="all",x=Object.freeze({allow:0,leave:1,remove:2,throw:3}),T=new Set([9,10,13]);class N{constructor(t={}){var e;this._limit=t.limit||{},this._maxTotalExpansions=this._limit.maxTotalExpansions||0,this._maxExpandedLength=this._limit.maxExpandedLength||0,this._postCheck="function"==typeof t.postCheck?t.postCheck:t=>t,this._limitTiers=(e=this._limit.applyLimitsTo??_)&&e!==_?e===m?new Set([m]):e===E?new Set([E]):Array.isArray(e)?new Set(e):new Set([_]):new Set([_]),this._numericAllowed=t.numericAllowed??!0,this._baseMap=g(d,t.namedEntities||null),this._externalMap=Object.create(null),this._inputMap=Object.create(null),this._totalExpansions=0,this._expandedLength=0,this._removeSet=new Set(t.remove&&Array.isArray(t.remove)?t.remove:[]),this._leaveSet=new Set(t.leave&&Array.isArray(t.leave)?t.leave:[]);const s=function(t){if(!t)return{xmlVersion:1,onLevel:x.allow,nullLevel:x.remove};const e=1.1===t.xmlVersion?1.1:1,s=x[t.onNCR]??x.allow,r=x[t.nullNCR]??x.remove;return{xmlVersion:e,onLevel:s,nullLevel:Math.max(r,x.remove)}}(t.ncr);this._ncrXmlVersion=s.xmlVersion,this._ncrOnLevel=s.onLevel,this._ncrNullLevel=s.nullLevel}setExternalEntities(t){if(t)for(const e of Object.keys(t))p(e);this._externalMap=g(t)}addExternalEntity(t,e){p(t),"string"==typeof e&&-1===e.indexOf("&")&&(this._externalMap[t]=e)}addInputEntities(t){this._totalExpansions=0,this._expandedLength=0,this._inputMap=g(t)}reset(){return this._inputMap=Object.create(null),this._totalExpansions=0,this._expandedLength=0,this}setXmlVersion(t){this._ncrXmlVersion=1.1===t?1.1:1}decode(t){if("string"!=typeof t||0===t.length)return t;const e=t,s=[],r=t.length;let n=0,i=0;const o=this._maxTotalExpansions>0,a=this._maxExpandedLength>0,h=o||a;for(;i<r;){if(38!==t.charCodeAt(i)){i++;continue}let e=i+1;for(;e<r&&59!==t.charCodeAt(e)&&e-i<=32;)e++;if(e>=r||59!==t.charCodeAt(e)){i++;continue}const c=t.slice(i+1,e);if(0===c.length){i++;continue}let l,u;if(this._removeSet.has(c))l="",void 0===u&&(u=_);else{if(this._leaveSet.has(c)){i++;continue}if(35===c.charCodeAt(0)){const t=this._resolveNCR(c);if(void 0===t){i++;continue}l=t,u=E}else{const t=this._resolveName(c);l=t?.value,u=t?.tier}}if(void 0!==l){if(i>n&&s.push(t.slice(n,i)),s.push(l),n=e+1,i=n,h&&this._tierCounts(u)){if(o&&(this._totalExpansions++,this._totalExpansions>this._maxTotalExpansions))throw new Error(`[EntityReplacer] Entity expansion count limit exceeded: ${this._totalExpansions} > ${this._maxTotalExpansions}`);if(a){const t=l.length-(c.length+2);if(t>0&&(this._expandedLength+=t,this._expandedLength>this._maxExpandedLength))throw new Error(`[EntityReplacer] Expanded content length limit exceeded: ${this._expandedLength} > ${this._maxExpandedLength}`)}}}else i++}n<r&&s.push(t.slice(n));const c=0===s.length?t:s.join("");return this._postCheck(c,e)}_tierCounts(t){return!!this._limitTiers.has(m)||this._limitTiers.has(t)}_resolveName(t){return t in this._inputMap?{value:this._inputMap[t],tier:_}:t in this._externalMap?{value:this._externalMap[t],tier:_}:t in this._baseMap?{value:this._baseMap[t],tier:E}:void 0}_classifyNCR(t){return 0===t?this._ncrNullLevel:t>=55296&&t<=57343||1===this._ncrXmlVersion&&t>=1&&t<=31&&!T.has(t)?x.remove:-1}_applyNCRAction(t,e,s){switch(t){case x.allow:return String.fromCodePoint(s);case x.remove:return"";case x.leave:return;case x.throw:throw new Error(`[EntityDecoder] Prohibited numeric character reference &${e}; (U+${s.toString(16).toUpperCase().padStart(4,"0")})`);default:return String.fromCodePoint(s)}}_resolveNCR(t){const e=t.charCodeAt(1);let s;if(s=120===e||88===e?parseInt(t.slice(2),16):parseInt(t.slice(1),10),Number.isNaN(s)||s<0||s>1114111)return;const r=this._classifyNCR(s);if(!this._numericAllowed&&r<x.remove)return;const n=-1===r?this._ncrOnLevel:Math.max(this._ncrOnLevel,r);return this._applyNCRAction(n,t,s)}}class I extends N{constructor(t){super(t)}parse(t){return"string"==typeof t&&(t=this.decode(t)),t}}class w{parse(t){return"string"==typeof t?t.trim():t}}class A{constructor(t,e){this.trueList=t||["true"],this.falseList=e||["false"]}parse(t){if("string"==typeof t){const e=t.toLowerCase();if(-1!==this.trueList.indexOf(e))return!0;if(-1!==this.falseList.indexOf(e))return!1}return t}}class C{constructor(t){this.options=t||{}}parse(t){return"string"==typeof t&&(t=function(t,e={}){if(e=Object.assign({},l,e),!t||"string"!=typeof t)return t;let s=t.trim();if(0===s.length)return t;if(void 0!==e.skipLike&&e.skipLike.test(s))return t;if("0"===s)return 0;if(e.hex&&h.test(s))return function(t){if(parseInt)return parseInt(t,16);if(Number.parseInt)return Number.parseInt(t,16);if(window&&window.parseInt)return window.parseInt(t,16);throw new Error("parseInt, Number.parseInt, window.parseInt are not supported")}(s);if(isFinite(s)){if(s.includes("e")||s.includes("E"))return function(t,e,s){if(!s.eNotation)return t;const r=e.match(u);if(r){let n=r[1]||"";const i=-1===r[3].indexOf("e")?"E":"e",o=r[2],a=n?t[o.length+1]===i:t[o.length]===i;return o.length>1&&a?t:(1!==o.length||!r[3].startsWith(`.${i}`)&&r[3][0]!==i)&&o.length>0?s.leadingZeros&&!a?(e=(r[1]||"")+r[3],Number(e)):t:Number(e)}return t}(t,s,e);{const n=c.exec(s);if(n){const i=n[1]||"",o=n[2];let a=(r=n[3])&&-1!==r.indexOf(".")?("."===(r=r.replace(/0+$/,""))?r="0":"."===r[0]?r="0"+r:"."===r[r.length-1]&&(r=r.substring(0,r.length-1)),r):r;const h=i?"."===t[o.length+1]:"."===t[o.length];if(!e.leadingZeros&&(o.length>1||1===o.length&&!h))return t;{const r=Number(s),n=String(r);if(0===r)return r;if(-1!==n.search(/[eE]/))return e.eNotation?r:t;if(-1!==s.indexOf("."))return"0"===n||n===a||n===`${i}${a}`?r:t;let h=o?a:s;return o?h===n||i+h===n?r:t:h===n||h===i+n?r:t}}return t}}var r;return function(t,e,s){const r=e===1/0;switch(s.infinity.toLowerCase()){case"null":return null;case"infinity":return e;case"string":return r?"Infinity":"-Infinity";default:return t}}(t,Number(s),e)}(t,this.options)),t}}const S={maxLength:200},y={$:"en-US","€":"de-DE","£":"en-GB","¥":"ja-JP","₹":"en-IN"},D=/^\s*(?:-|\+)?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d{1,2})?\s*(?:\$|€|¥|₹)?\s*$/u;class b{constructor(t){this.options=t||S}parse(t){if("string"==typeof t&&t.length<=this.options.maxLength&&-1!==t.indexOf(",,")&&t.indexOf(!0)){const e=t.match(D);if(e){const s=this.options.locale||y[e[2]||e[5]||"₹"],r=new Intl.NumberFormat(s);t=t.replace(/[^0-9,.]/g,"").trim(),t=Number(t.replace(r.format(1e3)[1],""))}}return t}}b.defaultOptions=S;const P=Object.freeze({ELEMENT:"ELEMENT",ATTRIBUTE:"ATTRIBUTE"});class U{constructor(t){this.matcher=t||null,this._rootName="^"}addAttribute(t,e,s){"version"===t&&this.tagName===this._rootName&&k(this.registeredValParsers,"setXmlVersion",+e);const r=this.options.attributes.prefix+t+this.options.attributes.suffix,n={elementName:t,elementValue:e,elementType:P.ATTRIBUTE,matcher:s,isLeafNode:!0};this.attributes[r]=this.parseValue(e,this.options.attributes.valueParsers,n)}parseValue(t,e,s){for(let r=0;r<e.length;r++){let n=e[r];"string"==typeof n&&(n=this.registeredValParsers[n]),n&&(t=n.parse(t,s))}return t}_addChild(t,e){}addComment(t){this.options.skip.comment||this.options.nameFor.comment&&this._addChild(this.options.nameFor.comment,t)}addLiteral(t){this.options.skip.cdata||(this.options.nameFor.cdata?this._addChild(this.options.nameFor.cdata,t):this.addRawValue(t||""))}addRawValue(t){this.addValue(t)}addInputEntities(t){k(this.registeredValParsers,"addInputEntities",t)}addDeclaration(t){this.addInstruction(t)}addInstruction(t){}onExit(t){}}function k(t,e,s){for(const r of Object.values(t))"function"==typeof r[e]&&r[e](s)}class v{constructor(){this.commonValParsers={entity:new I,trim:new w,boolean:new A,number:new C({hex:!0,leadingZeros:!0,eNotation:!0}),currency:new b}}registerValueParser(t,e){this.commonValParsers[t]=e}getInstance(t,e){return this.resetValueParsers(),new U(t,e,this.commonValParsers)}resetValueParsers(){for(const t of Object.values(this.commonValParsers))t&&t.reset&&t.reset()}}class O{constructor(t,e={},s){this.pattern=t,this.separator=e.separator||".",this.segments=this._parse(t),this.data=s,this._hasDeepWildcard=this.segments.some(t=>"deep-wildcard"===t.type),this._hasAttributeCondition=this.segments.some(t=>void 0!==t.attrName),this._hasPositionSelector=this.segments.some(t=>void 0!==t.position)}_parse(t){const e=[];let s=0,r="";for(;s<t.length;)t[s]===this.separator?s+1<t.length&&t[s+1]===this.separator?(r.trim()&&(e.push(this._parseSegment(r.trim())),r=""),e.push({type:"deep-wildcard"}),s+=2):(r.trim()&&e.push(this._parseSegment(r.trim())),r="",s++):(r+=t[s],s++);return r.trim()&&e.push(this._parseSegment(r.trim())),e}_parseSegment(t){const e={type:"tag"};let s=null,r=t;const n=t.match(/^([^\[]+)(\[[^\]]*\])(.*)$/);if(n&&(r=n[1]+n[3],n[2])){const t=n[2].slice(1,-1);t&&(s=t)}let i,o,a=r;if(r.includes("::")){const e=r.indexOf("::");if(i=r.substring(0,e).trim(),a=r.substring(e+2).trim(),!i)throw new Error(`Invalid namespace in pattern: ${t}`)}let h=null;if(a.includes(":")){const t=a.lastIndexOf(":"),e=a.substring(0,t).trim(),s=a.substring(t+1).trim();["first","last","odd","even"].includes(s)||/^nth\(\d+\)$/.test(s)?(o=e,h=s):o=a}else o=a;if(!o)throw new Error(`Invalid segment pattern: ${t}`);if(e.tag=o,i&&(e.namespace=i),s)if(s.includes("=")){const t=s.indexOf("=");e.attrName=s.substring(0,t).trim(),e.attrValue=s.substring(t+1).trim()}else e.attrName=s.trim();if(h){const t=h.match(/^nth\((\d+)\)$/);t?(e.position="nth",e.positionValue=parseInt(t[1],10)):e.position=h}return e}get length(){return this.segments.length}hasDeepWildcard(){return this._hasDeepWildcard}hasAttributeCondition(){return this._hasAttributeCondition}hasPositionSelector(){return this._hasPositionSelector}toString(){return this.pattern}}class M extends v{constructor(t){super(),this.options=i(t),this.options.alwaysArray&&(this.options.alwaysArray=this.options.alwaysArray.map(t=>"string"==typeof t?new O(t):t))}getInstance(t,e){this.resetValueParsers();const s={...this.commonValParsers};return new L(t,this.options,s,e)}}class L extends U{constructor(t,e,s,r){super(r),this.tagsStack=[],this.options={...e,...t,skip:{...e.skip,...t.skip},nameFor:{...e.nameFor,...t.nameFor},tags:{...e.tags,...t.tags},attributes:{...e.attributes,...t.attributes},textJoint:e.textJoint||"",forceArray:e?.forceArray||null,alwaysArray:e?.alwaysArray||[],forceTextNode:e?.forceTextNode??!1},this.registeredValParsers=s,this.root={},this.parent=this.root,this.tagName=this._rootName,this.value={},this.textValue="",this.attributes={},this.hasAttributes=!1}_buildAttributeValue(){return B(this.attributes)?(this.hasAttributes=!1,""):(this.hasAttributes=!0,this.options.attributes.groupBy?{[this.options.attributes.groupBy]:this.attributes}:this.attributes)}addElement(t){const e=this._buildAttributeValue();this.tagsStack.push([this.tagName,this.textValue,this.value,this.hasAttributes]),this.tagName=t.name,this.value=e,this.textValue="",this.attributes={}}onStopNode(t,e){"function"==typeof this.options.onStopNode&&this.options.onStopNode(t,e,this.matcher)}_resolveForceArray(t){let e,s;if(this.options.alwaysArray.some(t=>this.matcher.matches(t))&&(e=!0),"function"==typeof this.options.forceArray){const e=this.options.forceArray(this.matcher,t);!0===e?s=!0:!1===e&&(s=!1)}return!1!==e&&!1!==s&&(!0===e||!0===s)}closeElement(){const t=this.tagName;let e=this.value;const s=this.textValue,r=this.hasAttributes,n="object"!=typeof e||Array.isArray(e)||B(e)||r,i={elementName:t,elementValue:s,elementType:P.ELEMENT,matcher:this.matcher,isLeafNode:n};if(n){const t=this.parseValue(s,this.options.tags.valueParsers,i);r?(""!==t&&null!=t||this.options.forceTextNode)&&(e[this.options.nameFor.text]=t):e=this.options.forceTextNode?{[this.options.nameFor.text]:t}:t}else if(s.length>0){const t=this.parseValue(s,this.options.tags.valueParsers,i);e[this.options.nameFor.text]=t}else if(s.length>0||this.options.forceTextNode){const t=this.parseValue(s,this.options.tags.valueParsers,i);e[this.options.nameFor.text]=t}let o={tagName:t,value:e};if(void 0!==this.options.onTagClose&&(o=this.options.onTagClose(t,e,s,this.matcher),!o))return;const a=this.tagsStack.pop();let h=a[2];const c=this._resolveForceArray(n);h=this._addChildTo(o.tagName,o.value,h,c),this.tagName=a[0],this.textValue=a[1],this.value=h,this.hasAttributes=a[3]}_addChild(t,e){"string"==typeof this.value&&(this.value={[this.options.nameFor.text]:this.value}),this._addChildTo(t,e,this.value,!1),this.attributes={}}_addChildTo(t,e,s,r){return"string"==typeof s&&(s={}),Object.prototype.hasOwnProperty.call(s,t)?(Array.isArray(s[t])||(s[t]=[s[t]]),s[t].push(e)):s[t]=r?[e]:e,s}addValue(t){this.textValue.length>0?this.textValue+=this.options.textJoint+t:this.textValue=t}onExit(t){}addInstruction(t){const e=this._buildAttributeValue();this._addChild(t,e),this.attributes={}}getOutput(){return this.value}}function B(t){return 0===Object.keys(t).length}class ${constructor(){this._byDepthAndTag=new Map,this._wildcardByDepth=new Map,this._deepWildcards=[],this._patterns=new Set,this._sealed=!1}add(t){if(this._sealed)throw new TypeError("ExpressionSet is sealed. Create a new ExpressionSet to add more expressions.");if(this._patterns.has(t.pattern))return this;if(this._patterns.add(t.pattern),t.hasDeepWildcard())return this._deepWildcards.push(t),this;const e=t.length,s=t.segments[t.segments.length-1],r=s?.tag;if(r&&"*"!==r){const s=`${e}:${r}`;this._byDepthAndTag.has(s)||this._byDepthAndTag.set(s,[]),this._byDepthAndTag.get(s).push(t)}else this._wildcardByDepth.has(e)||this._wildcardByDepth.set(e,[]),this._wildcardByDepth.get(e).push(t);return this}addAll(t){for(const e of t)this.add(e);return this}has(t){return this._patterns.has(t.pattern)}get size(){return this._patterns.size}seal(){return this._sealed=!0,this}get isSealed(){return this._sealed}matchesAny(t){return null!==this.findMatch(t)}findMatch(t){const e=t.getDepth(),s=`${e}:${t.getCurrentTag()}`,r=this._byDepthAndTag.get(s);if(r)for(let e=0;e<r.length;e++)if(t.matches(r[e]))return r[e];const n=this._wildcardByDepth.get(e);if(n)for(let e=0;e<n.length;e++)if(t.matches(n[e]))return n[e];for(let e=0;e<this._deepWildcards.length;e++)if(t.matches(this._deepWildcards[e]))return this._deepWildcards[e];return null}}class R extends Error{constructor(t,e,s={}){super(t),this.name="ParseError",this.code=e,this.line=s.line??void 0,this.col=s.col??void 0,this.index=s.index??void 0}toString(){const t=this._posStr();return t?`${this.name} [${this.code}] at ${t}: ${this.message}`:`${this.name} [${this.code}]: ${this.message}`}_posStr(){return void 0!==this.line&&void 0!==this.col?`line ${this.line}, col ${this.col}`:void 0!==this.index?`index ${this.index}`:null}}const V=Object.freeze({INVALID_INPUT:"INVALID_INPUT",INVALID_STREAM:"INVALID_STREAM",ALREADY_STREAMING:"ALREADY_STREAMING",NOT_STREAMING:"NOT_STREAMING",DATA_MUST_BE_STRING:"DATA_MUST_BE_STRING",UNEXPECTED_END:"UNEXPECTED_END",UNEXPECTED_CLOSE_TAG:"UNEXPECTED_CLOSE_TAG",MISMATCHED_CLOSE_TAG:"MISMATCHED_CLOSE_TAG",UNEXPECTED_TRAILING_DATA:"UNEXPECTED_TRAILING_DATA",INVALID_TAG:"INVALID_TAG",UNCLOSED_QUOTE:"UNCLOSED_QUOTE",MULTIPLE_NAMESPACES:"MULTIPLE_NAMESPACES",SECURITY_PROTOTYPE_POLLUTION:"SECURITY_PROTOTYPE_POLLUTION",SECURITY_RESERVED_OPTION:"SECURITY_RESERVED_OPTION",SECURITY_RESTRICTED_NAME:"SECURITY_RESTRICTED_NAME",LIMIT_MAX_NESTED_TAGS:"LIMIT_MAX_NESTED_TAGS",LIMIT_MAX_ATTRIBUTES:"LIMIT_MAX_ATTRIBUTES",ENTITY_MAX_COUNT:"ENTITY_MAX_COUNT",ENTITY_MAX_SIZE:"ENTITY_MAX_SIZE",ENTITY_MAX_EXPANSIONS:"ENTITY_MAX_EXPANSIONS",ENTITY_MAX_EXPANDED_LENGTH:"ENTITY_MAX_EXPANDED_LENGTH",ENTITY_INVALID_KEY:"ENTITY_INVALID_KEY",ENTITY_INVALID_VALUE:"ENTITY_INVALID_VALUE"});function X(t){return" "===t||"\t"===t||"\n"===t||"\r"===t||"\f"===t}function Y(t){return 32===t||9===t||10===t||13===t||12===t}const F=["hasOwnProperty","toString","valueOf","__defineGetter__","__defineSetter__","__lookupGetter__","__lookupSetter__","toLocaleString","isPrototypeOf","propertyIsEnumerable"],G=["__proto__","constructor","prototype"],j=t=>F.includes(t)?"__"+t:t,z={skip:{declaration:!1,pi:!1,attributes:!0,cdata:!1,comment:!1,nsPrefix:!1,tags:[]},nameFor:{text:"#text",cdata:"",comment:""},attributes:{booleanType:!1,groupBy:"",prefix:"@_",suffix:""},tags:{unpaired:[],stopNodes:[]},strictReservedNames:!1,onDangerousProperty:j,only:[],doctypeOptions:{enabled:!1,maxEntityCount:100,maxEntitySize:1e4},autoClose:null,limits:{maxNestedTags:null,maxAttributesPerTag:null},feedable:{maxBufferSize:10485760,autoFlush:!0,flushThreshold:1024,bufferSize:256},exitIf:null,OutputBuilder:null},H=new Set([...G,...F]);function W(t,e){if("string"==typeof t&&""!==t&&H.has(t))throw new R(`SECURITY: '${t}' is a reserved JavaScript keyword and cannot be used as ${e}`,V.SECURITY_RESERVED_OPTION)}const Z=function(t){if(t&&(t.nameFor?.text&&W(t.nameFor.text,"nameFor.text"),t.nameFor?.cdata&&W(t.nameFor.cdata,"nameFor.cdata"),t.nameFor?.comment&&W(t.nameFor.comment,"nameFor.comment"),t.attributes?.prefix&&W(t.attributes.prefix,"attributes.prefix"),t.attributes?.groupBy&&W(t.attributes.groupBy,"attributes.groupBy"),void 0!==t.limits&&null!==t.limits)){if("object"!=typeof t.limits)throw new R("'limits' must be an object, got "+typeof t.limits,V.INVALID_INPUT);const{maxNestedTags:e,maxAttributesPerTag:s}=t.limits;if(null!=e&&("number"!=typeof e||!Number.isInteger(e)||e<1))throw new R(`'limits.maxNestedTags' must be a positive integer, got ${e}`,V.INVALID_INPUT);if(null!=s&&("number"!=typeof s||!Number.isInteger(s)||s<0))throw new R(`'limits.maxAttributesPerTag' must be a non-negative integer, got ${s}`,V.INVALID_INPUT)}const e=Q(z);if(t&&K(e,t),e.OutputBuilder||(e.OutputBuilder=new M),Array.isArray(e.tags?.stopNodes)){const t=new $;e.tags.stopNodes=e.tags.stopNodes.map(e=>J(e,"stopNodes",t)),t.seal(),e.tags.stopNodesSet=t}if(Array.isArray(e.skip?.tags)){const t=new $;e.skip.tags=e.skip.tags.map(e=>J(e,"skip.tags",t)),t.seal(),e.skip.tagsSet=t}if(null===e.onDangerousProperty&&(e.onDangerousProperty=j),null!==e.exitIf&&void 0!==e.exitIf&&"function"!=typeof e.exitIf)throw new R("'exitIf' must be a function, got "+typeof e.exitIf,V.INVALID_INPUT);return e.autoClose=function(t,e){if(!t)return null;if("html"===t){const t=e.tags.unpaired||[],s=[...new Set([...t,...q])];return e.tags={...e.tags,unpaired:s},{onEof:"closeAll",onMismatch:"discard",collectErrors:!0}}return"string"==typeof t?{onEof:t,onMismatch:"throw",collectErrors:!1}:"object"==typeof t?{onEof:t.onEof||"throw",onMismatch:t.onMismatch||"throw",collectErrors:t.collectErrors||!1}:null}(e.autoClose,e),e},q=["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"];function J(t,e,s){let r,n,i;if("string"==typeof t){if(0===t.length)throw new R(`${e} expression cannot be empty`,V.INVALID_INPUT);r=t,n=!1,i=[]}else if(t instanceof O)r=t.toString(),n=t.data?.nested??!1,i=t.data?.skipEnclosures??[];else{if(!t||"object"!=typeof t||void 0===t.expression)throw new R(`Invalid ${e} entry: expected a string, Expression, or { expression, nested?, skipEnclosures? } object.`,V.INVALID_INPUT);{const s=t.expression;if("string"==typeof s){if(0===s.length)throw new R(`${e} expression cannot be empty`,V.INVALID_INPUT);r=s}else{if(!(s instanceof O))throw new R(`${e} expression must be a string or Expression instance`,V.INVALID_INPUT);r=s.toString()}n=!0===t.nested,i=Array.isArray(t.skipEnclosures)?t.skipEnclosures:[]}}const o=new O(r,{},{nested:n,skipEnclosures:i});return s.add(o),o}function Q(t){if(null===t||"object"!=typeof t)return t;if(Array.isArray(t))return t.map(Q);if(t instanceof RegExp)return t;if(t instanceof O)return t;const e={};for(const s of Object.keys(t))e[s]="function"==typeof t[s]?t[s]:Q(t[s]);return e}function K(t,e){for(const s of Object.keys(e))"__proto__"!==s&&"constructor"!==s&&"prototype"!==s&&("OutputBuilder"===s||"function"==typeof e[s]||e[s]instanceof RegExp||Array.isArray(e[s])?t[s]=e[s]:"object"==typeof e[s]&&null!==e[s]?("object"==typeof t[s]&&null!==t[s]||(t[s]={}),K(t[s],e[s])):t[s]=e[s])}class tt{constructor(t,e={}){this.line=1,this.cols=0,this.buffer=t,this.startIndex=0,this.autoFlush=!1!==e.autoFlush,this.flushThreshold=e.flushThreshold??1024,this._marks=[-1,-1]}markTokenStart(t=0){this._marks[t]=this.startIndex}rewindToMark(){}clearMark(){this._marks[0]=-1,this._marks[1]=-1}flush(){let t=this.startIndex;for(const e of this._marks)e>=0&&e<t&&(t=e);if(t>0){this.buffer=this.buffer.substring(t);const e=this._marks.length;for(let s=0;s<e;s++)this._marks[s]>=0&&(this._marks[s]-=t);this.startIndex-=t}}readCh(){return this.buffer[this.startIndex++]}readChAt(t){return this.buffer[this.startIndex+t]}readStr(t,e){return void 0===e&&(e=this.startIndex),this.buffer.substring(e,e+t)}readUpto(t){const e=this.buffer.length,s=t.length;for(let r=this.startIndex;r<e;r++){let e=!0;for(let n=0;n<s;n++)if(this.buffer[r+n]!==t[n]){e=!1;break}if(e){const t=this.buffer.substring(this.startIndex,r);return this.startIndex=r+s,t}}throw new R(`Unexpected end of source reading '${t}'`,V.UNEXPECTED_END)}readUptoChar(t){const e=this.buffer.indexOf(t,this.startIndex);if(-1===e)throw new R(`Unexpected end of source reading '${t}'`,V.UNEXPECTED_END);const s=this.buffer.substring(this.startIndex,e);return this.startIndex=e+1,s}readUptoCloseTag(t){const e=this.buffer.length,s=t.length;let r=-1,n=0;for(let i=this.startIndex;i<e;i++){if(1===n){const t=this.buffer[i];if(" "===t||"\t"===t)continue;">"===t?n=2:(n=0,r=-1)}else{let e=!0;for(let r=0;r<s;r++)if(this.buffer[i+r]!==t[r]){e=!1;break}e&&(n=1,r=i,i+=s-1)}if(2===n){const t=this.buffer.substring(this.startIndex,r);return this.startIndex=i+1,t}}throw new R(`Unexpected end of source reading '${t}'`,V.UNEXPECTED_END)}readFromBuffer(t,e){const s=1===t?this.buffer[this.startIndex]:this.buffer.substring(this.startIndex,this.startIndex+t);return e&&this.updateBufferBoundary(t),s}updateBufferBoundary(t=1){this.startIndex+=t;const e=this._marks[0]>=0||this._marks[1]>=0;this.autoFlush&&this.startIndex>=this.flushThreshold&&!e&&this.flush()}canRead(t){return t=void 0!==t?t:this.startIndex,this.buffer.length-t>0}}class et{constructor(t,e={}){this.line=1,this.cols=0,this.buffer=t,this.startIndex=0,this.autoFlush=!1!==e.autoFlush,this.flushThreshold=e.flushThreshold??1024,this._tokenStart=-1}markTokenStart(){this._tokenStart=this.startIndex}rewindToMark(){}flush(){const t=this._tokenStart>=0?this._tokenStart:this.startIndex;t>0&&(this.buffer=Buffer.from(this.buffer.subarray(t)),this._tokenStart>=0?(this.startIndex-=t,this._tokenStart=0):this.startIndex=0)}readCh(){return String.fromCharCode(this.buffer[this.startIndex++])}readChAt(t){return String.fromCharCode(this.buffer[this.startIndex+t])}readStr(t,e){return void 0===e&&(e=this.startIndex),this.buffer.slice(e,e+t).toString()}readUpto(t){const e=this.buffer.length,s=t.length,r=Buffer.from(t);for(let t=this.startIndex;t<e;t++){let e=!0;for(let n=0;n<s;n++)if(this.buffer[t+n]!==r[n]){e=!1;break}if(e){const e=this.buffer.slice(this.startIndex,t).toString();return this.startIndex=t+s,e}}throw new R(`Unexpected end of source reading '${t}'`,V.UNEXPECTED_END)}readUptoChar(t){const e=t.charCodeAt(0),s=this.buffer,r=s.length;for(let t=this.startIndex;t<r;t++)if(s[t]===e){const e=s.slice(this.startIndex,t).toString();return this.startIndex=t+1,e}throw new R(`Unexpected end of source reading '${t}'`,V.UNEXPECTED_END)}readUptoCloseTag(t){const e=this.buffer.length,s=t.length,r=Buffer.from(t);let n=-1,i=0;for(let t=this.startIndex;t<e;t++){if(1===i){const e=this.buffer[t];if(32===e||9===e)continue;62===e?i=2:(i=0,n=-1)}else{let e=!0;for(let n=0;n<s;n++)if(this.buffer[t+n]!==r[n]){e=!1;break}e&&(i=1,n=t,t+=s-1)}if(2===i){const e=this.buffer.slice(this.startIndex,n).toString();return this.startIndex=t+1,e}}throw new R(`Unexpected end of source reading '${t}'`,V.UNEXPECTED_END)}readFromBuffer(t,e){let s;return 1===t?(s=this.buffer[this.startIndex],10===s?(this.line++,this.cols=1):this.cols++,s=String.fromCharCode(s)):(this.cols+=t,s=this.buffer.slice(this.startIndex,this.startIndex+t).toString()),e&&this.updateBufferBoundary(t),s}updateBufferBoundary(t=1){this.startIndex+=t,this.autoFlush&&this.startIndex>=this.flushThreshold&&this._tokenStart<0&&this.flush()}canRead(t){return t=void 0!==t?t:this.startIndex,this.buffer.length-t>0}}function st(t){const e=[],s=t.length;let r=0;for(;r<s;){for(;r<s&&Y(t.charCodeAt(r));)r++;if(r>=s)break;const n=r;for(;r<s&&61!==t.charCodeAt(r)&&!Y(t.charCodeAt(r));)r++;const i=t.substring(n,r);for(;r<s&&Y(t.charCodeAt(r));)r++;if(r>=s||61!==t.charCodeAt(r)){const t=[i,i,void 0,void 0,void 0];t.startIndex=n,e.push(t);continue}for(r++;r<s&&Y(t.charCodeAt(r));)r++;const o=t.charCodeAt(r);if(34===o||39===o){r++;let a="",h=r;for(;r<s&&t.charCodeAt(r)!==o;){const e=t.charCodeAt(r);10!==e&&13!==e||(a+=t.substring(h,r)+" ",h=r+1),r++}a+=t.substring(h,r),r++;const c=String.fromCharCode(o),l=[i+"="+c+a+c,i,"="+c+a+c,c,a];l.startIndex=n,e.push(l)}}return e}function rt(t,e){if(!t||0===t.length)return;const s=st(t),r=s.length,n=e.options.limits?.maxAttributesPerTag;if(null!=n&&r>n){const t=e.currentTagDetail?.name??"(unknown)";throw new R(`Tag '${t}' has ${r} attributes, exceeding limit of ${n}`,V.LIMIT_MAX_ATTRIBUTES,{line:e.source.line,col:e.source.cols,index:e.source.startIndex})}for(let t=0;t<r;t++){const r=e.processAttrName(s[t][1]);if(!1===r)continue;const n=s[t][4],i=void 0===n||n;e.outputBuilder.addAttribute(r,i,e.readonlyMatcher)}}const nt=":A-Za-z_À-ÖØ-öø-˿Ͱ-ͽͿ-҆҈-῿‌-‍⁰-↏Ⰰ-⿯、-퟿豈-﷏ﷰ-�",it=":A-Za-z_À-˿Ͱ-ͽͿ-҆҈-῿‌-‍⁰-↏Ⰰ-⿯、-퟿豈-﷏ﷰ-�𐀀-󯿿",ot=it+"\\-\\.\\d·̀-ͯ҇‿-⁀",at=(t,e,s="")=>{const r=`[${t.replace(":","")}][${e.replace(":","")}]*`;return{name:new RegExp(`^[${t}][${e}]*$`,s),ncName:new RegExp(`^${r}$`,s),qName:new RegExp(`^${r}(?::${r})?$`,s),nmToken:new RegExp(`^[${e}]+$`,s),nmTokens:new RegExp(`^[${e}]+(?:\\s+[${e}]+)*$`,s)}},ht=at(nt,nt+"\\-\\.\\d·̀-ͯ‿-⁀"),ct=at(it,ot,"u"),lt=(t="1.0")=>"1.1"===t?ct:ht,ut=(t,{xmlVersion:e="1.0"}={})=>lt(e).name.test(t),dt=(t,{xmlVersion:e="1.0"}={})=>lt(e).qName.test(t);function ft(t){t.source.markTokenStart(1);let e,s=!1,r=!1,n=!1;for(e=0;t.source.canRead(e);e++){const i=t.source.readChAt(e);if("'"!==i||r)if('"'!==i||s){if(">"===i&&!s&&!r){n=!0;break}}else r=!r;else s=!s}if(!n)throw new R("Unexpected closing of source waiting for '>'",V.UNEXPECTED_END);if(s||r)throw new R("Invalid attribute expression. Quote is not properly closed",V.UNCLOSED_QUOTE);const i=t.source.readStr(e);return t.source.updateBufferBoundary(e+1),pt(i,t)}function pt(t,e){const s={tagName:"",selfClosing:!1,rawAttributes:Object.create(null),_attrsExp:""};"/"===t[t.length-1]&&(s.selfClosing=!0,t=t.slice(0,-1));let r="",n=0;for(;n<t.length;n++)if(X(t[n])){s.tagName=t.substring(0,n),r=t.substring(n+1);break}if(0===s.tagName.length&&n===t.length&&(s.tagName=t),s.tagName=s.tagName.trimEnd(),s._attrsExp=r,!dt(s.tagName,e.xmlVersion))throw new R("Invalid tag name",V.INVALID_TAG_NAME);return!e.options.skip.attributes&&r.length>0&&function(t,e,s){if(!t||0===t.length)return;const r=st(t),n=r.length;let i=0;for(let t=0;t<n;t++){if(!1===e.processAttrName(r[t][1]))continue;i++;const n=r[t][4];s.rawAttributes[r[t][1]]=void 0===n||n}s.rawAttributesLen=i}(r,e,s),s}const gt=[{open:"\x3c!--",close:"--\x3e"},{open:"<![CDATA[",close:"]]>"},{open:"<?",close:"?>"}],_t=[{open:"'",close:"'"},{open:'"',close:'"'},{open:"`",close:"`"}];class Et{constructor(t,{nested:e=!1,skipEnclosures:s=[]}={}){this._tagName=t,this._nested=e,this._enclosures=s,this._content="",this._depth=1,this._active=!1}isActive(){return this._active}activate(){this._active=!0,this._content="",this._depth=1}resumeAfterOpenTag(){this._content="",this._depth=1}collect(t){t.markTokenStart(1);const e=this._enclosures.length;return this._nested||0!==e?this._nested&&0===e?this._collectDepthOnly(t):!this._nested&&e>0?this._collectEnclosureOnly(t):this._collectFull(t):this._collectPlain(t)}_collectPlain(t){const e="</"+this._tagName;for(;t.canRead();)if("<"===t.readChAt(0)){if(this._peekMatch(t,e)){let s=e.length,r=!1;for(;;){const e=t.readChAt(s);if(">"===e){r=!0;break}if(" "!==e&&"\t"!==e&&"\n"!==e&&"\r"!==e)break;s++}if(r){for(this._skipChars(t,e.length);t.canRead()&&">"!==t.readCh(););return this._finish()}}this._content+=t.readCh()}else this._content+=t.readCh();throw new R(`Unclosed stop node <${this._tagName}> — unexpected end of input`,V.UNEXPECTED_END)}_collectDepthOnly(t){for(;this._depth>0;){if(!t.canRead())throw new R(`Unclosed stop node <${this._tagName}> — unexpected end of input`,V.UNEXPECTED_END);if("<"!==t.readChAt(0)){this._content+=t.readCh();continue}if(t.readCh(),!t.canRead())throw new R(`Unclosed stop node <${this._tagName}> — unexpected end after '<'`,V.UNEXPECTED_END);if("/"===t.readChAt(0)){t.readCh();const e=this._readTagName(t),s=this._readToAngleClose(t);if(e===this._tagName&&(this._depth--,0===this._depth))return this._finish();this._content+="</"+e+s;continue}const e=this._readTagName(t);this._content+="<"+e;const{selfClosing:s,attrText:r}=this._readTagTail(t);this._content+=r,s||e!==this._tagName||this._depth++}throw new R(`Unclosed stop node <${this._tagName}> — unexpected end of input`,V.UNEXPECTED_END)}_collectEnclosureOnly(t){for(;t.canRead();){const e=this._matchEnclosureOpen(t);if(-1!==e){const s=this._enclosures[e];this._skipChars(t,s.open.length),this._content+=s.open;const r=this._readUpto(t,s.close);this._content+=r+s.close;continue}if("<"!==t.readChAt(0)){this._content+=t.readCh();continue}const s="</"+this._tagName;if(this._peekMatch(t,s)){let e=s.length,r=!1;for(;;){const s=t.readChAt(e);if(">"===s){r=!0;break}if(" "!==s&&"\t"!==s&&"\n"!==s&&"\r"!==s)break;e++}if(r){for(this._skipChars(t,s.length);t.canRead()&&">"!==t.readCh(););return this._finish()}}this._content+=t.readCh()}throw new R(`Unclosed stop node <${this._tagName}> — unexpected end of input`,V.UNEXPECTED_END)}_collectFull(t){for(;this._depth>0;){if(!t.canRead())throw new R(`Unclosed stop node <${this._tagName}> — unexpected end of input`,V.UNEXPECTED_END);const e=this._matchEnclosureOpen(t);if(-1!==e){const s=this._enclosures[e];this._skipChars(t,s.open.length),this._content+=s.open;const r=this._readUpto(t,s.close);this._content+=r+s.close;continue}if("<"!==t.readChAt(0)){this._content+=t.readCh();continue}if(t.readCh(),!t.canRead())throw new R(`Unclosed stop node <${this._tagName}> — unexpected end after '<'`,V.UNEXPECTED_END);if("/"===t.readChAt(0)){t.readCh();const e=this._readTagName(t),s=this._readToAngleClose(t);if(e===this._tagName&&(this._depth--,0===this._depth))return this._finish();this._content+="</"+e+s;continue}const s=this._readTagName(t);this._content+="<"+s;const{selfClosing:r,attrText:n}=this._readTagTail(t);this._content+=n,r||s!==this._tagName||this._depth++}throw new R(`Unclosed stop node <${this._tagName}> — unexpected end of input`,V.UNEXPECTED_END)}_finish(){const t=this._content;return this._active=!1,this._content="",this._depth=1,t}_matchEnclosureOpen(t){const e=this._enclosures.length;for(let s=0;s<e;s++)if(this._peekMatch(t,this._enclosures[s].open))return s;return-1}_readUpto(t,e){const s=e[0],r=e.length,n=t.startIndex;let i=0;for(;t.canRead();){if(t.readChAt(0)===s&&this._peekMatch(t,e)){const e=t.readStr(i,n);return this._skipChars(t,r),e}t.readCh(),i++}throw new R(`Unclosed stop node <${this._tagName}> — unexpected end looking for '${e}'`,V.UNEXPECTED_END)}_peekMatch(t,e){const s=e.length;for(let r=0;r<s;r++)if(t.readChAt(r)!==e[r])return!1;return!0}_skipChars(t,e){for(let s=0;s<e;s++)t.readCh()}_readTagName(t){let e="";for(;t.canRead();){const s=t.readChAt(0);if(">"===s||"/"===s||" "===s||"\t"===s||"\n"===s||"\r"===s)break;e+=t.readCh()}return e}_readTagTail(t){const e=t.startIndex;let s=0,r=!1,n=!1;for(;t.canRead();){const i=t.readCh();if(s++,"'"!==i||n)if('"'!==i||r){if(!r&&!n){if(">"===i)return{selfClosing:!1,attrText:t.readStr(s,e)};if("/"===i&&t.canRead()&&">"===t.readChAt(0))return t.readCh(),s++,{selfClosing:!0,attrText:t.readStr(s,e)}}}else n=!n;else r=!r}throw new R(`Unclosed stop node <${this._tagName}> — unexpected end inside tag`,V.UNEXPECTED_END)}_readToAngleClose(t){const e=t.startIndex;let s=0;for(;t.canRead();){const r=t.readCh();if(s++,">"===r)return t.readStr(s,e);if(" "!==r&&"\t"!==r&&"\n"!==r&&"\r"!==r)throw new R(`Malformed closing tag for </${this._tagName}>`,V.UNEXPECTED_END)}throw new R(`Unclosed stop node <${this._tagName}> — unexpected end looking for '>'`,V.UNEXPECTED_END)}}class mt{constructor(t){this._matcher=t}get separator(){return this._matcher.separator}getCurrentTag(){const t=this._matcher.path;return t.length>0?t[t.length-1].tag:void 0}getCurrentNamespace(){const t=this._matcher.path;return t.length>0?t[t.length-1].namespace:void 0}getAttrValue(t){const e=this._matcher.path;if(0!==e.length)return e[e.length-1].values?.[t]}hasAttr(t){const e=this._matcher.path;if(0===e.length)return!1;const s=e[e.length-1];return void 0!==s.values&&t in s.values}getPosition(){const t=this._matcher.path;return 0===t.length?-1:t[t.length-1].position??0}getCounter(){const t=this._matcher.path;return 0===t.length?-1:t[t.length-1].counter??0}getIndex(){return this.getPosition()}getDepth(){return this._matcher.path.length}toString(t,e=!0){return this._matcher.toString(t,e)}toArray(){return this._matcher.path.map(t=>t.tag)}matches(t){return this._matcher.matches(t)}matchesAny(t){return t.matchesAny(this._matcher)}}class xt{constructor(t={}){this.separator=t.separator||".",this.path=[],this.siblingStacks=[],this._pathStringCache=null,this._view=new mt(this)}push(t,e=null,s=null){this._pathStringCache=null,this.path.length>0&&(this.path[this.path.length-1].values=void 0);const r=this.path.length;this.siblingStacks[r]||(this.siblingStacks[r]=new Map);const n=this.siblingStacks[r],i=s?`${s}:${t}`:t,o=n.get(i)||0;let a=0;for(const t of n.values())a+=t;n.set(i,o+1);const h={tag:t,position:a,counter:o};null!=s&&(h.namespace=s),null!=e&&(h.values=e),this.path.push(h)}pop(){if(0===this.path.length)return;this._pathStringCache=null;const t=this.path.pop();return this.siblingStacks.length>this.path.length+1&&(this.siblingStacks.length=this.path.length+1),t}updateCurrent(t){if(this.path.length>0){const e=this.path[this.path.length-1];null!=t&&(e.values=t)}}getCurrentTag(){return this.path.length>0?this.path[this.path.length-1].tag:void 0}getCurrentNamespace(){return this.path.length>0?this.path[this.path.length-1].namespace:void 0}getAttrValue(t){if(0!==this.path.length)return this.path[this.path.length-1].values?.[t]}hasAttr(t){if(0===this.path.length)return!1;const e=this.path[this.path.length-1];return void 0!==e.values&&t in e.values}getPosition(){return 0===this.path.length?-1:this.path[this.path.length-1].position??0}getCounter(){return 0===this.path.length?-1:this.path[this.path.length-1].counter??0}getIndex(){return this.getPosition()}getDepth(){return this.path.length}toString(t,e=!0){const s=t||this.separator;if(s===this.separator&&!0===e){if(null!==this._pathStringCache)return this._pathStringCache;const t=this.path.map(t=>t.namespace?`${t.namespace}:${t.tag}`:t.tag).join(s);return this._pathStringCache=t,t}return this.path.map(t=>e&&t.namespace?`${t.namespace}:${t.tag}`:t.tag).join(s)}toArray(){return this.path.map(t=>t.tag)}reset(){this._pathStringCache=null,this.path=[],this.siblingStacks=[]}matches(t){const e=t.segments;return 0!==e.length&&(t.hasDeepWildcard()?this._matchWithDeepWildcard(e):this._matchSimple(e))}_matchSimple(t){if(this.path.length!==t.length)return!1;for(let e=0;e<t.length;e++)if(!this._matchSegment(t[e],this.path[e],e===this.path.length-1))return!1;return!0}_matchWithDeepWildcard(t){let e=this.path.length-1,s=t.length-1;for(;s>=0&&e>=0;){const r=t[s];if("deep-wildcard"===r.type){if(s--,s<0)return!0;const r=t[s];let n=!1;for(let t=e;t>=0;t--)if(this._matchSegment(r,this.path[t],t===this.path.length-1)){e=t-1,s--,n=!0;break}if(!n)return!1}else{if(!this._matchSegment(r,this.path[e],e===this.path.length-1))return!1;e--,s--}}return s<0}_matchSegment(t,e,s){if("*"!==t.tag&&t.tag!==e.tag)return!1;if(void 0!==t.namespace&&"*"!==t.namespace&&t.namespace!==e.namespace)return!1;if(void 0!==t.attrName){if(!s)return!1;if(!e.values||!(t.attrName in e.values))return!1;if(void 0!==t.attrValue&&String(e.values[t.attrName])!==String(t.attrValue))return!1}if(void 0!==t.position){if(!s)return!1;const r=e.counter??0;if("first"===t.position&&0!==r)return!1;if("odd"===t.position&&r%2!=1)return!1;if("even"===t.position&&r%2!=0)return!1;if("nth"===t.position&&r!==t.positionValue)return!1}return!0}matchesAny(t){return t.matchesAny(this)}snapshot(){return{path:this.path.map(t=>({...t})),siblingStacks:this.siblingStacks.map(t=>new Map(t))}}restore(t){this._pathStringCache=null,this.path=t.path.map(t=>({...t})),this.siblingStacks=t.siblingStacks.map(t=>new Map(t))}readOnly(){return this._view}}function Tt(t){const e=t.source;if(Ct(e),!e.canRead())throw new R("Unexpected end of source reading entity name",V.UNEXPECTED_END,{line:e.line,col:e.cols,index:e.startIndex});const s=e.startIndex;let r=0;for(;e.canRead();){const t=e.readCh();if(" "===t||"\t"===t||"\n"===t||"\r"===t||'"'===t||"'"===t)break;r++}const n=e.readStr(r,s);if(!e.canRead())throw new R(`Unexpected end of source reading entity name "${n}"`,V.UNEXPECTED_END,{line:e.line,col:e.cols,index:e.startIndex});if(St(n,t.xmlVersion),Ct(e),!e.canRead())throw new R(`Unexpected end of source after entity name "${n}"`,V.UNEXPECTED_END,{line:e.line,col:e.cols,index:e.startIndex});if(e.canRead(5)&&"SYSTEM"===e.readStr(6).toUpperCase())throw new R("External entities are not supported",V.INVALID_TAG,{line:e.line,col:e.cols,index:e.startIndex});if("%"===e.readStr(1))throw new R("Parameter entities are not supported",V.INVALID_TAG,{line:e.line,col:e.cols,index:e.startIndex});if(!e.canRead())throw new R(`Unexpected end of source reading entity value for "${n}"`,V.UNEXPECTED_END,{line:e.line,col:e.cols,index:e.startIndex});const[i]=At(e,"entity"),o=t.options?.doctypeOptions;if(o?.maxEntitySize&&i.length>o.maxEntitySize)throw new R(`Entity "${n}" size (${i.length}) exceeds maximum allowed size (${o.maxEntitySize})`,V.ENTITY_MAX_SIZE,{line:e.line,col:e.cols,index:e.startIndex});return e.readUptoChar(">"),[n,i]}function Nt(t){const e=t.source;if(Ct(e),!e.canRead())throw new R("Unexpected end of source reading ELEMENT name",V.UNEXPECTED_END,{line:e.line,col:e.cols,index:e.startIndex});const s=e.startIndex;let r=0;for(;e.canRead();){const t=e.readCh();if(" "===t||"\t"===t||"\n"===t||"\r"===t)break;r++}const n=e.readStr(r,s);if(!e.canRead())throw new R(`Unexpected end of source after ELEMENT name "${n}"`,V.UNEXPECTED_END,{line:e.line,col:e.cols,index:e.startIndex});if(!ut(n,t.xmlVersion))throw new R(`Invalid element name: "${n}"`,V.INVALID_TAG,{line:e.line,col:e.cols,index:e.startIndex});if(Ct(e),!e.canRead())throw new R("Unexpected end of source reading ELEMENT content model",V.UNEXPECTED_END,{line:e.line,col:e.cols,index:e.startIndex});let i=e.readStr(1);if("E"===i){if(!e.canRead(4))throw new R("Unexpected end of source reading ELEMENT content model keyword",V.UNEXPECTED_END,{line:e.line,col:e.cols,index:e.startIndex});if("EMPTY"!==e.readStr(5))return e.readUptoChar(">"),{elementName:n,contentModel:""};e.updateBufferBoundary(5)}else if("A"===i){if(!e.canRead(2))throw new R("Unexpected end of source reading ELEMENT content model keyword",V.UNEXPECTED_END,{line:e.line,col:e.cols,index:e.startIndex});if("ANY"!==e.readStr(3))return e.readUptoChar(">"),{elementName:n,contentModel:""};e.updateBufferBoundary(3)}else"("===i&&(e.updateBufferBoundary(1),e.readUptoChar(")"));return e.readUptoChar(">"),{elementName:n}}function It(t){t.source.readUptoChar(">")}function wt(t){const e=t.source;if(Ct(e),!e.canRead())throw new R("Unexpected end of source reading NOTATION name",V.UNEXPECTED_END,{line:e.line,col:e.cols,index:e.startIndex});const s=e.startIndex;let r=0;for(;e.canRead();){const t=e.readCh();if(" "===t||"\t"===t||"\n"===t||"\r"===t)break;r++}const n=e.readStr(r,s);if(!e.canRead())throw new R(`Unexpected end of source after NOTATION name "${n}"`,V.UNEXPECTED_END,{line:e.line,col:e.cols,index:e.startIndex});if(St(n,t.xmlVersion),Ct(e),!e.canRead(5))throw new R("Unexpected end of source reading NOTATION identifier type",V.UNEXPECTED_END,{line:e.line,col:e.cols,index:e.startIndex});let i=e.readStr(6).toUpperCase();if("SYSTEM"===i)e.updateBufferBoundary(6),Ct(e),At(e,"systemIdentifier");else{if("PUBLIC"!==i)throw new R(`Expected SYSTEM or PUBLIC in NOTATION, found "${i}"`,V.INVALID_TAG,{line:e.line,col:e.cols,index:e.startIndex});{if(e.updateBufferBoundary(6),Ct(e),At(e,"publicIdentifier"),Ct(e),!e.canRead())throw new R("Unexpected end of source after NOTATION PUBLIC identifier",V.UNEXPECTED_END,{line:e.line,col:e.cols,index:e.startIndex});let t=e.readStr(1);'"'!==t&&"'"!==t||At(e,"systemIdentifier")}}e.readUptoChar(">")}function At(t,e){if(!t.canRead())throw new R(`Unexpected end of source reading ${e} opening quote`,V.UNEXPECTED_END,{line:t.line,col:t.cols,index:t.startIndex});let s=t.readStr(1);if('"'!==s&&"'"!==s)throw new R(`Expected quoted string for ${e}, found "${s}"`,V.INVALID_TAG,{line:t.line,col:t.cols,index:t.startIndex});return t.updateBufferBoundary(1),[t.readUptoChar(s)]}function Ct(t){for(;t.canRead();){const e=t.readChAt(0);if(" "!==e&&"\t"!==e&&"\n"!==e&&"\r"!==e)break;t.updateBufferBoundary(1)}}function St(t,e){if(ut(t,e))return t;throw new R(`Invalid entity name "${t}"`,V.ENTITY_INVALID_KEY,{})}const yt=Object.freeze({UNCLOSED_EOF:"unclosed-eof",MISMATCHED_CLOSE:"mismatched-close",PHANTOM_CLOSE:"phantom-close",PARTIAL_TAG:"partial-tag"});class Dt{constructor(t){this.onEof=t.onEof||"throw",this.onMismatch=t.onMismatch||"throw",this.collectErrors=t.collectErrors||!1,this.errors=[]}handleEof(t){if("throw"===this.onEof)throw new R("Unexpected data in the end of document",V.UNEXPECTED_TRAILING_DATA);const{addTextNode:e,popTag:s}=t;let r=t.currentTagDetail;for(;r&&!r.root;)this._recordError(yt.UNCLOSED_EOF,{tag:r.name,expected:null,line:r.line,col:r.col,index:r.index}),e(),s(),r=t.currentTagDetail}handleMismatch(t,e){const{tagsStack:s,currentTagDetail:r,source:n,addTextNode:i}=e;if("throw"===this.onMismatch)throw new R(`Unexpected closing tag '${t}' expecting '${r.name}'`,V.MISMATCHED_CLOSE_TAG,{line:n?n.line:void 0,col:n?n.cols:void 0,index:n?n.startIndex:void 0});if("discard"===this.onMismatch)return this._recordError(yt.MISMATCHED_CLOSE,{tag:t,expected:r.name,line:n?n.line:null,col:n?n.cols:null,index:n?n.startIndex:null}),{action:"discard"};const o=[...s,r];let a=-1;const h=o.length;for(let e=h-1;e>=0;e--)if(o[e].name===t){a=e;break}if(-1===a)return this._recordError(yt.PHANTOM_CLOSE,{tag:t,expected:r.name,line:n?n.line:null,col:n?n.cols:null,index:n?n.startIndex:null}),{action:"discard"};const c=h-1-a;for(let s=0;s<c;s++){const r=o[h-1-s];this._recordError(yt.MISMATCHED_CLOSE,{tag:r.name,expected:t,line:r.line,col:r.col,index:r.index}),i(),e.popTag()}return e.currentTagDetail=o[a],{action:"close-matched"}}handlePartialTag(t,e){this._recordError(yt.PARTIAL_TAG,{tag:bt(t),expected:null,line:e.source?e.source.line:null,col:e.source?e.source.cols:null,index:e.source?e.source.startIndex:null}),e.tagTextData="",this.handleEof(e)}getErrors(){return this.errors.slice()}reset(){this.errors=[]}_recordError(t,e){this.collectErrors&&this.errors.push({type:t,...e})}}function bt(t){if(!t)return null;const e=("string"==typeof t.message?t.message:String(t)).match(/[Rr]eading closing tag '<\/([^']*)/);return e&&e[1]||null}class Pt{constructor(t,e=0,s=0,r=0){this.name=t,this.line=e,this.col=s,this.index=r}}class Ut{constructor(t){this.options=t,this.currentTagDetail=null,this.tagTextData="",this.tagsStack=[],this.matcher=new xt,this.readonlyMatcher=this.matcher.readOnly(),this.autoCloseHandler=t.autoClose?new Dt(t.autoClose):null,this._unpairedSet=new Set(this.options.tags.unpaired),this.stopNodeExpressionsSet=this.options.tags.stopNodesSet??new $,this.skipTagExpressionsSet=this.options.skip.tagsSet??new $,this._exitIf="function"==typeof t.exitIf?t.exitIf:null}initializeParser(){this.tagTextData="",this.tagsStack=[],this._stopNodeProcessor=null,this._exitIfTriggered=!1,this.xmlVersion="1.0",this.matcher||(this.matcher=new xt,this.readonlyMatcher=this.matcher.readOnly()),this.outputBuilder=this._createOutputBuilder(),this.root={root:!0,name:""},this.currentTagDetail=this.root}_createOutputBuilder(){return this.options.OutputBuilder.getInstance(this.options,this.readonlyMatcher)}wasExited(){return!0===this._exitIfTriggered}parse(t){return this.source=new tt(t),this.initializeParser(),this._parseAndFinalize(),this.outputBuilder.getOutput()}parseBytesArr(t){return this.source=new et(t),this.initializeParser(),this._parseAndFinalize(),this.outputBuilder.getOutput()}parseXml(){for(;this.source.canRead()&&!this._exitIfTriggered;){this.source.markTokenStart(0);const t=this.source.readCh();if(void 0===t||""===t)break;if("<"===t){const t=this.source.readChAt(0);if(""===t)throw new R("Unexpected end of source after '<'",V.UNEXPECTED_END,{line:this.source.line,col:this.source.cols,index:this.source.startIndex});"!"===t||"?"===t?(this.source.updateBufferBoundary(),this.addTextNode(),this.readSpecialTag(t)):"/"===t?(this.source.updateBufferBoundary(),this.readClosingTag()):this.readOpeningTag()}else{let e=0;for(;;){const t=this.source.readChAt(e);if("<"===t||void 0===t||""===t)break;e++}e>0?(this.tagTextData+=t+this.source.readStr(e,this.source.startIndex),this.source.updateBufferBoundary(e)):this.tagTextData+=t}}}finalizeXml(){if(this._exitIfTriggered)return;const t=this.tagsStack.length>0||this.currentTagDetail&&!this.currentTagDetail.root,e=!t&&void 0!==this.tagTextData&&this.tagTextData.trimEnd().length>0;if(t||e){if(!this.autoCloseHandler||!t||e)throw new R("Unexpected data in the end of document",V.UNEXPECTED_TRAILING_DATA);this.autoCloseHandler.handleEof(this._parserState())}}_parseAndFinalize(){let t=null;this.autoCloseHandler&&this.autoCloseHandler.reset();try{this.parseXml()}catch(e){if(!this.autoCloseHandler||!function(t){return t instanceof R?t.code===V.UNEXPECTED_END:t.message.startsWith("Unexpected end of source")||t.message.startsWith("Unexpected closing of source")}(e))throw e;t=e}t?this.autoCloseHandler.handlePartialTag(t,this._parserState()):this.finalizeXml()}readClosingTag(){const t=this.processTagName(function(t){t.markTokenStart(1);let e=0;const s=t.startIndex;for(;t.canRead();){if(">"===t.readCh()){const r=t.readStr(e,s);return r?r.trimEnd():""}e++}const r=t.readStr(e,s);throw t.updateBufferBoundary(e),new R(`Unexpected end of source reading closing tag '</${r}'`,V.UNEXPECTED_END)}(this.source));if(this.isUnpaired(t)||this.isStopNode())throw new R(`Unexpected closing tag '${t}'`,V.UNEXPECTED_CLOSE_TAG,{line:this.source.line,col:this.source.cols,index:this.source.startIndex});if(t!==this.currentTagDetail.name){if(!this.autoCloseHandler)throw new R(`Unexpected closing tag '${t}' expecting '${this.currentTagDetail.name}'`,V.MISMATCHED_CLOSE_TAG,{line:this.source.line,col:this.source.cols,index:this.source.startIndex});if("discard"===this.autoCloseHandler.handleMismatch(t,this._parserState()).action)return}this.currentTagDetail.root||this.addTextNode(),this.popTag()}readOpeningTag(){const t=this.options;if(this.addTextNode(),this._stopNodeProcessor&&this._stopNodeProcessor.isActive()){const{tagDetail:t,isSkip:e}=this._stopNodeProcessorMeta;this._stopNodeProcessor.resumeAfterOpenTag(),ft(this);const s=this._stopNodeProcessor.collect(this.source);return e||(this.outputBuilder.addElement(t,this.readonlyMatcher),this.outputBuilder.onStopNode?.(t,s,this.readonlyMatcher),this.outputBuilder.addValue(s,this.readonlyMatcher),this.outputBuilder.closeElement(this.readonlyMatcher)),this.matcher.pop(),this._stopNodeProcessor=null,void(this._stopNodeProcessorMeta=null)}let e=ft(this);const s=this.processTagName(e.tagName),r=new Pt(s,this.source.line,this.source.cols,this.source.startIndex),n=e.tagName.indexOf(":"),i=-1!==n?e.tagName.slice(0,n):void 0,o=void 0!==i?e.tagName.slice(n+1):s,a=t.limits?.maxNestedTags;if(null!=a){const t=this.tagsStack.length+1;if(t>a)throw new R(`Nesting depth ${t} exceeds limit of ${a} (tag: '${s}')`,V.LIMIT_MAX_NESTED_TAGS,{line:r.line,col:r.col,index:r.index})}let h={},c=0;e.rawAttributes&&(h=e.rawAttributes,c=e.rawAttributesLen),this.matcher.push(o,{},i),c>0&&this.matcher.updateCurrent(h);const l=this.isStopNode(),u=l?null:this.isSkipTag();if(t.skip.attributes||u||rt(e._attrsExp,this),this.isUnpaired(s))this.outputBuilder.addElement(r,this.readonlyMatcher),this.outputBuilder.closeElement(this.readonlyMatcher),this.matcher.pop();else if(e.selfClosing)u||(this.outputBuilder.addElement(r,this.readonlyMatcher),this.outputBuilder.closeElement(this.readonlyMatcher)),this.matcher.pop();else if(l){this._stopNodeProcessor=new Et(e.tagName,{nested:l.nested,skipEnclosures:l.skipEnclosures}),this._stopNodeProcessorMeta={tagDetail:r,isSkip:!1},this._stopNodeProcessor.activate();const t=this._stopNodeProcessor.collect(this.source);this.outputBuilder.addElement(r,this.readonlyMatcher),this.outputBuilder.onStopNode?.(r,t,this.readonlyMatcher),this.outputBuilder.addValue(t,this.readonlyMatcher),this.outputBuilder.closeElement(this.readonlyMatcher),this.matcher.pop(),this._stopNodeProcessor=null,this._stopNodeProcessorMeta=null}else if(u)this._stopNodeProcessor=new Et(e.tagName,{nested:u.nested,skipEnclosures:u.skipEnclosures}),this._stopNodeProcessorMeta={tagDetail:r,isSkip:!0},this._stopNodeProcessor.activate(),this._stopNodeProcessor.collect(this.source),this.matcher.pop(),this._stopNodeProcessor=null,this._stopNodeProcessorMeta=null;else if(this._exitIf&&this._exitIf(this.readonlyMatcher)){const t=this.tagsStack.length;for(this.matcher.pop();this.currentTagDetail&&!this.currentTagDetail.root;)this.addTextNode(),this.popTag();"function"==typeof this.outputBuilder.onExit&&this.outputBuilder.onExit({tagDetail:r,matcher:this.readonlyMatcher,depth:t}),this._exitIfTriggered=!0}else this.pushTag(r)}pushTag(t){this.tagsStack.push(this.currentTagDetail),this.outputBuilder.addElement(t,this.readonlyMatcher),this.currentTagDetail=t}popTag(){this.outputBuilder.closeElement(this.readonlyMatcher),this.matcher.pop(),this.currentTagDetail=this.tagsStack.pop()}readSpecialTag(t){if("!"===t){let t=this.source.readCh();if(null==t)throw new R("Unexpected end of source after '<!'",V.UNEXPECTED_END,{line:this.source.line,col:this.source.cols,index:this.source.startIndex});if("-"===t)!function(t){if(t.source.markTokenStart(1),!t.source.canRead())throw new R("Unexpected end of source reading comment",V.UNEXPECTED_END,{line:t.source.line,col:t.source.cols,index:t.source.startIndex});if("-"!==t.source.readCh())throw new R(`Invalid comment expression at ${t.source.line}:${t.source.cols}`,V.INVALID_TAG,{line:t.source.line,col:t.source.cols,index:t.source.startIndex});let e=t.source.readUpto("--\x3e");t.outputBuilder.addComment(e)}(this);else if("["===t)!function(t){if(t.source.markTokenStart(1),!t.source.canRead(5))throw new R("Unexpected end of source reading CDATA preamble",V.UNEXPECTED_END,{line:t.source.line,col:t.source.cols,index:t.source.startIndex});let e=t.source.readStr(6);if(t.source.updateBufferBoundary(6),"CDATA["!==e)throw new R(`Invalid CDATA expression at ${t.source.line}:${t.source.cols}`,V.INVALID_TAG,{line:t.source.line,col:t.source.cols,index:t.source.startIndex});let s=t.source.readUpto("]]>");t.outputBuilder.addLiteral(s)}(this);else if("D"===t){const t=function(t){if(t.source.markTokenStart(1),!t.source.canRead(5))throw new R("Unexpected end of source reading DOCTYPE preamble",V.UNEXPECTED_END,{line:t.source.line,col:t.source.cols,index:t.source.startIndex});let e=t.source.readStr(6);if(t.source.updateBufferBoundary(6),"OCTYPE"!==e)throw new R(`Invalid DOCTYPE expression at ${t.source.line}:${t.source.cols}`,V.INVALID_TAG,{line:t.source.line,col:t.source.cols,index:t.source.startIndex});const s=Object.create(null);let r=0,n=!1,i=!1;for(;t.source.canRead();){const e=t.source.startIndex;let o=t.source.readCh();if("<"===o&&n&&!i)try{if(!t.source.canRead())throw new R("Unexpected end of source reading DOCTYPE sub-tag",V.UNEXPECTED_END,{line:t.source.line,col:t.source.cols,index:t.source.startIndex});let e=t.source.readStr(1);if(t.source.updateBufferBoundary(1),"!"!==e)throw new R(`Invalid DOCTYPE body tag starting with "<${e}"`,V.INVALID_TAG,{line:t.source.line,col:t.source.cols,index:t.source.startIndex});if(!t.source.canRead())throw new R("Unexpected end of source reading DOCTYPE sub-tag type",V.UNEXPECTED_END,{line:t.source.line,col:t.source.cols,index:t.source.startIndex});let n=t.source.readStr(1);if(t.source.updateBufferBoundary(1),"-"===n){if(!t.source.canRead())throw new R("Unexpected end of source reading DOCTYPE comment",V.UNEXPECTED_END,{line:t.source.line,col:t.source.cols,index:t.source.startIndex});let e=t.source.readStr(1);if(t.source.updateBufferBoundary(1),"-"!==e)throw new R("Invalid comment in DOCTYPE",V.INVALID_TAG,{line:t.source.line,col:t.source.cols,index:t.source.startIndex});t.source.readUpto("--\x3e")}else if("E"===n){if(!t.source.canRead())throw new R("Unexpected end of source reading DOCTYPE E-type sub-tag",V.UNEXPECTED_END,{line:t.source.line,col:t.source.cols,index:t.source.startIndex});let e=t.source.readStr(1);if(t.source.updateBufferBoundary(1),"N"===e){if(!t.source.canRead(3))throw new R("Unexpected end of source reading DOCTYPE ENTITY keyword",V.UNEXPECTED_END,{line:t.source.line,col:t.source.cols,index:t.source.startIndex});let e=t.source.readStr(4);if(t.source.updateBufferBoundary(4),"TITY"!==e)throw new R("Invalid DOCTYPE ENTITY expression",V.INVALID_TAG,{line:t.source.line,col:t.source.cols,index:t.source.startIndex});const[n,i]=Tt(t);if(-1===i.indexOf("&")){const e=t.options?.doctypeOptions;if(e?.maxEntityCount&&r>=e.maxEntityCount)throw new R(`Entity count (${r+1}) exceeds maximum allowed (${e.maxEntityCount})`,V.ENTITY_MAX_COUNT,{line:t.source.line,col:t.source.cols,index:t.source.startIndex});const o=n.replace(/[.\-+*:]/g,"\\$&");s[n]={regx:RegExp(`&${o};`,"g"),val:i},r++}}else{if("L"!==e)throw new R(`Invalid DOCTYPE sub-tag "<!E${e}"`,V.INVALID_TAG,{line:t.source.line,col:t.source.cols,index:t.source.startIndex});{if(!t.source.canRead(4))throw new R("Unexpected end of source reading DOCTYPE ELEMENT keyword",V.UNEXPECTED_END,{line:t.source.line,col:t.source.cols,index:t.source.startIndex});let e=t.source.readStr(5);if(t.source.updateBufferBoundary(5),"EMENT"!==e)throw new R("Invalid DOCTYPE ELEMENT expression",V.INVALID_TAG,{line:t.source.line,col:t.source.cols,index:t.source.startIndex});Nt(t)}}}else if("A"===n){if(!t.source.canRead(5))throw new R("Unexpected end of source reading DOCTYPE ATTLIST keyword",V.UNEXPECTED_END,{line:t.source.line,col:t.source.cols,index:t.source.startIndex});let e=t.source.readStr(6);if(t.source.updateBufferBoundary(6),"TTLIST"!==e)throw new R("Invalid DOCTYPE ATTLIST expression",V.INVALID_TAG,{line:t.source.line,col:t.source.cols,index:t.source.startIndex});It(t)}else{if("N"!==n)throw new R(`Invalid DOCTYPE sub-tag "<!${n}"`,V.INVALID_TAG,{line:t.source.line,col:t.source.cols,index:t.source.startIndex});{if(!t.source.canRead(6))throw new R("Unexpected end of source reading DOCTYPE NOTATION keyword",V.UNEXPECTED_END,{line:t.source.line,col:t.source.cols,index:t.source.startIndex});let e=t.source.readStr(7);if(t.source.updateBufferBoundary(7),"OTATION"!==e)throw new R("Invalid DOCTYPE NOTATION expression",V.INVALID_TAG,{line:t.source.line,col:t.source.cols,index:t.source.startIndex});wt(t)}}}catch(s){throw s.code===V.UNEXPECTED_END&&(t.source.startIndex=e),s}else if("["===o)n=!0;else if("]"===o)i=!0;else if(">"===o&&(!n||i))return s}throw new R("Unclosed DOCTYPE",V.UNEXPECTED_END,{line:t.source.line,col:t.source.cols,index:t.source.startIndex})}(this);this.options.doctypeOptions.enabled&&t&&Object.keys(t).length>0&&this.outputBuilder.addInputEntities(t)}}else{if("?"!==t)throw new R(`Invalid tag '<${t}'`,V.INVALID_TAG,{line:this.source.line,col:this.source.cols,index:this.source.startIndex});!function(t){const e=t.options.skip;t.source.markTokenStart(1);let s=function(t){t.source.markTokenStart(1);let e,s=!1,r=!1,n=!1;for(e=0;t.source.canRead(e);e++){const i=t.source.readChAt(e),o=t.source.readChAt(e+1);if("'"!==i||r?'"'!==i||s||(r=!r):s=!s,!s&&!r&&"?"===i&&">"===o){n=!0;break}}if(!n)throw new R("Unexpected closing of source waiting for '?>'",V.UNEXPECTED_END);if(s||r)throw new R("Invalid attribute expression. Quote is not properly closed in PI tag expression",V.UNCLOSED_QUOTE);t.options.skip.attributes;const i=t.source.readStr(e);return t.source.updateBufferBoundary(e+2),pt(i,t)}(t);if(!s)throw new R("Invalid Pi Tag expression.",V.INVALID_TAG,{line:t.source.line,col:t.source.cols,index:t.source.startIndex});if("xml"===s.tagName){const e=s.rawAttributes?.version;t.xmlVersion="1.1"===e?1.1:1}e.attributes||rt(s._attrsExp,t),"xml"===s.tagName?e.declaration||t.outputBuilder.addDeclaration("?xml"):e.pi||t.outputBuilder.addInstruction("?"+s.tagName)}(this)}}addTextNode(){void 0!==this.tagTextData&&""!==this.tagTextData&&(this.tagTextData.trim().length>0&&this.outputBuilder.addValue(this.tagTextData,this.readonlyMatcher),this.tagTextData="")}processAttrName(t){const e=this.options;if(t=kt(t,e.skip.nsPrefix),!dt(t,this.xmlVersion))throw new R(`Invalid attribute name: ${t}`,V.INVALID_ATTRIBUTE_NAME);if(t=vt(t,e.onDangerousProperty),e.strictReservedNames&&t===e.attributes.groupBy)throw new R(`Restricted attribute name: ${t}`,V.SECURITY_RESTRICTED_NAME);return t}processTagName(t){const e=this.options,s=e.nameFor;if(t=vt(t=kt(t,e.skip.nsPrefix),e.onDangerousProperty),e.strictReservedNames&&(t===s.comment||t===s.cdata||t===s.text))throw new R(`Restricted tag name: ${t}`,V.SECURITY_RESTRICTED_NAME);return t}isUnpaired(t){return this._unpairedSet.has(t)}isStopNode(){if(0===this.stopNodeExpressionsSet.size)return null;const t=this.stopNodeExpressionsSet.findMatch(this.matcher);return t?t.data:null}isSkipTag(){if(0===this.skipTagExpressionsSet.size)return null;const t=this.skipTagExpressionsSet.findMatch(this.matcher);return t?t.data:null}_parserState(){const t=this;return{get tagsStack(){return t.tagsStack},get currentTagDetail(){return t.currentTagDetail},set currentTagDetail(e){t.currentTagDetail=e},get outputBuilder(){return t.outputBuilder},get readonlyMatcher(){return t.readonlyMatcher},get matcher(){return t.matcher},get source(){return t.source},get tagTextData(){return t.tagTextData},set tagTextData(e){t.tagTextData=e},addTextNode:t.addTextNode.bind(t),popTag:t.popTag.bind(t)}}}function kt(t,e){if(e){const e=t.split(":");if(2===e.length)return"xmlns"!==e[0]&&e[1];if(e.length>2)throw new R(`Multiple namespaces in name: ${t}`,V.MULTIPLE_NAMESPACES)}return t}function vt(t,e){if(G.includes(t))throw new R(`[SECURITY] Invalid name: "${t}" is a reserved JavaScript keyword that could cause prototype pollution`,V.SECURITY_PROTOTYPE_POLLUTION);return F.includes(t)?e(t):t}class Ot{constructor(t={}){this.line=1,this.cols=0,this.buffer="",this.startIndex=0,this.isComplete=!1,this.maxBufferSize=t.maxBufferSize||10485760,this.autoFlush=!1!==t.autoFlush,this.flushThreshold=t.flushThreshold||1024,this._marks=[-1,-1]}feed(t){const e="string"==typeof t?t:t.toString(),s=this.buffer.length-this.startIndex;if(s+e.length>this.maxBufferSize)throw new R(`Buffer size limit exceeded (${s+e.length} > ${this.maxBufferSize}). Increase feedable.maxBufferSize or reduce chunk size.`,V.INVALID_INPUT);this.buffer+=e}end(){this.isComplete=!0}canRead(t=0){return this.startIndex+t<this.buffer.length}markTokenStart(t=0){this._marks[t]=this.startIndex}rewindToMark(){this._marks[0]>=0&&(this.startIndex=this._marks[0]),this._marks[0]=-1,this._marks[1]=-1}clearMark(){this._marks[0]=-1,this._marks[1]=-1}readCh(){const t=this.buffer[this.startIndex++];return"\n"===t?(this.line++,this.cols=0):this.cols++,t}readChAt(t){return this.buffer[this.startIndex+t]}readStr(t,e){return void 0===e&&(e=this.startIndex),this.buffer.substring(e,e+t)}readUpto(t){const e=this.buffer.length,s=t.length;for(let r=this.startIndex;r<e;r++){let e=!0;for(let n=0;n<s;n++)if(this.buffer[r+n]!==t[n]){e=!1;break}if(e){const t=this.buffer.substring(this.startIndex,r);return this.startIndex=r+s,t}}throw new R(`Unexpected end of source reading '${t}'`,V.UNEXPECTED_END)}readUptoChar(t){const e=this.buffer.indexOf(t,this.startIndex);if(-1===e)throw new R(`Unexpected end of source reading '${t}'`,V.UNEXPECTED_END);const s=this.buffer.substring(this.startIndex,e);return this.startIndex=e+1,s}readUptoCloseTag(t){const e=this.buffer.length,s=t.length;let r=-1,n=0;for(let i=this.startIndex;i<e;i++){if(1===n){const t=this.buffer[i];if(" "===t||"\t"===t)continue;">"===t?n=2:(n=0,r=-1)}else{let e=!0;for(let r=0;r<s;r++)if(this.buffer[i+r]!==t[r]){e=!1;break}e&&(n=1,r=i,i+=s-1)}if(2===n){const t=this.buffer.substring(this.startIndex,r);return this.startIndex=i+1,t}}throw new R(`Unexpected end of source reading '${t}'`,V.UNEXPECTED_END)}updateBufferBoundary(t=1){this.startIndex+=t;const e=this._marks[0]>=0||this._marks[1]>=0;this.autoFlush&&this.startIndex>=this.flushThreshold&&!e&&this.flush()}flush(){let t=this.startIndex;for(const e of this._marks)e>=0&&e<t&&(t=e);if(t>0){this.buffer=this.buffer.substring(t);const e=this._marks.length;for(let s=0;s<e;s++)this._marks[s]>=0&&(this._marks[s]-=t);this.startIndex-=t}}}class Mt extends Ot{attachStream(t,e,s,r){t.on("data",t=>{try{this.feed("string"==typeof t?t:t.toString()),e(null)}catch(t){e(t)}}),t.on("error",r),t.on("end",()=>{try{this.end(),s()}catch(t){r(t)}})}}class Lt{constructor(t){this.options=Z(t),this._feedParser=null,this._feedSource=null,this._isFeeding=!1,this._pendingBytes=0,this._batchThreshold=this.options.feedable?.bufferSize}parse(t){if(t instanceof Buffer||ArrayBuffer.isView(t))t=t.toString();else if("string"!=typeof t){if(!t||"function"!=typeof t.toString)throw new R("XML data must be a string or Buffer.",V.INVALID_INPUT);t=t.toString()}const e=this._createParser(),s=e.parse(t);return this.wasExited=e.wasExited(),this._lastParseErrors=e.autoCloseHandler?.getErrors()??[],s}parseBytesArr(t){if(!(t instanceof Uint8Array||ArrayBuffer.isView(t)))throw new R("XML data must be a Uint8Array or ArrayBufferView.",V.INVALID_INPUT);t=Buffer.from(t);const e=this._createParser(),s=e.parseBytesArr(t);return this.wasExited=e.wasExited(),this._lastParseErrors=e.autoCloseHandler?.getErrors()??[],s}parseStream(t){if(null===(e=t)||"object"!=typeof e||"function"!=typeof e.read||"function"!=typeof e.on||"boolean"!=typeof e.readableEnded)throw new R("parseStream() requires a Node.js Readable stream.",V.INVALID_STREAM);var e;const s=new Mt(this.options.feedable),r=this._createParser();return r.source=s,r.initializeParser(),new Promise((e,n)=>{let i=!1;const o=e=>{i||(i=!0,t.destroy(),n(e))};s.attachStream(t,t=>{if(t)o(t);else try{r.parseXml()}catch(t){t.code===V.UNEXPECTED_END?s.rewindToMark():o(t)}},()=>{if(!i)try{r.finalizeXml(),this._lastParseErrors=r.autoCloseHandler?.getErrors()??[],i=!0,e(r.outputBuilder.getOutput())}catch(t){o(t)}},o)})}_runParse(){if(!this._feedParser)return;const t=this._feedSource.startIndex;try{this._feedParser.parseXml()}catch(t){if(t.code!==V.UNEXPECTED_END)throw t;this._feedSource.rewindToMark()}this._feedSource.startIndex>t?this._pendingBytes=0:this._batchThreshold=Math.min(2*this._batchThreshold,this.options.feedable.maxBufferSize)}feed(t){let e;if(this._isFeeding||this._initFeedSession(),"string"==typeof t)e=t;else if(Buffer.isBuffer(t))e=t.toString();else{if(!t?.toString)throw new R("feed() data must be a string or Buffer.",V.DATA_MUST_BE_STRING);e=t.toString()}return this._feedSource.feed(e),this._pendingBytes+=e.length,this._pendingBytes>=this._batchThreshold&&this._runParse(),this}end(){if(!this._isFeeding)throw new R("No data fed. Call feed() before end().",V.NOT_STREAMING);this._runParse();try{this._feedSource.end();let t=null;const e=this._feedParser.autoCloseHandler;e&&e.reset();try{this._feedParser.parseXml()}catch(s){if(s.code!==V.UNEXPECTED_END)throw s;if(!e)throw s;t=s}return t?e.handlePartialTag(t,this._feedParser._parserState()):this._feedParser.finalizeXml(),this._lastParseErrors=e?.getErrors()??[],this.wasExited=this._feedParser.wasExited(),this._feedParser.outputBuilder.getOutput()}finally{this._cleanupFeedSession()}}getParseErrors(){return this._lastParseErrors??[]}_createParser(){return new Ut(this.options)}_initFeedSession(){this._feedSource=new Ot(this.options.feedable),this._feedParser=this._createParser(),this._feedParser.source=this._feedSource,this._feedParser.initializeParser(),this._isFeeding=!0}_cleanupFeedSession(){this._feedParser=null,this._feedSource=null,this._isFeeding=!1}}module.exports=e})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nodable/flexible-xml-parser",
3
- "version": "1.1.1",
3
+ "version": "1.2.1",
4
4
  "description": "Fastest XML parser in pure JS with fully customizable ouput",
5
5
  "main": "./lib/fxp.cjs",
6
6
  "type": "module",
@@ -44,16 +44,17 @@
44
44
  "access": "public"
45
45
  },
46
46
  "dependencies": {
47
- "@nodable/base-output-builder": "^1.0.5",
48
- "@nodable/compact-builder": "^1.0.6",
47
+ "@nodable/base-output-builder": "^1.0.6",
48
+ "@nodable/compact-builder": "^1.0.9",
49
49
  "path-expression-matcher": "^1.5.0",
50
- "strnum": "^2.2.2"
50
+ "xml-naming": "^0.1.0"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@babel/core": "^7.29.0",
54
54
  "@babel/plugin-transform-runtime": "^7.29.0",
55
55
  "@babel/preset-env": "^7.29.2",
56
56
  "@babel/register": "^7.28.6",
57
+ "@byspec/xml": "^0.1.0",
57
58
  "@nodable/entities": "^2.1.0",
58
59
  "@types/node": "^20.19.37",
59
60
  "babel-loader": "^10.1.1",
@@ -64,6 +65,7 @@
64
65
  "webpack-cli": "^7.0.2"
65
66
  },
66
67
  "files": [
68
+ "lib/fxp.cjs",
67
69
  "lib/fxp.d.cts",
68
70
  "src",
69
71
  "CHANGELOG.md"
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
  import { ParseError, ErrorCode } from './ParseError.js';
3
+ import { isSpaceCode } from "./util.js"
3
4
 
4
5
  /**
5
6
  * AttributeProcessor — owns all attribute parsing logic.
@@ -21,9 +22,87 @@ import { ParseError, ErrorCode } from './ParseError.js';
21
22
  * complete attribute context when value parsers execute.
22
23
  */
23
24
 
24
- // Module-level regex. Stateless between calls because getAllMatches() always
25
- // resets lastIndex to 0 before iterating see getAllMatches() below.
26
- const attrsRegx = new RegExp('([^\\s=]+)\\s*(=\\s*([\'"])([\\s\\S]*?)\\3)?', 'gm');
25
+ // Module-level regex kept for reference only no longer called from this
26
+ // module. parseAttributes() below replaces it with an O(n) linear scanner
27
+ // that is immune to catastrophic backtracking and stack overflow.
28
+ // const attrsRegx = new RegExp('([^\\s=]+)\\s*(=\\s*([\'"])([\\s\\S]*?)\\3)?', 'gm');
29
+
30
+ /**
31
+ * Parse an attribute expression string into an array of match tuples.
32
+ *
33
+ * Each element has the same shape the old getAllMatches() returned so that
34
+ * callers are unchanged:
35
+ * [fullMatch, name, '=value' | undefined, quote | undefined, value | undefined]
36
+ *
37
+ * The implementation is a single O(n) pass over char codes with no regex and
38
+ * no recursion, making it safe for arbitrarily long attribute strings.
39
+ *
40
+ * State machine:
41
+ * SEEK_NAME — skipping whitespace looking for the start of an attr name
42
+ * IN_NAME — accumulating a name token until whitespace or '='
43
+ * SEEK_VALUE — saw name + optional whitespace, now expecting '=' or next name
44
+ * IN_VALUE — inside a quoted value, accumulating until the closing quote
45
+ *
46
+ * @param {string} attrStr
47
+ * @returns {Array} array of match tuples (see shape above)
48
+ */
49
+ function parseAttributes(attrStr) {
50
+ const results = [];
51
+ const len = attrStr.length;
52
+ let i = 0;
53
+
54
+ while (i < len) {
55
+ // Skip whitespace between attributes
56
+ while (i < len && isSpaceCode(attrStr.charCodeAt(i))) i++;
57
+ if (i >= len) break;
58
+
59
+ // Read name
60
+ const nameStart = i;
61
+ while (i < len && attrStr.charCodeAt(i) !== 61 && !isSpaceCode(attrStr.charCodeAt(i))) i++;
62
+ const name = attrStr.substring(nameStart, i);
63
+
64
+ // Skip whitespace before '='
65
+ while (i < len && isSpaceCode(attrStr.charCodeAt(i))) i++;
66
+
67
+ if (i >= len || attrStr.charCodeAt(i) !== 61) {
68
+ // Boolean attribute — no '='
69
+ const m = [name, name, undefined, undefined, undefined];
70
+ m.startIndex = nameStart;
71
+ results.push(m);
72
+ continue;
73
+ }
74
+
75
+ i++; // skip '='
76
+
77
+ // Skip whitespace after '='
78
+ while (i < len && isSpaceCode(attrStr.charCodeAt(i))) i++;
79
+
80
+ // Read quoted value
81
+ const quote = attrStr.charCodeAt(i);
82
+ if (quote === 34 || quote === 39) { // " or '
83
+ i++; // skip opening quote
84
+ const valueStart = i;
85
+ let value = '';
86
+ let segStart = i;
87
+ while (i < len && attrStr.charCodeAt(i) !== quote) {
88
+ const c = attrStr.charCodeAt(i);
89
+ if (c === 10 || c === 13) { // \n or \r → space per XML §3.3.3
90
+ value += attrStr.substring(segStart, i) + ' ';
91
+ segStart = i + 1;
92
+ }
93
+ i++;
94
+ }
95
+ value += attrStr.substring(segStart, i);
96
+ i++; // skip closing quote
97
+ const quoteChar = String.fromCharCode(quote);
98
+ const m = [name + '=' + quoteChar + value + quoteChar, name, '=' + quoteChar + value + quoteChar, quoteChar, value];
99
+ m.startIndex = nameStart;
100
+ results.push(m);
101
+ }
102
+ }
103
+
104
+ return results;
105
+ }
27
106
 
28
107
  /**
29
108
  * Pass 1: extract raw (unparsed) attribute values into rawAttributes.
@@ -33,9 +112,9 @@ const attrsRegx = new RegExp('([^\\s=]+)\\s*(=\\s*([\'"])([\\s\\S]*?)\\3)?', 'gm
33
112
  * @param {object} tagExp - tagExp object to populate rawAttributes (Object.create(null))
34
113
  */
35
114
  export function collectRawAttributes(attrStr, parser, tagExp) {
36
-
37
115
  if (!attrStr || attrStr.length === 0) return;
38
- const matches = getAllMatches(attrStr, attrsRegx);
116
+
117
+ const matches = parseAttributes(attrStr);
39
118
  const len = matches.length;
40
119
  let count = 0;
41
120
  for (let i = 0; i < len; i++) {
@@ -56,7 +135,7 @@ export function collectRawAttributes(attrStr, parser, tagExp) {
56
135
  */
57
136
  export function flushAttributes(attrStr, parser) {
58
137
  if (!attrStr || attrStr.length === 0) return;
59
- const matches = getAllMatches(attrStr, attrsRegx);
138
+ const matches = parseAttributes(attrStr);
60
139
  const len = matches.length;
61
140
 
62
141
  const maxAttrs = parser.options.limits?.maxAttributesPerTag;
@@ -78,30 +157,4 @@ export function flushAttributes(attrStr, parser) {
78
157
 
79
158
  parser.outputBuilder.addAttribute(attrName, attrVal, parser.readonlyMatcher);
80
159
  }
81
- }
82
-
83
- /**
84
- * Run the regex against the string and return all capture groups.
85
- * lastIndex is always reset to 0 before iterating so the module-level
86
- * stateful regex is safe to share across calls.
87
- *
88
- * @param {string} string
89
- * @param {RegExp} regex
90
- * @returns {Array}
91
- */
92
- function getAllMatches(string, regex) {
93
- regex.lastIndex = 0;
94
- const matches = [];
95
- let match = regex.exec(string);
96
- while (match) {
97
- const allmatches = [];
98
- allmatches.startIndex = regex.lastIndex - match[0].length;
99
- const len = match.length;
100
- for (let index = 0; index < len; index++) {
101
- allmatches.push(match[index]);
102
- }
103
- matches.push(allmatches);
104
- match = regex.exec(string);
105
- }
106
- return matches;
107
160
  }
@@ -1,5 +1,5 @@
1
- import { isName } from './util.js';
2
1
  import { ParseError, ErrorCode } from './ParseError.js';
2
+ import { name as isName, qName as isQName } from 'xml-naming';
3
3
 
4
4
  export function readDocType(parser) {
5
5
  parser.source.markTokenStart(1);
@@ -267,7 +267,7 @@ function readEntityExp(parser) {
267
267
  { line: source.line, col: source.cols, index: source.startIndex });
268
268
  }
269
269
 
270
- validateEntityName(entityName);
270
+ validateEntityName(entityName, parser.xmlVersion);
271
271
  skipSourceWhitespace(source);
272
272
 
273
273
  if (!source.canRead()) {
@@ -346,7 +346,7 @@ function readElementExp(parser) {
346
346
  { line: source.line, col: source.cols, index: source.startIndex });
347
347
  }
348
348
 
349
- if (!isName(elementName)) {
349
+ if (!isName(elementName, parser.xmlVersion)) {
350
350
  throw new ParseError(`Invalid element name: "${elementName}"`,
351
351
  ErrorCode.INVALID_TAG,
352
352
  { line: source.line, col: source.cols, index: source.startIndex });
@@ -434,7 +434,7 @@ function readNotationExp(parser) {
434
434
  { line: source.line, col: source.cols, index: source.startIndex });
435
435
  }
436
436
 
437
- validateEntityName(notationName);
437
+ validateEntityName(notationName, parser.xmlVersion);
438
438
  skipSourceWhitespace(source);
439
439
 
440
440
  // Need all 6 chars of "SYSTEM" / "PUBLIC" before we can classify
@@ -512,8 +512,8 @@ function skipSourceWhitespace(source) {
512
512
  }
513
513
  }
514
514
 
515
- function validateEntityName(name) {
516
- if (isName(name)) return name;
515
+ function validateEntityName(name, xmlVersion) {
516
+ if (isName(name, xmlVersion)) return name;
517
517
  throw new ParseError(
518
518
  `Invalid entity name "${name}"`,
519
519
  ErrorCode.ENTITY_INVALID_KEY,
@@ -132,6 +132,7 @@ export const defaultOptions = {
132
132
  maxBufferSize: 10 * 1024 * 1024,
133
133
  autoFlush: true,
134
134
  flushThreshold: 1024,
135
+ bufferSize: 256
135
136
  },
136
137
 
137
138
  // --- exitIf ---
package/src/XMLParser.js CHANGED
@@ -13,6 +13,10 @@ export default class XMLParser {
13
13
  this._feedParser = null;
14
14
  this._feedSource = null;
15
15
  this._isFeeding = false;
16
+
17
+ // ── Batching state ──────────────────────────────────
18
+ this._pendingBytes = 0;
19
+ this._batchThreshold = this.options.feedable?.bufferSize;
16
20
  }
17
21
 
18
22
  // ─── One-shot parse methods ───────────────────────────────────────────────
@@ -126,6 +130,37 @@ export default class XMLParser {
126
130
 
127
131
  // ─── Incremental feed()/end() API ────────────────────────────────────────
128
132
 
133
+ _runParse() {
134
+ if (!this._feedParser) return;
135
+
136
+ const beforePos = this._feedSource.startIndex; // bytes consumed so far
137
+
138
+ try {
139
+ this._feedParser.parseXml();
140
+ } catch (err) {
141
+ if (err.code === ErrorCode.UNEXPECTED_END) {
142
+ this._feedSource.rewindToMark();
143
+ } else {
144
+ throw err;
145
+ }
146
+ }
147
+
148
+ const afterPos = this._feedSource.startIndex;
149
+ const didAdvance = afterPos > beforePos;
150
+
151
+ if (didAdvance) {
152
+ // Real progress made — reset threshold normally
153
+ this._pendingBytes = 0;
154
+ } else {
155
+ // Parser is stuck mid-token — grow the threshold to avoid
156
+ // hammering parseXml() until significantly more data arrives
157
+ this._batchThreshold = Math.min(
158
+ this._batchThreshold * 2,
159
+ this.options.feedable.maxBufferSize
160
+ );
161
+ }
162
+ }
163
+
129
164
  /**
130
165
  * Feed an XML data chunk for incremental parsing.
131
166
  *
@@ -160,20 +195,12 @@ export default class XMLParser {
160
195
  }
161
196
 
162
197
  this._feedSource.feed(str);
198
+ this._pendingBytes += str.length;
163
199
 
164
- try {
165
- this._feedParser.parseXml();
166
- } catch (err) {
167
- if (err.code === ErrorCode.UNEXPECTED_END) {
168
- // Chunk boundary fell mid-token. Rewind to the token start so the
169
- // incomplete bytes are re-parsed when the next chunk arrives.
170
- this._feedSource.rewindToMark();
171
- } else {
172
- // Real parse error — clean up and propagate.
173
- this._cleanupFeedSession();
174
- throw err;
175
- }
200
+ if (this._pendingBytes >= this._batchThreshold) {
201
+ this._runParse();
176
202
  }
203
+ // Otherwise, delay parsing until next feed() or end()
177
204
 
178
205
  return this;
179
206
  }
@@ -201,6 +228,9 @@ export default class XMLParser {
201
228
  throw new ParseError('No data fed. Call feed() before end().', ErrorCode.NOT_STREAMING);
202
229
  }
203
230
 
231
+ // Force a final parse (any pending bytes are now processed)
232
+ this._runParse();
233
+
204
234
  try {
205
235
  // Mark the source as complete so readers know there is no more data.
206
236
  this._feedSource.end();
@@ -5,9 +5,10 @@ import { StopNodeProcessor } from './StopNodeProcessor.js';
5
5
  import { readComment, readCdata, readPiTag } from './XmlSpecialTagsReader.js';
6
6
  import { Expression, ExpressionSet, Matcher } from 'path-expression-matcher';
7
7
  import { readDocType } from './DocTypeReader.js';
8
- import { isName, DANGEROUS_PROPERTY_NAMES, criticalProperties } from './util.js';
8
+ import { DANGEROUS_PROPERTY_NAMES, criticalProperties } from './util.js';
9
9
  import AutoCloseHandler from './AutoCloseHandler.js';
10
10
  import { ParseError, ErrorCode } from './ParseError.js';
11
+ import { name as isName, qName as isQName } from 'xml-naming';
11
12
 
12
13
  class TagDetail {
13
14
  /**
@@ -60,6 +61,7 @@ export default class Xml2JsParser {
60
61
  this.tagsStack = [];
61
62
  this._stopNodeProcessor = null;
62
63
  this._exitIfTriggered = false;
64
+ this.xmlVersion = '1.0';
63
65
 
64
66
  if (!this.matcher) {
65
67
  this.matcher = new Matcher();
@@ -283,6 +285,18 @@ export default class Xml2JsParser {
283
285
  this.source.startIndex,
284
286
  );
285
287
 
288
+ // Extract namespace prefix and local name from raw tag name (e.g. "ns:tag" → "ns", "tag").
289
+ // Always done from the raw name (tagExp.tagName), before processTagName strips the prefix,
290
+ // so these values are stable regardless of skip.nsPrefix.
291
+ const colonIdx = tagExp.tagName.indexOf(':');
292
+ const tagNamespace = colonIdx !== -1 ? tagExp.tagName.slice(0, colonIdx) : undefined;
293
+ // Local name for the matcher: prefix-free always (e.g. "code" from "ns:code").
294
+ // The matcher library tracks namespace separately via the 3rd push() argument —
295
+ // passing the full "ns:code" as the tag name would break ns::code expression matching.
296
+ const matcherTagName = tagNamespace !== undefined
297
+ ? tagExp.tagName.slice(colonIdx + 1)
298
+ : processedTagName;
299
+
286
300
  // ── Limit: maxNestedTags ─────────────────────────────────────────────────
287
301
  const maxNested = options.limits?.maxNestedTags;
288
302
  if (maxNested !== undefined && maxNested !== null) {
@@ -304,7 +318,7 @@ export default class Xml2JsParser {
304
318
  raeAttrLen = tagExp.rawAttributesLen;
305
319
  }
306
320
 
307
- this.matcher.push(processedTagName, {});
321
+ this.matcher.push(matcherTagName, {}, tagNamespace);
308
322
  if (raeAttrLen > 0) {
309
323
  this.matcher.updateCurrent(rawAttributes);
310
324
  }
@@ -334,7 +348,10 @@ export default class Xml2JsParser {
334
348
  this.matcher.pop();
335
349
  } else if (stopNodeConfig) {
336
350
  // Create a fresh processor with the matching nested + skipEnclosures config.
337
- this._stopNodeProcessor = new StopNodeProcessor(processedTagName, {
351
+ // Raw tag name (tagExp.tagName) is used — the processor scans the source
352
+ // character-by-character and must match the prefix-as-written (e.g. "ns:code"),
353
+ // independent of what skip.nsPrefix does to the processed output name.
354
+ this._stopNodeProcessor = new StopNodeProcessor(tagExp.tagName, {
338
355
  nested: stopNodeConfig.nested,
339
356
  skipEnclosures: stopNodeConfig.skipEnclosures,
340
357
  });
@@ -351,7 +368,8 @@ export default class Xml2JsParser {
351
368
  } else if (skipTagConfig) {
352
369
  // Skip tag: collect raw content (to advance the source past the closing tag)
353
370
  // but call no output builder methods — the tag is silently dropped.
354
- this._stopNodeProcessor = new StopNodeProcessor(processedTagName, {
371
+ // Raw tag name used for the same reason as the stop-node branch above.
372
+ this._stopNodeProcessor = new StopNodeProcessor(tagExp.tagName, {
355
373
  nested: skipTagConfig.nested,
356
374
  skipEnclosures: skipTagConfig.skipEnclosures,
357
375
  });
@@ -460,7 +478,7 @@ export default class Xml2JsParser {
460
478
  processAttrName(attrName) {
461
479
  const options = this.options;
462
480
  attrName = resolveNsPrefix(attrName, options.skip.nsPrefix);
463
- if (!isName(attrName)) { //TODO: make it optional
481
+ if (!isQName(attrName, this.xmlVersion)) { //TODO: make it optional
464
482
  throw new ParseError(`Invalid attribute name: ${attrName}`, ErrorCode.INVALID_ATTRIBUTE_NAME);
465
483
  }
466
484
  attrName = sanitizeName(attrName, options.onDangerousProperty);
@@ -1,7 +1,8 @@
1
1
  'use strict';
2
2
  import { ParseError, ErrorCode } from './ParseError.js';
3
3
  import { collectRawAttributes } from './AttributeProcessor.js';
4
- import { isName } from "./util.js"
4
+ import { isSpace } from "./util.js"
5
+ import { name as isName, qName as isQName } from 'xml-naming';
5
6
  // Re-export flushAttributes so Xml2JsParser and XmlSpecialTagsReader can
6
7
  // continue to import it from here without changing their import lines.
7
8
  export { flushAttributes } from './AttributeProcessor.js';
@@ -157,19 +158,20 @@ function buildTagExpObj(exp, parser) {
157
158
  let attrsExp = "";
158
159
  let i = 0;
159
160
 
160
- for (; i < expLen; i++) {
161
- if (exp[i] === " ") {
161
+ for (; i < exp.length; i++) {
162
+ const c = exp[i];
163
+ if (isSpace(c)) {
162
164
  tagExp.tagName = exp.substring(0, i);
163
165
  attrsExp = exp.substring(i + 1);
164
166
  break;
165
167
  }
166
168
  }
167
169
  //only tag
168
- if (tagExp.tagName.length === 0 && i === expLen) tagExp.tagName = exp;
170
+ if (tagExp.tagName.length === 0 && i === exp.length) tagExp.tagName = exp;
169
171
  tagExp.tagName = tagExp.tagName.trimEnd();
170
172
  tagExp._attrsExp = attrsExp;
171
173
 
172
- if (!isName(tagExp.tagName)) {
174
+ if (!isQName(tagExp.tagName, parser.xmlVersion)) {
173
175
  throw new ParseError("Invalid tag name", ErrorCode.INVALID_TAG_NAME);
174
176
  }
175
177
 
@@ -178,6 +180,7 @@ function buildTagExpObj(exp, parser) {
178
180
  if (!parser.options.skip.attributes && attrsExp.length > 0) {
179
181
  collectRawAttributes(attrsExp, parser, tagExp);
180
182
  }
181
-
183
+ // console.log(tagExp)
182
184
  return tagExp;
183
- }
185
+ }
186
+
@@ -36,11 +36,21 @@ export function readPiTag(parser) {
36
36
  parser.source.markTokenStart(1);
37
37
  //<? already consumed
38
38
  let tagExp = readPiExp(parser, "?>");
39
- if (!tagExp) throw new ParseError(
40
- "Invalid Pi Tag expression.",
41
- ErrorCode.INVALID_TAG,
42
- { line: parser.source.line, col: parser.source.cols, index: parser.source.startIndex }
43
- );
39
+ if (!tagExp) {
40
+ throw new ParseError(
41
+ "Invalid Pi Tag expression.",
42
+ ErrorCode.INVALID_TAG,
43
+ { line: parser.source.line, col: parser.source.cols, index: parser.source.startIndex }
44
+ )
45
+ } else if (tagExp.tagName === "xml") {
46
+ // Read version from the declaration and store it on the parser for validators.
47
+ const version = tagExp.rawAttributes?.version;
48
+ if (version === '1.1') {
49
+ parser.xmlVersion = 1.1;
50
+ } else {
51
+ parser.xmlVersion = 1.0; // default
52
+ }
53
+ }
44
54
 
45
55
  // Flush attributes into the output builder's this.attributes accumulator
46
56
  // so addDeclaration() / addInstruction() pick them up, mirroring what readOpeningTag
package/src/util.js CHANGED
@@ -1,10 +1,3 @@
1
- 'use strict';
2
-
3
- const nameStartChar = ':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';
4
- const nameChar = nameStartChar + '\\-.\\d\\u00B7\\u0300-\\u036F\\u203F-\\u2040';
5
- export const nameRegexp = '[' + nameStartChar + '][' + nameChar + ']*';
6
- const regexName = new RegExp('^' + nameRegexp + '$');
7
-
8
1
  export function getAllMatches(string, regex) {
9
2
  const matches = [];
10
3
  let match = regex.exec(string);
@@ -21,9 +14,15 @@ export function getAllMatches(string, regex) {
21
14
  return matches;
22
15
  }
23
16
 
24
- export const isName = function (string) {
25
- const match = regexName.exec(string);
26
- return !(match === null || typeof match === 'undefined');
17
+
18
+
19
+ export function isSpace(char) {
20
+ return char === " " || char === "\t" || char === "\n" || char === "\r" || char === "\f";
21
+ }
22
+
23
+
24
+ export function isSpaceCode(code) {
25
+ return code === 32 || code === 9 || code === 10 || code === 13 || code === 12; // space \t \n \r \f
27
26
  }
28
27
 
29
28
  export function isExist(v) {