@depup/fast-xml-parser 5.10.1-depup.0 → 5.11.1-depup.0
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 +8 -1
- package/README.md +5 -4
- package/changes.json +7 -3
- package/lib/fxp.cjs +1 -1
- package/lib/fxp.min.js +1 -1
- package/lib/fxp.min.js.map +1 -1
- package/lib/fxparser.min.js +1 -1
- package/lib/fxparser.min.js.map +1 -1
- package/lib/fxvalidator.min.js +1 -1
- package/lib/fxvalidator.min.js.map +1 -1
- package/package.json +12 -8
- package/src/fxp.d.ts +2 -0
- package/src/validator.js +98 -5
- package/src/xmlparser/DocTypeReader.js +16 -1
- package/src/xmlparser/OrderedObjParser.js +23 -1
- package/src/xmlparser/xmlNode.js +14 -0
package/lib/fxvalidator.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.XMLValidator=t():e.XMLValidator=t()}(this,()=>(()=>{"use strict";var e={d:(t,r)=>{for(var n in r)e.o(r,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:r[n]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{validate:()=>l});var r=":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",n=new RegExp("^["+r+"]["+r+"\\-.\\d\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$"),i=function(e){return!(null==n.exec(e))},a={allowBooleanAttributes:!1,unpairedTags:[]};function l(e,t){t=Object.assign({},a,t);var r=[],n=!1,i=!1;"\ufeff"===e[0]&&(e=e.substr(1));for(var l=0;l<e.length;l++)if("<"===e[l]&&"?"===e[l+1]){if((l=u(e,l+=2)).err)return l}else{if("<"!==e[l]){if(o(e[l]))continue;return
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.XMLValidator=t():e.XMLValidator=t()}(this,()=>(()=>{"use strict";var e={d:(t,r)=>{for(var n in r)e.o(r,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:r[n]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{validate:()=>l});var r=":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",n=new RegExp("^["+r+"]["+r+"\\-.\\d\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$"),i=function(e){return!(null==n.exec(e))},a={allowBooleanAttributes:!1,unpairedTags:[]};function l(e,t){t=Object.assign({},a,t);var r=[],n=!1,i=!1;"\ufeff"===e[0]&&(e=e.substr(1));for(var l=0;l<e.length;l++)if("<"===e[l]&&"?"===e[l+1]){if((l=u(e,l+=2)).err)return l}else{if("<"!==e[l]){if(o(e[l]))continue;return h("InvalidChar","char '"+e[l]+"' is not expected.",m(e,l))}var d=l;if("!"===e[++l]){l=f(e,l);continue}var s=!1;"/"===e[l]&&(s=!0,l++);for(var p="";l<e.length&&">"!==e[l]&&" "!==e[l]&&"\t"!==e[l]&&"\n"!==e[l]&&"\r"!==e[l];l++)p+=e[l];if("/"===(p=p.trim())[p.length-1]&&(p=p.substring(0,p.length-1),l--),!b(p))return h("InvalidTag",0===p.trim().length?"Invalid space after '<'.":"Tag '"+p+"' is an invalid name.",m(e,l));var F=g(e,l);if(!1===F)return h("InvalidAttr","Attributes for '"+p+"' have open quote.",m(e,l));var I=F.value;if(l=F.index,"/"===I[I.length-1]){var x=l-I.length,y=v(I=I.substring(0,I.length-1),t);if(!0!==y)return h(y.err.code,y.err.msg,m(e,x+y.err.line));n=!0}else if(s){if(!F.tagClosed)return h("InvalidTag","Closing tag '"+p+"' doesn't have proper closing.",m(e,l));if(I.trim().length>0)return h("InvalidTag","Closing tag '"+p+"' can't have attributes or invalid starting.",m(e,d));if(0===r.length)return h("InvalidTag","Closing tag '"+p+"' has not been opened.",m(e,d));var A=r.pop();if(p!==A.tagName){var C=m(e,A.tagStartPos);return h("InvalidTag","Expected closing tag '"+A.tagName+"' (opened in line "+C.line+", col "+C.col+") instead of closing tag '"+p+"'.",m(e,d))}0==r.length&&(i=!0)}else{var T=v(I,t);if(!0!==T)return h(T.err.code,T.err.msg,m(e,l-I.length+T.err.line));if(!0===i)return h("InvalidXml","Multiple possible root nodes found.",m(e,l));-1!==t.unpairedTags.indexOf(p)||r.push({tagName:p,tagStartPos:d}),n=!0}for(l++;l<e.length;l++)if("<"===e[l]){if("!"===e[l+1]){l=f(e,++l);continue}if("?"!==e[l+1])break;if((l=u(e,++l)).err)return l}else if("&"===e[l]){var O=c(e,l);if(-1==O)return h("InvalidChar","char '&' is not expected.",m(e,l));l=O}else if(!0===i&&!o(e[l]))return h("InvalidXml","Extra text at the end",m(e,l));"<"===e[l]&&l--}return n?1==r.length?h("InvalidTag","Unclosed tag '"+r[0].tagName+"'.",m(e,r[0].tagStartPos)):!(r.length>0)||h("InvalidXml","Invalid '"+JSON.stringify(r.map(function(e){return e.tagName}),null,4).replace(/\r?\n/g,"")+"' found.",{line:1,col:1}):h("InvalidXml","Start tag expected.",1)}function o(e){return" "===e||"\t"===e||"\n"===e||"\r"===e}function u(e,t){for(var r=t;t<e.length;t++)if("?"!=e[t]&&" "!=e[t]);else{var n=e.substr(r,t-r);if(t>5&&"xml"===n)return h("InvalidXml","XML declaration allowed only at the start of the document.",m(e,t));if("?"==e[t]&&">"==e[t+1]){t++;break}}return t}function f(e,t){if(e.length>t+5&&"-"===e[t+1]&&"-"===e[t+2]){for(t+=3;t<e.length;t++)if("-"===e[t]&&"-"===e[t+1]&&">"===e[t+2]){t+=2;break}}else if(e.length>t+8&&"D"===e[t+1]&&"O"===e[t+2]&&"C"===e[t+3]&&"T"===e[t+4]&&"Y"===e[t+5]&&"P"===e[t+6]&&"E"===e[t+7]){var r=1;for(t+=8;t<e.length;t++)if("<"===e[t])r++;else if(">"===e[t]&&0===--r)break}else if(e.length>t+9&&"["===e[t+1]&&"C"===e[t+2]&&"D"===e[t+3]&&"A"===e[t+4]&&"T"===e[t+5]&&"A"===e[t+6]&&"["===e[t+7])for(t+=8;t<e.length;t++)if("]"===e[t]&&"]"===e[t+1]&&">"===e[t+2]){t+=2;break}return t}var d='"',s="'";function g(e,t){for(var r="",n="",i=!1;t<e.length;t++){if(e[t]===d||e[t]===s)""===n?n=e[t]:n!==e[t]||(n="");else if(">"===e[t]&&""===n){i=!0;break}r+=e[t]}return""===n&&{value:r,index:t,tagClosed:i}}function v(e,t){for(var r=function(e){for(var t=[],r=e.length,n=0;n<r;){for(var i=n;n<r&&o(e[n]);)n++;if(n>=r)break;if("="!==e[n]){for(var a=e.slice(i,n),l=n;n<r&&!o(e[n])&&"="!==e[n];)n++;for(var u=e.slice(l,n),f=void 0,d=n;d<r&&o(e[d]);)d++;d<r&&"="===e[d]&&(f=e.slice(n,d+1),n=d+1);for(var s=void 0,g=void 0,v=n;v<r&&o(e[v]);)v++;if(v<r&&('"'===e[v]||"'"===e[v])){var c=v+1,h=e.indexOf(e[v],c);-1!==h&&(s=e[v],g=e.slice(c,h),n=h+1)}var p={startIndex:i};p[1]=a,p[2]=u,p[3]=f,p[4]=void 0!==s||void 0,p[5]=s,p[6]=g,t.push(p)}else n=i+1}return t}(e),n={},i=0;i<r.length;i++){if(0===r[i][1].length)return h("InvalidAttr","Attribute '"+r[i][2]+"' has no space in starting.",F(r[i]));if(void 0!==r[i][3]&&void 0===r[i][4])return h("InvalidAttr","Attribute '"+r[i][2]+"' is without value.",F(r[i]));if(void 0===r[i][3]&&!t.allowBooleanAttributes)return h("InvalidAttr","boolean attribute '"+r[i][2]+"' is not allowed.",F(r[i]));var a=r[i][2];if(!p(a))return h("InvalidAttr","Attribute '"+a+"' is an invalid name.",F(r[i]));if(Object.prototype.hasOwnProperty.call(n,a))return h("InvalidAttr","Attribute '"+a+"' is repeated.",F(r[i]));n[a]=1}return!0}function c(e,t){if(";"===e[++t])return-1;if("#"===e[t])return function(e,t){var r=/\d/;for("x"===e[t]&&(t++,r=/[\da-fA-F]/);t<e.length;t++){if(";"===e[t])return t;if(!e[t].match(r))break}return-1}(e,++t);for(var r=0;t<e.length;t++,r++)if(!(e[t].match(/\w/)&&r<20)){if(";"===e[t])break;return-1}return t}function h(e,t,r){return{err:{code:e,msg:t,line:r.line||r,col:r.col}}}function p(e){return i(e)}function b(e){return i(e)}function m(e,t){var r=e.substring(0,t).split(/\r?\n/);return{line:r.length,col:r[r.length-1].length+1}}function F(e){return e.startIndex+e[1].length}return t})());
|
|
2
2
|
//# sourceMappingURL=fxvalidator.min.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"./lib/fxvalidator.min.js","mappings":"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","sources":["webpack://XMLValidator/webpack/universalModuleDefinition","webpack://XMLValidator/webpack/bootstrap","webpack://XMLValidator/webpack/runtime/define property getters","webpack://XMLValidator/webpack/runtime/hasOwnProperty shorthand","webpack://XMLValidator/webpack/runtime/make namespace object","webpack://XMLValidator/./src/util.js","webpack://XMLValidator/./src/validator.js"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"XMLValidator\"] = factory();\n\telse\n\t\troot[\"XMLValidator\"] = factory();\n})(this, () => {\nreturn ","// The require scope\nvar __webpack_require__ = {};\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","'use strict';\n\nconst 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';\nconst nameChar = nameStartChar + '\\\\-.\\\\d\\\\u00B7\\\\u0300-\\\\u036F\\\\u203F-\\\\u2040';\nexport const nameRegexp = '[' + nameStartChar + '][' + nameChar + ']*';\nconst regexName = new RegExp('^' + nameRegexp + '$');\n\nexport function getAllMatches(string, regex) {\n const matches = [];\n let match = regex.exec(string);\n while (match) {\n const allmatches = [];\n allmatches.startIndex = regex.lastIndex - match[0].length;\n const len = match.length;\n for (let index = 0; index < len; index++) {\n allmatches.push(match[index]);\n }\n matches.push(allmatches);\n match = regex.exec(string);\n }\n return matches;\n}\n\nexport const isName = function (string) {\n const match = regexName.exec(string);\n return !(match === null || typeof match === 'undefined');\n}\n\nexport function isExist(v) {\n return typeof v !== 'undefined';\n}\n\nexport function isEmptyObject(obj) {\n return Object.keys(obj).length === 0;\n}\n\nexport function getValue(v) {\n if (exports.isExist(v)) {\n return v;\n } else {\n return '';\n }\n}\n\n/**\n * Dangerous property names that could lead to prototype pollution or security issues\n */\nexport const DANGEROUS_PROPERTY_NAMES = [\n // '__proto__',\n // 'constructor',\n // 'prototype',\n 'hasOwnProperty',\n 'toString',\n 'valueOf',\n '__defineGetter__',\n '__defineSetter__',\n '__lookupGetter__',\n '__lookupSetter__'\n];\n\nexport const criticalProperties = [\"__proto__\", \"constructor\", \"prototype\"];","'use strict';\n\nimport { getAllMatches, isName } from './util.js';\n\nconst defaultOptions = {\n allowBooleanAttributes: false, //A tag can have attributes without any value\n unpairedTags: []\n};\n\n//const tagsPattern = new RegExp(\"<\\\\/?([\\\\w:\\\\-_\\.]+)\\\\s*\\/?>\",\"g\");\nexport function validate(xmlData, options) {\n options = Object.assign({}, defaultOptions, options);\n\n //xmlData = xmlData.replace(/(\\r\\n|\\n|\\r)/gm,\"\");//make it single line\n //xmlData = xmlData.replace(/(^\\s*<\\?xml.*?\\?>)/g,\"\");//Remove XML starting tag\n //xmlData = xmlData.replace(/(<!DOCTYPE[\\s\\w\\\"\\.\\/\\-\\:]+(\\[.*\\])*\\s*>)/g,\"\");//Remove DOCTYPE\n const tags = [];\n let tagFound = false;\n\n //indicates that the root tag has been closed (aka. depth 0 has been reached)\n let reachedRoot = false;\n\n if (xmlData[0] === '\\ufeff') {\n // check for byte order mark (BOM)\n xmlData = xmlData.substr(1);\n }\n\n for (let i = 0; i < xmlData.length; i++) {\n\n if (xmlData[i] === '<' && xmlData[i + 1] === '?') {\n i += 2;\n i = readPI(xmlData, i);\n if (i.err) return i;\n } else if (xmlData[i] === '<') {\n //starting of tag\n //read until you reach to '>' avoiding any '>' in attribute value\n let tagStartPos = i;\n i++;\n\n if (xmlData[i] === '!') {\n i = readCommentAndCDATA(xmlData, i);\n continue;\n } else {\n let closingTag = false;\n if (xmlData[i] === '/') {\n //closing tag\n closingTag = true;\n i++;\n }\n //read tagname\n let tagName = '';\n for (; i < xmlData.length &&\n xmlData[i] !== '>' &&\n xmlData[i] !== ' ' &&\n xmlData[i] !== '\\t' &&\n xmlData[i] !== '\\n' &&\n xmlData[i] !== '\\r'; i++\n ) {\n tagName += xmlData[i];\n }\n tagName = tagName.trim();\n //console.log(tagName);\n\n if (tagName[tagName.length - 1] === '/') {\n //self closing tag without attributes\n tagName = tagName.substring(0, tagName.length - 1);\n //continue;\n i--;\n }\n if (!validateTagName(tagName)) {\n let msg;\n if (tagName.trim().length === 0) {\n msg = \"Invalid space after '<'.\";\n } else {\n msg = \"Tag '\" + tagName + \"' is an invalid name.\";\n }\n return getErrorObject('InvalidTag', msg, getLineNumberForPosition(xmlData, i));\n }\n\n const result = readAttributeStr(xmlData, i);\n if (result === false) {\n return getErrorObject('InvalidAttr', \"Attributes for '\" + tagName + \"' have open quote.\", getLineNumberForPosition(xmlData, i));\n }\n let attrStr = result.value;\n i = result.index;\n\n if (attrStr[attrStr.length - 1] === '/') {\n //self closing tag\n const attrStrStart = i - attrStr.length;\n attrStr = attrStr.substring(0, attrStr.length - 1);\n const isValid = validateAttributeString(attrStr, options);\n if (isValid === true) {\n tagFound = true;\n //continue; //text may presents after self closing tag\n } else {\n //the result from the nested function returns the position of the error within the attribute\n //in order to get the 'true' error line, we need to calculate the position where the attribute begins (i - attrStr.length) and then add the position within the attribute\n //this gives us the absolute index in the entire xml, which we can use to find the line at last\n return getErrorObject(isValid.err.code, isValid.err.msg, getLineNumberForPosition(xmlData, attrStrStart + isValid.err.line));\n }\n } else if (closingTag) {\n if (!result.tagClosed) {\n return getErrorObject('InvalidTag', \"Closing tag '\" + tagName + \"' doesn't have proper closing.\", getLineNumberForPosition(xmlData, i));\n } else if (attrStr.trim().length > 0) {\n return getErrorObject('InvalidTag', \"Closing tag '\" + tagName + \"' can't have attributes or invalid starting.\", getLineNumberForPosition(xmlData, tagStartPos));\n } else if (tags.length === 0) {\n return getErrorObject('InvalidTag', \"Closing tag '\" + tagName + \"' has not been opened.\", getLineNumberForPosition(xmlData, tagStartPos));\n } else {\n const otg = tags.pop();\n if (tagName !== otg.tagName) {\n let openPos = getLineNumberForPosition(xmlData, otg.tagStartPos);\n return getErrorObject('InvalidTag',\n \"Expected closing tag '\" + otg.tagName + \"' (opened in line \" + openPos.line + \", col \" + openPos.col + \") instead of closing tag '\" + tagName + \"'.\",\n getLineNumberForPosition(xmlData, tagStartPos));\n }\n\n //when there are no more tags, we reached the root level.\n if (tags.length == 0) {\n reachedRoot = true;\n }\n }\n } else {\n const isValid = validateAttributeString(attrStr, options);\n if (isValid !== true) {\n //the result from the nested function returns the position of the error within the attribute\n //in order to get the 'true' error line, we need to calculate the position where the attribute begins (i - attrStr.length) and then add the position within the attribute\n //this gives us the absolute index in the entire xml, which we can use to find the line at last\n return getErrorObject(isValid.err.code, isValid.err.msg, getLineNumberForPosition(xmlData, i - attrStr.length + isValid.err.line));\n }\n\n //if the root level has been reached before ...\n if (reachedRoot === true) {\n return getErrorObject('InvalidXml', 'Multiple possible root nodes found.', getLineNumberForPosition(xmlData, i));\n } else if (options.unpairedTags.indexOf(tagName) !== -1) {\n //don't push into stack\n } else {\n tags.push({ tagName, tagStartPos });\n }\n tagFound = true;\n }\n\n //skip tag text value\n //It may include comments and CDATA value\n for (i++; i < xmlData.length; i++) {\n if (xmlData[i] === '<') {\n if (xmlData[i + 1] === '!') {\n //comment or CADATA\n i++;\n i = readCommentAndCDATA(xmlData, i);\n continue;\n } else if (xmlData[i + 1] === '?') {\n i = readPI(xmlData, ++i);\n if (i.err) return i;\n } else {\n break;\n }\n } else if (xmlData[i] === '&') {\n const afterAmp = validateAmpersand(xmlData, i);\n if (afterAmp == -1)\n return getErrorObject('InvalidChar', \"char '&' is not expected.\", getLineNumberForPosition(xmlData, i));\n i = afterAmp;\n } else {\n if (reachedRoot === true && !isWhiteSpace(xmlData[i])) {\n return getErrorObject('InvalidXml', \"Extra text at the end\", getLineNumberForPosition(xmlData, i));\n }\n }\n } //end of reading tag text value\n if (xmlData[i] === '<') {\n i--;\n }\n }\n } else {\n if (isWhiteSpace(xmlData[i])) {\n continue;\n }\n return getErrorObject('InvalidChar', \"char '\" + xmlData[i] + \"' is not expected.\", getLineNumberForPosition(xmlData, i));\n }\n }\n\n if (!tagFound) {\n return getErrorObject('InvalidXml', 'Start tag expected.', 1);\n } else if (tags.length == 1) {\n return getErrorObject('InvalidTag', \"Unclosed tag '\" + tags[0].tagName + \"'.\", getLineNumberForPosition(xmlData, tags[0].tagStartPos));\n } else if (tags.length > 0) {\n return getErrorObject('InvalidXml', \"Invalid '\" +\n JSON.stringify(tags.map(t => t.tagName), null, 4).replace(/\\r?\\n/g, '') +\n \"' found.\", { line: 1, col: 1 });\n }\n\n return true;\n};\n\nfunction isWhiteSpace(char) {\n return char === ' ' || char === '\\t' || char === '\\n' || char === '\\r';\n}\n/**\n * Read Processing insstructions and skip\n * @param {*} xmlData\n * @param {*} i\n */\nfunction readPI(xmlData, i) {\n const start = i;\n for (; i < xmlData.length; i++) {\n if (xmlData[i] == '?' || xmlData[i] == ' ') {\n //tagname\n const tagname = xmlData.substr(start, i - start);\n if (i > 5 && tagname === 'xml') {\n return getErrorObject('InvalidXml', 'XML declaration allowed only at the start of the document.', getLineNumberForPosition(xmlData, i));\n } else if (xmlData[i] == '?' && xmlData[i + 1] == '>') {\n //check if valid attribut string\n i++;\n break;\n } else {\n continue;\n }\n }\n }\n return i;\n}\n\nfunction readCommentAndCDATA(xmlData, i) {\n if (xmlData.length > i + 5 && xmlData[i + 1] === '-' && xmlData[i + 2] === '-') {\n //comment\n for (i += 3; i < xmlData.length; i++) {\n if (xmlData[i] === '-' && xmlData[i + 1] === '-' && xmlData[i + 2] === '>') {\n i += 2;\n break;\n }\n }\n } else if (\n xmlData.length > i + 8 &&\n xmlData[i + 1] === 'D' &&\n xmlData[i + 2] === 'O' &&\n xmlData[i + 3] === 'C' &&\n xmlData[i + 4] === 'T' &&\n xmlData[i + 5] === 'Y' &&\n xmlData[i + 6] === 'P' &&\n xmlData[i + 7] === 'E'\n ) {\n let angleBracketsCount = 1;\n for (i += 8; i < xmlData.length; i++) {\n if (xmlData[i] === '<') {\n angleBracketsCount++;\n } else if (xmlData[i] === '>') {\n angleBracketsCount--;\n if (angleBracketsCount === 0) {\n break;\n }\n }\n }\n } else if (\n xmlData.length > i + 9 &&\n xmlData[i + 1] === '[' &&\n xmlData[i + 2] === 'C' &&\n xmlData[i + 3] === 'D' &&\n xmlData[i + 4] === 'A' &&\n xmlData[i + 5] === 'T' &&\n xmlData[i + 6] === 'A' &&\n xmlData[i + 7] === '['\n ) {\n for (i += 8; i < xmlData.length; i++) {\n if (xmlData[i] === ']' && xmlData[i + 1] === ']' && xmlData[i + 2] === '>') {\n i += 2;\n break;\n }\n }\n }\n\n return i;\n}\n\nconst doubleQuote = '\"';\nconst singleQuote = \"'\";\n\n/**\n * Keep reading xmlData until '<' is found outside the attribute value.\n * @param {string} xmlData\n * @param {number} i\n */\nfunction readAttributeStr(xmlData, i) {\n let attrStr = '';\n let startChar = '';\n let tagClosed = false;\n for (; i < xmlData.length; i++) {\n if (xmlData[i] === doubleQuote || xmlData[i] === singleQuote) {\n if (startChar === '') {\n startChar = xmlData[i];\n } else if (startChar !== xmlData[i]) {\n //if vaue is enclosed with double quote then single quotes are allowed inside the value and vice versa\n } else {\n startChar = '';\n }\n } else if (xmlData[i] === '>') {\n if (startChar === '') {\n tagClosed = true;\n break;\n }\n }\n attrStr += xmlData[i];\n }\n if (startChar !== '') {\n return false;\n }\n\n return {\n value: attrStr,\n index: i,\n tagClosed: tagClosed\n };\n}\n\n/**\n * Select all the attributes whether valid or invalid.\n */\nconst validAttrStrRegxp = new RegExp('(\\\\s*)([^\\\\s=]+)(\\\\s*=)?(\\\\s*([\\'\"])(([\\\\s\\\\S])*?)\\\\5)?', 'g');\n\n//attr, =\"sd\", a=\"amit's\", a=\"sd\"b=\"saf\", ab cd=\"\"\n\nfunction validateAttributeString(attrStr, options) {\n //console.log(\"start:\"+attrStr+\":end\");\n\n //if(attrStr.trim().length === 0) return true; //empty string\n\n const matches = getAllMatches(attrStr, validAttrStrRegxp);\n const attrNames = {};\n\n for (let i = 0; i < matches.length; i++) {\n if (matches[i][1].length === 0) {\n //nospace before attribute name: a=\"sd\"b=\"saf\"\n return getErrorObject('InvalidAttr', \"Attribute '\" + matches[i][2] + \"' has no space in starting.\", getPositionFromMatch(matches[i]))\n } else if (matches[i][3] !== undefined && matches[i][4] === undefined) {\n return getErrorObject('InvalidAttr', \"Attribute '\" + matches[i][2] + \"' is without value.\", getPositionFromMatch(matches[i]));\n } else if (matches[i][3] === undefined && !options.allowBooleanAttributes) {\n //independent attribute: ab\n return getErrorObject('InvalidAttr', \"boolean attribute '\" + matches[i][2] + \"' is not allowed.\", getPositionFromMatch(matches[i]));\n }\n /* else if(matches[i][6] === undefined){//attribute without value: ab=\n return { err: { code:\"InvalidAttr\",msg:\"attribute \" + matches[i][2] + \" has no value assigned.\"}};\n } */\n const attrName = matches[i][2];\n if (!validateAttrName(attrName)) {\n return getErrorObject('InvalidAttr', \"Attribute '\" + attrName + \"' is an invalid name.\", getPositionFromMatch(matches[i]));\n }\n if (!Object.prototype.hasOwnProperty.call(attrNames, attrName)) {\n //check for duplicate attribute.\n attrNames[attrName] = 1;\n } else {\n return getErrorObject('InvalidAttr', \"Attribute '\" + attrName + \"' is repeated.\", getPositionFromMatch(matches[i]));\n }\n }\n\n return true;\n}\n\nfunction validateNumberAmpersand(xmlData, i) {\n let re = /\\d/;\n if (xmlData[i] === 'x') {\n i++;\n re = /[\\da-fA-F]/;\n }\n for (; i < xmlData.length; i++) {\n if (xmlData[i] === ';')\n return i;\n if (!xmlData[i].match(re))\n break;\n }\n return -1;\n}\n\nfunction validateAmpersand(xmlData, i) {\n // https://www.w3.org/TR/xml/#dt-charref\n i++;\n if (xmlData[i] === ';')\n return -1;\n if (xmlData[i] === '#') {\n i++;\n return validateNumberAmpersand(xmlData, i);\n }\n let count = 0;\n for (; i < xmlData.length; i++, count++) {\n if (xmlData[i].match(/\\w/) && count < 20)\n continue;\n if (xmlData[i] === ';')\n break;\n return -1;\n }\n return i;\n}\n\nfunction getErrorObject(code, message, lineNumber) {\n return {\n err: {\n code: code,\n msg: message,\n line: lineNumber.line || lineNumber,\n col: lineNumber.col,\n },\n };\n}\n\nfunction validateAttrName(attrName) {\n return isName(attrName);\n}\n\n// const startsWithXML = /^xml/i;\n\nfunction validateTagName(tagname) {\n return isName(tagname) /* && !tagname.match(startsWithXML) */;\n}\n\n//this function returns the line number for the character at the given index\nfunction getLineNumberForPosition(xmlData, index) {\n const lines = xmlData.substring(0, index).split(/\\r?\\n/);\n return {\n line: lines.length,\n\n // column number is last line's length + 1, because column numbering starts at 1:\n col: lines[lines.length - 1].length + 1\n };\n}\n\n//this function returns the position of the first character of match within attrStr\nfunction getPositionFromMatch(match) {\n return match.startIndex + match[1].length;\n}\n"],"names":["root","factory","exports","module","define","amd","this","__webpack_require__","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","nameStartChar","regexName","RegExp","isName","string","exec","defaultOptions","allowBooleanAttributes","unpairedTags","validate","xmlData","options","assign","tags","tagFound","reachedRoot","substr","i","length","readPI","err","isWhiteSpace","getErrorObject","getLineNumberForPosition","tagStartPos","readCommentAndCDATA","closingTag","tagName","trim","substring","validateTagName","result","readAttributeStr","attrStr","index","attrStrStart","isValid","validateAttributeString","code","msg","line","tagClosed","otg","pop","openPos","col","indexOf","push","afterAmp","validateAmpersand","JSON","stringify","map","t","replace","char","start","tagname","angleBracketsCount","doubleQuote","singleQuote","startChar","validAttrStrRegxp","matches","regex","match","allmatches","startIndex","lastIndex","len","getAllMatches","attrNames","getPositionFromMatch","undefined","attrName","validateAttrName","re","validateNumberAmpersand","count","message","lineNumber","lines","split"],"sourceRoot":""}
|
|
1
|
+
{"version":3,"file":"./lib/fxvalidator.min.js","mappings":"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","sources":["webpack://XMLValidator/webpack/universalModuleDefinition","webpack://XMLValidator/webpack/bootstrap","webpack://XMLValidator/webpack/runtime/define property getters","webpack://XMLValidator/webpack/runtime/hasOwnProperty shorthand","webpack://XMLValidator/webpack/runtime/make namespace object","webpack://XMLValidator/./src/util.js","webpack://XMLValidator/./src/validator.js"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"XMLValidator\"] = factory();\n\telse\n\t\troot[\"XMLValidator\"] = factory();\n})(this, () => {\nreturn ","// The require scope\nvar __webpack_require__ = {};\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","'use strict';\n\nconst 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';\nconst nameChar = nameStartChar + '\\\\-.\\\\d\\\\u00B7\\\\u0300-\\\\u036F\\\\u203F-\\\\u2040';\nexport const nameRegexp = '[' + nameStartChar + '][' + nameChar + ']*';\nconst regexName = new RegExp('^' + nameRegexp + '$');\n\nexport function getAllMatches(string, regex) {\n const matches = [];\n let match = regex.exec(string);\n while (match) {\n const allmatches = [];\n allmatches.startIndex = regex.lastIndex - match[0].length;\n const len = match.length;\n for (let index = 0; index < len; index++) {\n allmatches.push(match[index]);\n }\n matches.push(allmatches);\n match = regex.exec(string);\n }\n return matches;\n}\n\nexport const isName = function (string) {\n const match = regexName.exec(string);\n return !(match === null || typeof match === 'undefined');\n}\n\nexport function isExist(v) {\n return typeof v !== 'undefined';\n}\n\nexport function isEmptyObject(obj) {\n return Object.keys(obj).length === 0;\n}\n\nexport function getValue(v) {\n if (exports.isExist(v)) {\n return v;\n } else {\n return '';\n }\n}\n\n/**\n * Dangerous property names that could lead to prototype pollution or security issues\n */\nexport const DANGEROUS_PROPERTY_NAMES = [\n // '__proto__',\n // 'constructor',\n // 'prototype',\n 'hasOwnProperty',\n 'toString',\n 'valueOf',\n '__defineGetter__',\n '__defineSetter__',\n '__lookupGetter__',\n '__lookupSetter__'\n];\n\nexport const criticalProperties = [\"__proto__\", \"constructor\", \"prototype\"];","'use strict';\n\nimport { isName } from './util.js';\n\nconst defaultOptions = {\n allowBooleanAttributes: false, //A tag can have attributes without any value\n unpairedTags: []\n};\n\n//const tagsPattern = new RegExp(\"<\\\\/?([\\\\w:\\\\-_\\.]+)\\\\s*\\/?>\",\"g\");\nexport function validate(xmlData, options) {\n options = Object.assign({}, defaultOptions, options);\n\n //xmlData = xmlData.replace(/(\\r\\n|\\n|\\r)/gm,\"\");//make it single line\n //xmlData = xmlData.replace(/(^\\s*<\\?xml.*?\\?>)/g,\"\");//Remove XML starting tag\n //xmlData = xmlData.replace(/(<!DOCTYPE[\\s\\w\\\"\\.\\/\\-\\:]+(\\[.*\\])*\\s*>)/g,\"\");//Remove DOCTYPE\n const tags = [];\n let tagFound = false;\n\n //indicates that the root tag has been closed (aka. depth 0 has been reached)\n let reachedRoot = false;\n\n if (xmlData[0] === '\\ufeff') {\n // check for byte order mark (BOM)\n xmlData = xmlData.substr(1);\n }\n\n for (let i = 0; i < xmlData.length; i++) {\n\n if (xmlData[i] === '<' && xmlData[i + 1] === '?') {\n i += 2;\n i = readPI(xmlData, i);\n if (i.err) return i;\n } else if (xmlData[i] === '<') {\n //starting of tag\n //read until you reach to '>' avoiding any '>' in attribute value\n let tagStartPos = i;\n i++;\n\n if (xmlData[i] === '!') {\n i = readCommentAndCDATA(xmlData, i);\n continue;\n } else {\n let closingTag = false;\n if (xmlData[i] === '/') {\n //closing tag\n closingTag = true;\n i++;\n }\n //read tagname\n let tagName = '';\n for (; i < xmlData.length &&\n xmlData[i] !== '>' &&\n xmlData[i] !== ' ' &&\n xmlData[i] !== '\\t' &&\n xmlData[i] !== '\\n' &&\n xmlData[i] !== '\\r'; i++\n ) {\n tagName += xmlData[i];\n }\n tagName = tagName.trim();\n //console.log(tagName);\n\n if (tagName[tagName.length - 1] === '/') {\n //self closing tag without attributes\n tagName = tagName.substring(0, tagName.length - 1);\n //continue;\n i--;\n }\n if (!validateTagName(tagName)) {\n let msg;\n if (tagName.trim().length === 0) {\n msg = \"Invalid space after '<'.\";\n } else {\n msg = \"Tag '\" + tagName + \"' is an invalid name.\";\n }\n return getErrorObject('InvalidTag', msg, getLineNumberForPosition(xmlData, i));\n }\n\n const result = readAttributeStr(xmlData, i);\n if (result === false) {\n return getErrorObject('InvalidAttr', \"Attributes for '\" + tagName + \"' have open quote.\", getLineNumberForPosition(xmlData, i));\n }\n let attrStr = result.value;\n i = result.index;\n\n if (attrStr[attrStr.length - 1] === '/') {\n //self closing tag\n const attrStrStart = i - attrStr.length;\n attrStr = attrStr.substring(0, attrStr.length - 1);\n const isValid = validateAttributeString(attrStr, options);\n if (isValid === true) {\n tagFound = true;\n //continue; //text may presents after self closing tag\n } else {\n //the result from the nested function returns the position of the error within the attribute\n //in order to get the 'true' error line, we need to calculate the position where the attribute begins (i - attrStr.length) and then add the position within the attribute\n //this gives us the absolute index in the entire xml, which we can use to find the line at last\n return getErrorObject(isValid.err.code, isValid.err.msg, getLineNumberForPosition(xmlData, attrStrStart + isValid.err.line));\n }\n } else if (closingTag) {\n if (!result.tagClosed) {\n return getErrorObject('InvalidTag', \"Closing tag '\" + tagName + \"' doesn't have proper closing.\", getLineNumberForPosition(xmlData, i));\n } else if (attrStr.trim().length > 0) {\n return getErrorObject('InvalidTag', \"Closing tag '\" + tagName + \"' can't have attributes or invalid starting.\", getLineNumberForPosition(xmlData, tagStartPos));\n } else if (tags.length === 0) {\n return getErrorObject('InvalidTag', \"Closing tag '\" + tagName + \"' has not been opened.\", getLineNumberForPosition(xmlData, tagStartPos));\n } else {\n const otg = tags.pop();\n if (tagName !== otg.tagName) {\n let openPos = getLineNumberForPosition(xmlData, otg.tagStartPos);\n return getErrorObject('InvalidTag',\n \"Expected closing tag '\" + otg.tagName + \"' (opened in line \" + openPos.line + \", col \" + openPos.col + \") instead of closing tag '\" + tagName + \"'.\",\n getLineNumberForPosition(xmlData, tagStartPos));\n }\n\n //when there are no more tags, we reached the root level.\n if (tags.length == 0) {\n reachedRoot = true;\n }\n }\n } else {\n const isValid = validateAttributeString(attrStr, options);\n if (isValid !== true) {\n //the result from the nested function returns the position of the error within the attribute\n //in order to get the 'true' error line, we need to calculate the position where the attribute begins (i - attrStr.length) and then add the position within the attribute\n //this gives us the absolute index in the entire xml, which we can use to find the line at last\n return getErrorObject(isValid.err.code, isValid.err.msg, getLineNumberForPosition(xmlData, i - attrStr.length + isValid.err.line));\n }\n\n //if the root level has been reached before ...\n if (reachedRoot === true) {\n return getErrorObject('InvalidXml', 'Multiple possible root nodes found.', getLineNumberForPosition(xmlData, i));\n } else if (options.unpairedTags.indexOf(tagName) !== -1) {\n //don't push into stack\n } else {\n tags.push({ tagName, tagStartPos });\n }\n tagFound = true;\n }\n\n //skip tag text value\n //It may include comments and CDATA value\n for (i++; i < xmlData.length; i++) {\n if (xmlData[i] === '<') {\n if (xmlData[i + 1] === '!') {\n //comment or CADATA\n i++;\n i = readCommentAndCDATA(xmlData, i);\n continue;\n } else if (xmlData[i + 1] === '?') {\n i = readPI(xmlData, ++i);\n if (i.err) return i;\n } else {\n break;\n }\n } else if (xmlData[i] === '&') {\n const afterAmp = validateAmpersand(xmlData, i);\n if (afterAmp == -1)\n return getErrorObject('InvalidChar', \"char '&' is not expected.\", getLineNumberForPosition(xmlData, i));\n i = afterAmp;\n } else {\n if (reachedRoot === true && !isWhiteSpace(xmlData[i])) {\n return getErrorObject('InvalidXml', \"Extra text at the end\", getLineNumberForPosition(xmlData, i));\n }\n }\n } //end of reading tag text value\n if (xmlData[i] === '<') {\n i--;\n }\n }\n } else {\n if (isWhiteSpace(xmlData[i])) {\n continue;\n }\n return getErrorObject('InvalidChar', \"char '\" + xmlData[i] + \"' is not expected.\", getLineNumberForPosition(xmlData, i));\n }\n }\n\n if (!tagFound) {\n return getErrorObject('InvalidXml', 'Start tag expected.', 1);\n } else if (tags.length == 1) {\n return getErrorObject('InvalidTag', \"Unclosed tag '\" + tags[0].tagName + \"'.\", getLineNumberForPosition(xmlData, tags[0].tagStartPos));\n } else if (tags.length > 0) {\n return getErrorObject('InvalidXml', \"Invalid '\" +\n JSON.stringify(tags.map(t => t.tagName), null, 4).replace(/\\r?\\n/g, '') +\n \"' found.\", { line: 1, col: 1 });\n }\n\n return true;\n};\n\nfunction isWhiteSpace(char) {\n return char === ' ' || char === '\\t' || char === '\\n' || char === '\\r';\n}\n/**\n * Read Processing insstructions and skip\n * @param {*} xmlData\n * @param {*} i\n */\nfunction readPI(xmlData, i) {\n const start = i;\n for (; i < xmlData.length; i++) {\n if (xmlData[i] == '?' || xmlData[i] == ' ') {\n //tagname\n const tagname = xmlData.substr(start, i - start);\n if (i > 5 && tagname === 'xml') {\n return getErrorObject('InvalidXml', 'XML declaration allowed only at the start of the document.', getLineNumberForPosition(xmlData, i));\n } else if (xmlData[i] == '?' && xmlData[i + 1] == '>') {\n //check if valid attribut string\n i++;\n break;\n } else {\n continue;\n }\n }\n }\n return i;\n}\n\nfunction readCommentAndCDATA(xmlData, i) {\n if (xmlData.length > i + 5 && xmlData[i + 1] === '-' && xmlData[i + 2] === '-') {\n //comment\n for (i += 3; i < xmlData.length; i++) {\n if (xmlData[i] === '-' && xmlData[i + 1] === '-' && xmlData[i + 2] === '>') {\n i += 2;\n break;\n }\n }\n } else if (\n xmlData.length > i + 8 &&\n xmlData[i + 1] === 'D' &&\n xmlData[i + 2] === 'O' &&\n xmlData[i + 3] === 'C' &&\n xmlData[i + 4] === 'T' &&\n xmlData[i + 5] === 'Y' &&\n xmlData[i + 6] === 'P' &&\n xmlData[i + 7] === 'E'\n ) {\n let angleBracketsCount = 1;\n for (i += 8; i < xmlData.length; i++) {\n if (xmlData[i] === '<') {\n angleBracketsCount++;\n } else if (xmlData[i] === '>') {\n angleBracketsCount--;\n if (angleBracketsCount === 0) {\n break;\n }\n }\n }\n } else if (\n xmlData.length > i + 9 &&\n xmlData[i + 1] === '[' &&\n xmlData[i + 2] === 'C' &&\n xmlData[i + 3] === 'D' &&\n xmlData[i + 4] === 'A' &&\n xmlData[i + 5] === 'T' &&\n xmlData[i + 6] === 'A' &&\n xmlData[i + 7] === '['\n ) {\n for (i += 8; i < xmlData.length; i++) {\n if (xmlData[i] === ']' && xmlData[i + 1] === ']' && xmlData[i + 2] === '>') {\n i += 2;\n break;\n }\n }\n }\n\n return i;\n}\n\nconst doubleQuote = '\"';\nconst singleQuote = \"'\";\n\n/**\n * Keep reading xmlData until '<' is found outside the attribute value.\n * @param {string} xmlData\n * @param {number} i\n */\nfunction readAttributeStr(xmlData, i) {\n let attrStr = '';\n let startChar = '';\n let tagClosed = false;\n for (; i < xmlData.length; i++) {\n if (xmlData[i] === doubleQuote || xmlData[i] === singleQuote) {\n if (startChar === '') {\n startChar = xmlData[i];\n } else if (startChar !== xmlData[i]) {\n //if vaue is enclosed with double quote then single quotes are allowed inside the value and vice versa\n } else {\n startChar = '';\n }\n } else if (xmlData[i] === '>') {\n if (startChar === '') {\n tagClosed = true;\n break;\n }\n }\n attrStr += xmlData[i];\n }\n if (startChar !== '') {\n return false;\n }\n\n return {\n value: attrStr,\n index: i,\n tagClosed: tagClosed\n };\n}\n\n/**\n * Walk `attrStr` once, left to right, splitting it into attribute tokens.\n *\n * This replaces a regex that used to do the same job\n * (`(\\s*)([^\\s=]+)(\\s*=)?(\\s*(['\"])(([\\s\\S])*?)\\5)?`). That regex led with an\n * optional whitespace group followed by a required \"non-whitespace\" group.\n * On a long run of whitespace that never resolves into an attribute name\n * (e.g. a tag with thousands of trailing spaces before `>`), the engine\n * backtracks the whitespace group one character at a time before giving up\n * and moving to the next starting position — one full backtrack per\n * position, which is quadratic in the length of the run.\n *\n * A single forward-only scan can never backtrack, so it can't be made slow\n * this way no matter how much whitespace the input contains — it's always\n * proportional to the length of the string, once.\n *\n * Each returned token mirrors the shape the old regex match array had, so\n * the validation logic below (which reads token[1]..token[6]) didn't need\n * to change:\n * token.startIndex - where this token begins in attrStr\n * token[1] - leading whitespace before the name\n * token[2] - the attribute name\n * token[3] - whitespace + '=' if present, else undefined\n * token[4] - marker (any defined value) if a quoted value was found\n * token[5] - the quote character used ('\"' or \"'\")\n * token[6] - the value's text, without the surrounding quotes\n *\n * A malformed leading character (e.g. a stray '=' with no name before it)\n * is simply skipped over, one character at a time — the same outcome the\n * old regex produced by failing to match at that position and retrying at\n * the next one.\n */\nfunction scanAttributeTokens(attrStr) {\n const tokens = [];\n const len = attrStr.length;\n let i = 0;\n\n while (i < len) {\n const tokenStart = i;\n\n // Leading whitespace before the name.\n while (i < len && isWhiteSpace(attrStr[i])) i++;\n if (i >= len) break; // trailing whitespace only — nothing left to read\n\n if (attrStr[i] === '=') {\n // No name before this '=' — not a valid attribute start. Move past\n // just this one character and try again from the next position.\n i = tokenStart + 1;\n continue;\n }\n\n const leadingWs = attrStr.slice(tokenStart, i);\n\n // Attribute name — everything up to the next whitespace or '='.\n const nameStart = i;\n while (i < len && !isWhiteSpace(attrStr[i]) && attrStr[i] !== '=') i++;\n const name = attrStr.slice(nameStart, i);\n\n // Optional whitespace + '='.\n let equalsGroup; // whitespace + '=' text, or undefined if absent\n let j = i;\n while (j < len && isWhiteSpace(attrStr[j])) j++;\n if (j < len && attrStr[j] === '=') {\n equalsGroup = attrStr.slice(i, j + 1);\n i = j + 1;\n }\n\n // Optional whitespace + quoted value.\n let quoteChar;\n let value;\n let k = i;\n while (k < len && isWhiteSpace(attrStr[k])) k++;\n if (k < len && (attrStr[k] === '\"' || attrStr[k] === \"'\")) {\n const valueStart = k + 1;\n const closeIdx = attrStr.indexOf(attrStr[k], valueStart);\n if (closeIdx !== -1) {\n quoteChar = attrStr[k];\n value = attrStr.slice(valueStart, closeIdx);\n i = closeIdx + 1;\n }\n // No closing quote found anywhere in the rest of the string — leave\n // quoteChar/value undefined, same as the old regex's group failing\n // to match a backreference-less run.\n }\n\n const token = { startIndex: tokenStart };\n token[1] = leadingWs;\n token[2] = name;\n token[3] = equalsGroup;\n token[4] = quoteChar !== undefined ? true : undefined;\n token[5] = quoteChar;\n token[6] = value;\n tokens.push(token);\n }\n\n return tokens;\n}\n\n//attr, =\"sd\", a=\"amit's\", a=\"sd\"b=\"saf\", ab cd=\"\"\n\nfunction validateAttributeString(attrStr, options) {\n //console.log(\"start:\"+attrStr+\":end\");\n\n //if(attrStr.trim().length === 0) return true; //empty string\n\n const matches = scanAttributeTokens(attrStr);\n const attrNames = {};\n\n for (let i = 0; i < matches.length; i++) {\n if (matches[i][1].length === 0) {\n //nospace before attribute name: a=\"sd\"b=\"saf\"\n return getErrorObject('InvalidAttr', \"Attribute '\" + matches[i][2] + \"' has no space in starting.\", getPositionFromMatch(matches[i]))\n } else if (matches[i][3] !== undefined && matches[i][4] === undefined) {\n return getErrorObject('InvalidAttr', \"Attribute '\" + matches[i][2] + \"' is without value.\", getPositionFromMatch(matches[i]));\n } else if (matches[i][3] === undefined && !options.allowBooleanAttributes) {\n //independent attribute: ab\n return getErrorObject('InvalidAttr', \"boolean attribute '\" + matches[i][2] + \"' is not allowed.\", getPositionFromMatch(matches[i]));\n }\n /* else if(matches[i][6] === undefined){//attribute without value: ab=\n return { err: { code:\"InvalidAttr\",msg:\"attribute \" + matches[i][2] + \" has no value assigned.\"}};\n } */\n const attrName = matches[i][2];\n if (!validateAttrName(attrName)) {\n return getErrorObject('InvalidAttr', \"Attribute '\" + attrName + \"' is an invalid name.\", getPositionFromMatch(matches[i]));\n }\n if (!Object.prototype.hasOwnProperty.call(attrNames, attrName)) {\n //check for duplicate attribute.\n attrNames[attrName] = 1;\n } else {\n return getErrorObject('InvalidAttr', \"Attribute '\" + attrName + \"' is repeated.\", getPositionFromMatch(matches[i]));\n }\n }\n\n return true;\n}\n\nfunction validateNumberAmpersand(xmlData, i) {\n let re = /\\d/;\n if (xmlData[i] === 'x') {\n i++;\n re = /[\\da-fA-F]/;\n }\n for (; i < xmlData.length; i++) {\n if (xmlData[i] === ';')\n return i;\n if (!xmlData[i].match(re))\n break;\n }\n return -1;\n}\n\nfunction validateAmpersand(xmlData, i) {\n // https://www.w3.org/TR/xml/#dt-charref\n i++;\n if (xmlData[i] === ';')\n return -1;\n if (xmlData[i] === '#') {\n i++;\n return validateNumberAmpersand(xmlData, i);\n }\n let count = 0;\n for (; i < xmlData.length; i++, count++) {\n if (xmlData[i].match(/\\w/) && count < 20)\n continue;\n if (xmlData[i] === ';')\n break;\n return -1;\n }\n return i;\n}\n\nfunction getErrorObject(code, message, lineNumber) {\n return {\n err: {\n code: code,\n msg: message,\n line: lineNumber.line || lineNumber,\n col: lineNumber.col,\n },\n };\n}\n\nfunction validateAttrName(attrName) {\n return isName(attrName);\n}\n\n// const startsWithXML = /^xml/i;\n\nfunction validateTagName(tagname) {\n return isName(tagname) /* && !tagname.match(startsWithXML) */;\n}\n\n//this function returns the line number for the character at the given index\nfunction getLineNumberForPosition(xmlData, index) {\n const lines = xmlData.substring(0, index).split(/\\r?\\n/);\n return {\n line: lines.length,\n\n // column number is last line's length + 1, because column numbering starts at 1:\n col: lines[lines.length - 1].length + 1\n };\n}\n\n//this function returns the position of the first character of match within attrStr\nfunction getPositionFromMatch(match) {\n return match.startIndex + match[1].length;\n}"],"names":["root","factory","exports","module","define","amd","this","__webpack_require__","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","nameStartChar","regexName","RegExp","isName","string","exec","defaultOptions","allowBooleanAttributes","unpairedTags","validate","xmlData","options","assign","tags","tagFound","reachedRoot","substr","i","length","readPI","err","isWhiteSpace","getErrorObject","getLineNumberForPosition","tagStartPos","readCommentAndCDATA","closingTag","tagName","trim","substring","validateTagName","result","readAttributeStr","attrStr","index","attrStrStart","isValid","validateAttributeString","code","msg","line","tagClosed","otg","pop","openPos","col","indexOf","push","afterAmp","validateAmpersand","JSON","stringify","map","t","replace","char","start","tagname","angleBracketsCount","doubleQuote","singleQuote","startChar","matches","tokens","len","tokenStart","leadingWs","slice","nameStart","name","equalsGroup","j","quoteChar","k","valueStart","closeIdx","token","startIndex","undefined","scanAttributeTokens","attrNames","getPositionFromMatch","attrName","validateAttrName","re","match","validateNumberAmpersand","count","message","lineNumber","lines","split"],"sourceRoot":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@depup/fast-xml-parser",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.11.1-depup.0",
|
|
4
4
|
"description": "Validate XML, Parse XML, Build XML without C/C++ based libraries (with updated dependencies)",
|
|
5
5
|
"main": "./lib/fxp.cjs",
|
|
6
6
|
"type": "module",
|
|
@@ -92,23 +92,27 @@
|
|
|
92
92
|
],
|
|
93
93
|
"dependencies": {
|
|
94
94
|
"@nodable/entities": "^3.0.0",
|
|
95
|
-
"fast-xml-builder": "^1.3.
|
|
96
|
-
"is-unsafe": "^2.0.
|
|
95
|
+
"fast-xml-builder": "^1.3.1",
|
|
96
|
+
"is-unsafe": "^2.0.2",
|
|
97
97
|
"path-expression-matcher": "^1.6.2",
|
|
98
|
-
"strnum": "^2.4.
|
|
98
|
+
"strnum": "^2.4.2",
|
|
99
99
|
"xml-naming": "^0.3.0"
|
|
100
100
|
},
|
|
101
101
|
"depup": {
|
|
102
102
|
"changes": {
|
|
103
103
|
"fast-xml-builder": {
|
|
104
104
|
"from": "^1.2.0",
|
|
105
|
-
"to": "^1.3.
|
|
105
|
+
"to": "^1.3.1"
|
|
106
|
+
},
|
|
107
|
+
"is-unsafe": {
|
|
108
|
+
"from": "^2.0.0",
|
|
109
|
+
"to": "^2.0.2"
|
|
106
110
|
}
|
|
107
111
|
},
|
|
108
|
-
"depsUpdated":
|
|
112
|
+
"depsUpdated": 2,
|
|
109
113
|
"originalPackage": "fast-xml-parser",
|
|
110
|
-
"originalVersion": "5.
|
|
111
|
-
"processedAt": "2026-
|
|
114
|
+
"originalVersion": "5.11.1",
|
|
115
|
+
"processedAt": "2026-08-27T11:24:27.016Z",
|
|
112
116
|
"smokeTest": "passed"
|
|
113
117
|
}
|
|
114
118
|
}
|
package/src/fxp.d.ts
CHANGED
|
@@ -749,4 +749,6 @@ export class XMLBuilder {
|
|
|
749
749
|
export interface XMLMetaData {
|
|
750
750
|
/** The index, if available, of the character where the XML node began in the input stream. */
|
|
751
751
|
startIndex?: number;
|
|
752
|
+
/** The index, if available, of the character where the XML node ended in the input stream. */
|
|
753
|
+
endIndex?: number;
|
|
752
754
|
}
|
package/src/validator.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { isName } from './util.js';
|
|
4
4
|
|
|
5
5
|
const defaultOptions = {
|
|
6
6
|
allowBooleanAttributes: false, //A tag can have attributes without any value
|
|
@@ -310,9 +310,102 @@ function readAttributeStr(xmlData, i) {
|
|
|
310
310
|
}
|
|
311
311
|
|
|
312
312
|
/**
|
|
313
|
-
*
|
|
313
|
+
* Walk `attrStr` once, left to right, splitting it into attribute tokens.
|
|
314
|
+
*
|
|
315
|
+
* This replaces a regex that used to do the same job
|
|
316
|
+
* (`(\s*)([^\s=]+)(\s*=)?(\s*(['"])(([\s\S])*?)\5)?`). That regex led with an
|
|
317
|
+
* optional whitespace group followed by a required "non-whitespace" group.
|
|
318
|
+
* On a long run of whitespace that never resolves into an attribute name
|
|
319
|
+
* (e.g. a tag with thousands of trailing spaces before `>`), the engine
|
|
320
|
+
* backtracks the whitespace group one character at a time before giving up
|
|
321
|
+
* and moving to the next starting position — one full backtrack per
|
|
322
|
+
* position, which is quadratic in the length of the run.
|
|
323
|
+
*
|
|
324
|
+
* A single forward-only scan can never backtrack, so it can't be made slow
|
|
325
|
+
* this way no matter how much whitespace the input contains — it's always
|
|
326
|
+
* proportional to the length of the string, once.
|
|
327
|
+
*
|
|
328
|
+
* Each returned token mirrors the shape the old regex match array had, so
|
|
329
|
+
* the validation logic below (which reads token[1]..token[6]) didn't need
|
|
330
|
+
* to change:
|
|
331
|
+
* token.startIndex - where this token begins in attrStr
|
|
332
|
+
* token[1] - leading whitespace before the name
|
|
333
|
+
* token[2] - the attribute name
|
|
334
|
+
* token[3] - whitespace + '=' if present, else undefined
|
|
335
|
+
* token[4] - marker (any defined value) if a quoted value was found
|
|
336
|
+
* token[5] - the quote character used ('"' or "'")
|
|
337
|
+
* token[6] - the value's text, without the surrounding quotes
|
|
338
|
+
*
|
|
339
|
+
* A malformed leading character (e.g. a stray '=' with no name before it)
|
|
340
|
+
* is simply skipped over, one character at a time — the same outcome the
|
|
341
|
+
* old regex produced by failing to match at that position and retrying at
|
|
342
|
+
* the next one.
|
|
314
343
|
*/
|
|
315
|
-
|
|
344
|
+
function scanAttributeTokens(attrStr) {
|
|
345
|
+
const tokens = [];
|
|
346
|
+
const len = attrStr.length;
|
|
347
|
+
let i = 0;
|
|
348
|
+
|
|
349
|
+
while (i < len) {
|
|
350
|
+
const tokenStart = i;
|
|
351
|
+
|
|
352
|
+
// Leading whitespace before the name.
|
|
353
|
+
while (i < len && isWhiteSpace(attrStr[i])) i++;
|
|
354
|
+
if (i >= len) break; // trailing whitespace only — nothing left to read
|
|
355
|
+
|
|
356
|
+
if (attrStr[i] === '=') {
|
|
357
|
+
// No name before this '=' — not a valid attribute start. Move past
|
|
358
|
+
// just this one character and try again from the next position.
|
|
359
|
+
i = tokenStart + 1;
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const leadingWs = attrStr.slice(tokenStart, i);
|
|
364
|
+
|
|
365
|
+
// Attribute name — everything up to the next whitespace or '='.
|
|
366
|
+
const nameStart = i;
|
|
367
|
+
while (i < len && !isWhiteSpace(attrStr[i]) && attrStr[i] !== '=') i++;
|
|
368
|
+
const name = attrStr.slice(nameStart, i);
|
|
369
|
+
|
|
370
|
+
// Optional whitespace + '='.
|
|
371
|
+
let equalsGroup; // whitespace + '=' text, or undefined if absent
|
|
372
|
+
let j = i;
|
|
373
|
+
while (j < len && isWhiteSpace(attrStr[j])) j++;
|
|
374
|
+
if (j < len && attrStr[j] === '=') {
|
|
375
|
+
equalsGroup = attrStr.slice(i, j + 1);
|
|
376
|
+
i = j + 1;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// Optional whitespace + quoted value.
|
|
380
|
+
let quoteChar;
|
|
381
|
+
let value;
|
|
382
|
+
let k = i;
|
|
383
|
+
while (k < len && isWhiteSpace(attrStr[k])) k++;
|
|
384
|
+
if (k < len && (attrStr[k] === '"' || attrStr[k] === "'")) {
|
|
385
|
+
const valueStart = k + 1;
|
|
386
|
+
const closeIdx = attrStr.indexOf(attrStr[k], valueStart);
|
|
387
|
+
if (closeIdx !== -1) {
|
|
388
|
+
quoteChar = attrStr[k];
|
|
389
|
+
value = attrStr.slice(valueStart, closeIdx);
|
|
390
|
+
i = closeIdx + 1;
|
|
391
|
+
}
|
|
392
|
+
// No closing quote found anywhere in the rest of the string — leave
|
|
393
|
+
// quoteChar/value undefined, same as the old regex's group failing
|
|
394
|
+
// to match a backreference-less run.
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
const token = { startIndex: tokenStart };
|
|
398
|
+
token[1] = leadingWs;
|
|
399
|
+
token[2] = name;
|
|
400
|
+
token[3] = equalsGroup;
|
|
401
|
+
token[4] = quoteChar !== undefined ? true : undefined;
|
|
402
|
+
token[5] = quoteChar;
|
|
403
|
+
token[6] = value;
|
|
404
|
+
tokens.push(token);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
return tokens;
|
|
408
|
+
}
|
|
316
409
|
|
|
317
410
|
//attr, ="sd", a="amit's", a="sd"b="saf", ab cd=""
|
|
318
411
|
|
|
@@ -321,7 +414,7 @@ function validateAttributeString(attrStr, options) {
|
|
|
321
414
|
|
|
322
415
|
//if(attrStr.trim().length === 0) return true; //empty string
|
|
323
416
|
|
|
324
|
-
const matches =
|
|
417
|
+
const matches = scanAttributeTokens(attrStr);
|
|
325
418
|
const attrNames = {};
|
|
326
419
|
|
|
327
420
|
for (let i = 0; i < matches.length; i++) {
|
|
@@ -422,4 +515,4 @@ function getLineNumberForPosition(xmlData, index) {
|
|
|
422
515
|
//this function returns the position of the first character of match within attrStr
|
|
423
516
|
function getPositionFromMatch(match) {
|
|
424
517
|
return match.startIndex + match[1].length;
|
|
425
|
-
}
|
|
518
|
+
}
|
|
@@ -23,8 +23,23 @@ export default class DocTypeReader {
|
|
|
23
23
|
i = i + 9;
|
|
24
24
|
let angleBracketsCount = 1;
|
|
25
25
|
let hasBody = false, comment = false;
|
|
26
|
+
let quoteChar = null; // tracks an open SYSTEM/PUBLIC literal before the '[' body
|
|
26
27
|
let exp = "";
|
|
27
28
|
for (; i < xmlData.length; i++) {
|
|
29
|
+
// Inside a quoted external-identifier literal — XML allows '<'
|
|
30
|
+
// and '>' as plain data here, so they must not be interpreted
|
|
31
|
+
// as DOCTYPE structure until the matching quote closes.
|
|
32
|
+
if (quoteChar !== null) {
|
|
33
|
+
if (xmlData[i] === quoteChar) quoteChar = null;
|
|
34
|
+
exp += xmlData[i];
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if (!hasBody && !comment && (xmlData[i] === '"' || xmlData[i] === "'")) {
|
|
38
|
+
quoteChar = xmlData[i];
|
|
39
|
+
exp += xmlData[i];
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
|
|
28
43
|
if (xmlData[i] === '<' && !comment) { //Determine the tag type
|
|
29
44
|
if (hasBody && hasSeq(xmlData, "!ENTITY", i)) {
|
|
30
45
|
i += 7;
|
|
@@ -79,7 +94,7 @@ export default class DocTypeReader {
|
|
|
79
94
|
exp += xmlData[i];
|
|
80
95
|
}
|
|
81
96
|
}
|
|
82
|
-
if (angleBracketsCount !== 0) {
|
|
97
|
+
if (quoteChar !== null || angleBracketsCount !== 0) {
|
|
83
98
|
throw new Error(`Unclosed DOCTYPE`);
|
|
84
99
|
}
|
|
85
100
|
} else {
|
|
@@ -336,7 +336,12 @@ const parseXml = function (xmlData) {
|
|
|
336
336
|
this.matcher.pop();
|
|
337
337
|
this.isCurrentNodeStopNode = false; // Reset flag when closing tag
|
|
338
338
|
|
|
339
|
-
|
|
339
|
+
//a closing tag with no matching opening tag leaves the stack empty
|
|
340
|
+
currentNode = this.tagsNodeStack.pop() || xmlObj;//avoid recursion, set the parent tag scope
|
|
341
|
+
|
|
342
|
+
if (options.captureMetaData && currentNode) {
|
|
343
|
+
currentNode.addEndIndex(closeIndex + 1);
|
|
344
|
+
}
|
|
340
345
|
textData = "";
|
|
341
346
|
i = closeIndex;
|
|
342
347
|
} else if (c1 === 63) { //'?'
|
|
@@ -362,6 +367,11 @@ const parseXml = function (xmlData) {
|
|
|
362
367
|
childNode[":@"] = attsMap
|
|
363
368
|
}
|
|
364
369
|
this.addChild(currentNode, childNode, this.readonlyMatcher, i);
|
|
370
|
+
|
|
371
|
+
if (options.captureMetaData) {
|
|
372
|
+
// closeIndex points at '?' of the closing '?>'
|
|
373
|
+
currentNode.addEndIndex(tagData.closeIndex + 2);
|
|
374
|
+
}
|
|
365
375
|
}
|
|
366
376
|
|
|
367
377
|
|
|
@@ -526,6 +536,10 @@ const parseXml = function (xmlData) {
|
|
|
526
536
|
this.isCurrentNodeStopNode = false; // Reset flag
|
|
527
537
|
|
|
528
538
|
this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);
|
|
539
|
+
|
|
540
|
+
if (options.captureMetaData) {
|
|
541
|
+
currentNode.addEndIndex(i + 1);
|
|
542
|
+
}
|
|
529
543
|
} else {
|
|
530
544
|
//selfClosing tag
|
|
531
545
|
if (isSelfClosing) {
|
|
@@ -536,6 +550,10 @@ const parseXml = function (xmlData) {
|
|
|
536
550
|
childNode[":@"] = prefixedAttrs;
|
|
537
551
|
}
|
|
538
552
|
this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);
|
|
553
|
+
|
|
554
|
+
if (options.captureMetaData) {
|
|
555
|
+
currentNode.addEndIndex(closeIndex + 1);
|
|
556
|
+
}
|
|
539
557
|
this.matcher.pop(); // Pop self-closing tag
|
|
540
558
|
this.isCurrentNodeStopNode = false; // Reset flag
|
|
541
559
|
}
|
|
@@ -545,6 +563,10 @@ const parseXml = function (xmlData) {
|
|
|
545
563
|
childNode[":@"] = prefixedAttrs;
|
|
546
564
|
}
|
|
547
565
|
this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);
|
|
566
|
+
|
|
567
|
+
if (options.captureMetaData) {
|
|
568
|
+
currentNode.addEndIndex(result.closeIndex + 1);
|
|
569
|
+
}
|
|
548
570
|
this.matcher.pop(); // Pop unpaired tag
|
|
549
571
|
this.isCurrentNodeStopNode = false; // Reset flag
|
|
550
572
|
i = result.closeIndex;
|
package/src/xmlparser/xmlNode.js
CHANGED
|
@@ -27,12 +27,26 @@ export default class XmlNode {
|
|
|
27
27
|
this.child.push({ [node.tagname]: node.child });
|
|
28
28
|
}
|
|
29
29
|
// if requested, add the startIndex
|
|
30
|
+
this.addStartIndex(startIndex);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
addStartIndex(startIndex) {
|
|
30
34
|
if (startIndex !== undefined) {
|
|
31
35
|
// Note: for now we just overwrite the metadata. If we had more complex metadata,
|
|
32
36
|
// we might need to do an object append here: metadata = { ...metadata, startIndex }
|
|
33
37
|
this.child[this.child.length - 1][METADATA_SYMBOL] = { startIndex };
|
|
34
38
|
}
|
|
35
39
|
}
|
|
40
|
+
|
|
41
|
+
addEndIndex(endIndex) {
|
|
42
|
+
const lastChild = this.child[this.child.length - 1];
|
|
43
|
+
// endIndex is write-once: when updateTag drops a node, the last child is a
|
|
44
|
+
// previously completed sibling whose endIndex must not be overwritten
|
|
45
|
+
if (lastChild !== undefined && lastChild[METADATA_SYMBOL] !== undefined
|
|
46
|
+
&& lastChild[METADATA_SYMBOL].endIndex === undefined) {
|
|
47
|
+
lastChild[METADATA_SYMBOL].endIndex = endIndex;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
36
50
|
/** symbol used for metadata */
|
|
37
51
|
static getMetaDataSymbol() {
|
|
38
52
|
return METADATA_SYMBOL;
|