compose mime
This commit is contained in:
parent
bb80b267ff
commit
21f00d94a7
1
node_modules/.bin/fxparser
generated
vendored
Symbolic link
1
node_modules/.bin/fxparser
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../fast-xml-parser/src/cli/cli.js
|
||||||
269
node_modules/.package-lock.json
generated
vendored
269
node_modules/.package-lock.json
generated
vendored
@ -39,6 +39,15 @@
|
|||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@buttercup/fetch": {
|
||||||
|
"version": "0.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@buttercup/fetch/-/fetch-0.2.1.tgz",
|
||||||
|
"integrity": "sha512-sCgECOx8wiqY8NN1xN22BqqKzXYIG2AicNLlakOAI4f0WgyLVUbAigMf8CZhBtJxdudTcB1gD5lciqi44jwJvg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optionalDependencies": {
|
||||||
|
"node-fetch": "^3.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@csstools/color-helpers": {
|
"node_modules/@csstools/color-helpers": {
|
||||||
"version": "5.0.2",
|
"version": "5.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.2.tgz",
|
||||||
@ -2650,6 +2659,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/base-64": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/base64-js": {
|
"node_modules/base64-js": {
|
||||||
"version": "1.5.1",
|
"version": "1.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||||
@ -2766,6 +2781,12 @@
|
|||||||
"node": ">=10.16.0"
|
"node": ">=10.16.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/byte-length": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/byte-length/-/byte-length-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-ovBpjmsgd/teRmgcPh23d4gJvxDoXtAzEL9xTfMU8Yc2kqCDb7L9jAG0XHl1nzuGl+h3ebCIF1i62UFyA9V/2Q==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/camelcase-css": {
|
"node_modules/camelcase-css": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
|
||||||
@ -2793,6 +2814,15 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"node_modules/charenc": {
|
||||||
|
"version": "0.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz",
|
||||||
|
"integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==",
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/chokidar": {
|
"node_modules/chokidar": {
|
||||||
"version": "3.6.0",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
|
||||||
@ -2977,6 +3007,15 @@
|
|||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/crypt": {
|
||||||
|
"version": "0.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
|
||||||
|
"integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==",
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cssesc": {
|
"node_modules/cssesc": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
|
||||||
@ -3116,6 +3155,15 @@
|
|||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/data-uri-to-buffer": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/data-urls": {
|
"node_modules/data-urls": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz",
|
||||||
@ -3445,6 +3493,24 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/fast-xml-parser": {
|
||||||
|
"version": "4.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.3.tgz",
|
||||||
|
"integrity": "sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/NaturalIntelligence"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"strnum": "^1.1.1"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"fxparser": "src/cli/cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fastq": {
|
"node_modules/fastq": {
|
||||||
"version": "1.18.0",
|
"version": "1.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz",
|
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz",
|
||||||
@ -3453,6 +3519,29 @@
|
|||||||
"reusify": "^1.0.4"
|
"reusify": "^1.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/fetch-blob": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/jimmywarting"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "paypal",
|
||||||
|
"url": "https://paypal.me/jimmywarting"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"node-domexception": "^1.0.0",
|
||||||
|
"web-streams-polyfill": "^3.0.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^12.20 || >= 14.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fill-range": {
|
"node_modules/fill-range": {
|
||||||
"version": "7.1.1",
|
"version": "7.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||||
@ -3479,6 +3568,18 @@
|
|||||||
"url": "https://github.com/sponsors/isaacs"
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/formdata-polyfill": {
|
||||||
|
"version": "4.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
|
||||||
|
"integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"fetch-blob": "^3.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.20.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fraction.js": {
|
"node_modules/fraction.js": {
|
||||||
"version": "4.3.7",
|
"version": "4.3.7",
|
||||||
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
|
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
|
||||||
@ -3584,6 +3685,12 @@
|
|||||||
"he": "bin/he"
|
"he": "bin/he"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hot-patcher": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/hot-patcher/-/hot-patcher-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-ECg1JFG0YzehicQaogenlcs2qg6WsXQsxtnbr1i696u5tLUjtJdQAh0u2g0Q5YV45f263Ta1GnUJsc8WIfJf4Q==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/html-encoding-sniffer": {
|
"node_modules/html-encoding-sniffer": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz",
|
||||||
@ -3792,6 +3899,12 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/is-buffer": {
|
||||||
|
"version": "1.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
|
||||||
|
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/is-core-module": {
|
"node_modules/is-core-module": {
|
||||||
"version": "2.16.1",
|
"version": "2.16.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
|
||||||
@ -3961,6 +4074,12 @@
|
|||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/layerr": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/layerr/-/layerr-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-tv754Ki2dXpPVApOrjTyRo4/QegVb9eVFq4mjqp4+NM5NaX7syQvN5BBNfV/ZpAHCEHV24XdUVrBAoka4jt3pA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/leac": {
|
"node_modules/leac": {
|
||||||
"version": "0.6.0",
|
"version": "0.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/leac/-/leac-0.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/leac/-/leac-0.6.0.tgz",
|
||||||
@ -4093,6 +4212,17 @@
|
|||||||
"libqp": "2.1.1"
|
"libqp": "2.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/md5": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==",
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"charenc": "0.0.2",
|
||||||
|
"crypt": "0.0.2",
|
||||||
|
"is-buffer": "~1.1.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/merge2": {
|
"node_modules/merge2": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
||||||
@ -4189,6 +4319,12 @@
|
|||||||
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/nested-property": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/nested-property/-/nested-property-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-yFehXNWRs4cM0+dz7QxCd06hTbWbSkV0ISsqBfkntU6TOY4Qm3Q88fRRLOddkGh2Qq6dZvnKVAahfhjcUvLnyA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/next": {
|
"node_modules/next": {
|
||||||
"version": "15.3.1",
|
"version": "15.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/next/-/next-15.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/next/-/next-15.3.1.tgz",
|
||||||
@ -4311,6 +4447,44 @@
|
|||||||
"node": "^10 || ^12 || >=14"
|
"node": "^10 || ^12 || >=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/node-domexception": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
|
||||||
|
"deprecated": "Use your platform's native DOMException instead",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/jimmywarting"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://paypal.me/jimmywarting"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/node-fetch": {
|
||||||
|
"version": "3.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
|
||||||
|
"integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"data-uri-to-buffer": "^4.0.0",
|
||||||
|
"fetch-blob": "^3.1.4",
|
||||||
|
"formdata-polyfill": "^4.0.10"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/node-fetch"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/node-gettext": {
|
"node_modules/node-gettext": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/node-gettext/-/node-gettext-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/node-gettext/-/node-gettext-3.0.0.tgz",
|
||||||
@ -4480,6 +4654,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
|
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/path-posix": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-posix/-/path-posix-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-1gJ0WpNIiYcQydgg3Ed8KzvIqTsDpNwq+cjBCssvBtuTWjEqY1AW+i+OepiEMqDCzyro9B2sLAe4RBPajMYFiA==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
"node_modules/path-scurry": {
|
"node_modules/path-scurry": {
|
||||||
"version": "1.11.1",
|
"version": "1.11.1",
|
||||||
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
|
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
|
||||||
@ -5016,6 +5196,12 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/querystringify": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/queue-microtask": {
|
"node_modules/queue-microtask": {
|
||||||
"version": "1.2.3",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
||||||
@ -5336,6 +5522,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
|
||||||
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
|
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/requires-port": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/resolve": {
|
"node_modules/resolve": {
|
||||||
"version": "1.22.10",
|
"version": "1.22.10",
|
||||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
|
||||||
@ -5709,6 +5901,18 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/strnum": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/NaturalIntelligence"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/styled-jsx": {
|
"node_modules/styled-jsx": {
|
||||||
"version": "5.1.6",
|
"version": "5.1.6",
|
||||||
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz",
|
||||||
@ -5988,6 +6192,25 @@
|
|||||||
"browserslist": ">= 4.21.0"
|
"browserslist": ">= 4.21.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/url-join": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/url-join/-/url-join-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/url-parse": {
|
||||||
|
"version": "1.5.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
|
||||||
|
"integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"querystringify": "^2.1.1",
|
||||||
|
"requires-port": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/use-callback-ref": {
|
"node_modules/use-callback-ref": {
|
||||||
"version": "1.3.3",
|
"version": "1.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz",
|
||||||
@ -6132,6 +6355,52 @@
|
|||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/web-streams-polyfill": {
|
||||||
|
"version": "3.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
|
||||||
|
"integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/webdav": {
|
||||||
|
"version": "5.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/webdav/-/webdav-5.8.0.tgz",
|
||||||
|
"integrity": "sha512-iuFG7NamJ41Oshg4930iQgfIpRrUiatPWIekeznYgEf2EOraTRcDPTjy7gIOMtkdpKTaqPk1E68NO5PAGtJahA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@buttercup/fetch": "^0.2.1",
|
||||||
|
"base-64": "^1.0.0",
|
||||||
|
"byte-length": "^1.0.2",
|
||||||
|
"entities": "^6.0.0",
|
||||||
|
"fast-xml-parser": "^4.5.1",
|
||||||
|
"hot-patcher": "^2.0.1",
|
||||||
|
"layerr": "^3.0.0",
|
||||||
|
"md5": "^2.3.0",
|
||||||
|
"minimatch": "^9.0.5",
|
||||||
|
"nested-property": "^4.0.0",
|
||||||
|
"node-fetch": "^3.3.2",
|
||||||
|
"path-posix": "^1.0.0",
|
||||||
|
"url-join": "^5.0.0",
|
||||||
|
"url-parse": "^1.5.10"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/webdav/node_modules/entities": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==",
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/webidl-conversions": {
|
"node_modules/webidl-conversions": {
|
||||||
"version": "7.0.0",
|
"version": "7.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
|
||||||
|
|||||||
21
node_modules/@buttercup/fetch/LICENSE
generated
vendored
Normal file
21
node_modules/@buttercup/fetch/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2023 Buttercup
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
44
node_modules/@buttercup/fetch/README.md
generated
vendored
Normal file
44
node_modules/@buttercup/fetch/README.md
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# Fetch
|
||||||
|
> Fetch adapter for cross-platform use.
|
||||||
|
|
||||||
|
[](https://buttercup.pw) [](https://www.npmjs.com/package/@buttercup/fetch) 
|
||||||
|
|
||||||
|
## About
|
||||||
|
|
||||||
|
This library exports `fetch` in various environments, such as within a browser or under NodeJS:
|
||||||
|
|
||||||
|
* Browsers get the native `window.fetch`
|
||||||
|
* NodeJS gets `node-fetch`
|
||||||
|
|
||||||
|
_This library was designed to be used primarily within Buttercup and its supporting libraries: Features and fixes implemented here will be oriented to furthering Buttercup's goals, and unnessarily changes may be rejected due to that._
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
For browser use you need only install this library:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
npm install @buttercup/fetch --save-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
For NodeJS use you must also install `node-fetch`:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
npm install @buttercup/fetch node-fetch --save
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
You can import the various components related to fetch regardless of the entry your application uses:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import {
|
||||||
|
fetch,
|
||||||
|
Headers,
|
||||||
|
Request,
|
||||||
|
Response
|
||||||
|
} from "@buttercup/fetch";
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
const res = await fetch("https://...");
|
||||||
|
```
|
||||||
20
node_modules/@buttercup/fetch/dist/index.browser.d.ts
generated
vendored
Normal file
20
node_modules/@buttercup/fetch/dist/index.browser.d.ts
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
declare global {
|
||||||
|
var WorkerGlobalScope: any;
|
||||||
|
}
|
||||||
|
export declare const fetch: any;
|
||||||
|
export declare const Headers: {
|
||||||
|
new (init?: HeadersInit): Headers;
|
||||||
|
prototype: Headers;
|
||||||
|
};
|
||||||
|
export declare const Request: {
|
||||||
|
new (input: globalThis.RequestInfo | URL, init?: globalThis.RequestInit): Request;
|
||||||
|
prototype: Request;
|
||||||
|
};
|
||||||
|
export declare const Response: {
|
||||||
|
new (body?: BodyInit, init?: ResponseInit): Response;
|
||||||
|
prototype: Response;
|
||||||
|
error(): Response;
|
||||||
|
redirect(url: string | URL, status?: number): Response;
|
||||||
|
};
|
||||||
|
export type RequestInfo = Parameters<typeof window.fetch>[0];
|
||||||
|
export type RequestInit = Parameters<typeof window.fetch>[1];
|
||||||
11
node_modules/@buttercup/fetch/dist/index.browser.js
generated
vendored
Normal file
11
node_modules/@buttercup/fetch/dist/index.browser.js
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
const inWebWorker = typeof WorkerGlobalScope !== "undefined" &&
|
||||||
|
self instanceof WorkerGlobalScope;
|
||||||
|
const root = inWebWorker
|
||||||
|
? self
|
||||||
|
: typeof window !== "undefined"
|
||||||
|
? window
|
||||||
|
: globalThis;
|
||||||
|
export const fetch = root.fetch.bind(root);
|
||||||
|
export const Headers = root.Headers;
|
||||||
|
export const Request = root.Request;
|
||||||
|
export const Response = root.Response;
|
||||||
2
node_modules/@buttercup/fetch/dist/index.node.d.ts
generated
vendored
Normal file
2
node_modules/@buttercup/fetch/dist/index.node.d.ts
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import fetch, { Headers, Request, RequestInfo, RequestInit, Response } from "node-fetch";
|
||||||
|
export { fetch, Headers, Request, RequestInfo, RequestInit, Response };
|
||||||
2
node_modules/@buttercup/fetch/dist/index.node.js
generated
vendored
Normal file
2
node_modules/@buttercup/fetch/dist/index.node.js
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import fetch, { Headers, Request, Response, } from "node-fetch";
|
||||||
|
export { fetch, Headers, Request, Response };
|
||||||
65
node_modules/@buttercup/fetch/package.json
generated
vendored
Normal file
65
node_modules/@buttercup/fetch/package.json
generated
vendored
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
{
|
||||||
|
"name": "@buttercup/fetch",
|
||||||
|
"version": "0.2.1",
|
||||||
|
"description": "Fetch adapter for cross-platform use.",
|
||||||
|
"type": "module",
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"browser": "./dist/index.browser.js",
|
||||||
|
"default": "./dist/index.node.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"react-native": "./dist/index.browser.js",
|
||||||
|
"types": "./dist/index.node.d.ts",
|
||||||
|
"scripts": {
|
||||||
|
"build": "npm run clean && tsc",
|
||||||
|
"clean": "rimraf dist",
|
||||||
|
"format": "prettier --write \"{source,test}/**/*.{js,ts}\"",
|
||||||
|
"prepublishOnly": "npm run build",
|
||||||
|
"test": "npm run test:node && npm run test:format",
|
||||||
|
"test:format": "prettier --check \"{source,test}/**/*.{js,ts}\"",
|
||||||
|
"test:node": "npm run build && mocha 'test/node/**.spec.js'"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"./dist/**/*"
|
||||||
|
],
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/buttercup/fetch.git"
|
||||||
|
},
|
||||||
|
"lint-staged": {
|
||||||
|
"{source,test}/**/*.{js,ts}": [
|
||||||
|
"prettier --write"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"husky": {
|
||||||
|
"hooks": {
|
||||||
|
"pre-commit": "lint-staged"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"fetch",
|
||||||
|
"request"
|
||||||
|
],
|
||||||
|
"author": "Perry Mitchell <perry@perrymitchell.net>",
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/buttercup/fetch/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/buttercup/fetch#readme",
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^18.11.18",
|
||||||
|
"chai": "^4.3.7",
|
||||||
|
"husky": "^4.3.8",
|
||||||
|
"json-server": "^0.17.1",
|
||||||
|
"lint-staged": "^13.1.0",
|
||||||
|
"mocha": "^10.2.0",
|
||||||
|
"prettier": "^2.8.3",
|
||||||
|
"rimraf": "^4.1.2",
|
||||||
|
"typescript": "^4.9.5",
|
||||||
|
"url-join": "^5.0.0"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"node-fetch": "^3.3.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
20
node_modules/base-64/LICENSE-MIT.txt
generated
vendored
Normal file
20
node_modules/base-64/LICENSE-MIT.txt
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
Copyright Mathias Bynens <https://mathiasbynens.be/>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
112
node_modules/base-64/README.md
generated
vendored
Normal file
112
node_modules/base-64/README.md
generated
vendored
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
# base64 [](https://travis-ci.org/mathiasbynens/base64) [](https://coveralls.io/r/mathiasbynens/base64)
|
||||||
|
|
||||||
|
_base64_ is a robust base64 encoder/decoder that is fully compatible with [`atob()` and `btoa()`](https://html.spec.whatwg.org/multipage/webappapis.html#atob), written in JavaScript. The base64-encoding and -decoding algorithms it uses are fully [RFC 4648](https://tools.ietf.org/html/rfc4648#section-4) compliant.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Via [npm](https://www.npmjs.com/):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install base-64
|
||||||
|
```
|
||||||
|
|
||||||
|
In a browser:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script src="base64.js"></script>
|
||||||
|
```
|
||||||
|
|
||||||
|
In [Narwhal](http://narwhaljs.org/), [Node.js](https://nodejs.org/), and [RingoJS](http://ringojs.org/):
|
||||||
|
|
||||||
|
```js
|
||||||
|
var base64 = require('base-64');
|
||||||
|
```
|
||||||
|
|
||||||
|
In [Rhino](http://www.mozilla.org/rhino/):
|
||||||
|
|
||||||
|
```js
|
||||||
|
load('base64.js');
|
||||||
|
```
|
||||||
|
|
||||||
|
Using an AMD loader like [RequireJS](http://requirejs.org/):
|
||||||
|
|
||||||
|
```js
|
||||||
|
require(
|
||||||
|
{
|
||||||
|
'paths': {
|
||||||
|
'base64': 'path/to/base64'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
['base64'],
|
||||||
|
function(base64) {
|
||||||
|
console.log(base64);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### `base64.version`
|
||||||
|
|
||||||
|
A string representing the semantic version number.
|
||||||
|
|
||||||
|
### `base64.encode(input)`
|
||||||
|
|
||||||
|
This function takes a byte string (the `input` parameter) and encodes it according to base64. The input data must be in the form of a string containing only characters in the range from U+0000 to U+00FF, each representing a binary byte with values `0x00` to `0xFF`. The `base64.encode()` function is designed to be fully compatible with [`btoa()` as described in the HTML Standard](https://html.spec.whatwg.org/multipage/webappapis.html#dom-windowbase64-btoa).
|
||||||
|
|
||||||
|
```js
|
||||||
|
var encodedData = base64.encode(input);
|
||||||
|
```
|
||||||
|
|
||||||
|
To base64-encode any Unicode string, [encode it as UTF-8 first](https://github.com/mathiasbynens/utf8.js#utf8encodestring):
|
||||||
|
|
||||||
|
```js
|
||||||
|
var base64 = require('base-64');
|
||||||
|
var utf8 = require('utf8');
|
||||||
|
|
||||||
|
var text = 'foo © bar 𝌆 baz';
|
||||||
|
var bytes = utf8.encode(text);
|
||||||
|
var encoded = base64.encode(bytes);
|
||||||
|
console.log(encoded);
|
||||||
|
// → 'Zm9vIMKpIGJhciDwnYyGIGJheg=='
|
||||||
|
```
|
||||||
|
|
||||||
|
### `base64.decode(input)`
|
||||||
|
|
||||||
|
This function takes a base64-encoded string (the `input` parameter) and decodes it. The return value is in the form of a string containing only characters in the range from U+0000 to U+00FF, each representing a binary byte with values `0x00` to `0xFF`. The `base64.decode()` function is designed to be fully compatible with [`atob()` as described in the HTML Standard](https://html.spec.whatwg.org/multipage/webappapis.html#dom-windowbase64-atob).
|
||||||
|
|
||||||
|
```js
|
||||||
|
var decodedData = base64.decode(encodedData);
|
||||||
|
```
|
||||||
|
|
||||||
|
To base64-decode UTF-8-encoded data back into a Unicode string, [UTF-8-decode it](https://github.com/mathiasbynens/utf8.js#utf8decodebytestring) after base64-decoding it:
|
||||||
|
|
||||||
|
```js
|
||||||
|
var encoded = 'Zm9vIMKpIGJhciDwnYyGIGJheg==';
|
||||||
|
var bytes = base64.decode(encoded);
|
||||||
|
var text = utf8.decode(bytes);
|
||||||
|
console.log(text);
|
||||||
|
// → 'foo © bar 𝌆 baz'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
_base64_ is designed to work in at least Node.js v0.10.0, Narwhal 0.3.2, RingoJS 0.8-0.9, PhantomJS 1.9.0, Rhino 1.7RC4, as well as old and modern versions of Chrome, Firefox, Safari, Opera, and Internet Explorer.
|
||||||
|
|
||||||
|
## Unit tests & code coverage
|
||||||
|
|
||||||
|
After cloning this repository, run `npm install` to install the dependencies needed for development and testing. You may want to install Istanbul _globally_ using `npm install istanbul -g`.
|
||||||
|
|
||||||
|
Once that’s done, you can run the unit tests in Node using `npm test` or `node tests/tests.js`. To run the tests in Rhino, Ringo, Narwhal, and web browsers as well, use `grunt test`.
|
||||||
|
|
||||||
|
To generate the code coverage report, use `grunt cover`.
|
||||||
|
|
||||||
|
## Author
|
||||||
|
|
||||||
|
| [](https://twitter.com/mathias "Follow @mathias on Twitter") |
|
||||||
|
|---|
|
||||||
|
| [Mathias Bynens](https://mathiasbynens.be/) |
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
_base64_ is available under the [MIT](https://mths.be/mit) license.
|
||||||
164
node_modules/base-64/base64.js
generated
vendored
Normal file
164
node_modules/base-64/base64.js
generated
vendored
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
/*! https://mths.be/base64 v1.0.0 by @mathias | MIT license */
|
||||||
|
;(function(root) {
|
||||||
|
|
||||||
|
// Detect free variables `exports`.
|
||||||
|
var freeExports = typeof exports == 'object' && exports;
|
||||||
|
|
||||||
|
// Detect free variable `module`.
|
||||||
|
var freeModule = typeof module == 'object' && module &&
|
||||||
|
module.exports == freeExports && module;
|
||||||
|
|
||||||
|
// Detect free variable `global`, from Node.js or Browserified code, and use
|
||||||
|
// it as `root`.
|
||||||
|
var freeGlobal = typeof global == 'object' && global;
|
||||||
|
if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
|
||||||
|
root = freeGlobal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
var InvalidCharacterError = function(message) {
|
||||||
|
this.message = message;
|
||||||
|
};
|
||||||
|
InvalidCharacterError.prototype = new Error;
|
||||||
|
InvalidCharacterError.prototype.name = 'InvalidCharacterError';
|
||||||
|
|
||||||
|
var error = function(message) {
|
||||||
|
// Note: the error messages used throughout this file match those used by
|
||||||
|
// the native `atob`/`btoa` implementation in Chromium.
|
||||||
|
throw new InvalidCharacterError(message);
|
||||||
|
};
|
||||||
|
|
||||||
|
var TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
||||||
|
// http://whatwg.org/html/common-microsyntaxes.html#space-character
|
||||||
|
var REGEX_SPACE_CHARACTERS = /[\t\n\f\r ]/g;
|
||||||
|
|
||||||
|
// `decode` is designed to be fully compatible with `atob` as described in the
|
||||||
|
// HTML Standard. http://whatwg.org/html/webappapis.html#dom-windowbase64-atob
|
||||||
|
// The optimized base64-decoding algorithm used is based on @atk’s excellent
|
||||||
|
// implementation. https://gist.github.com/atk/1020396
|
||||||
|
var decode = function(input) {
|
||||||
|
input = String(input)
|
||||||
|
.replace(REGEX_SPACE_CHARACTERS, '');
|
||||||
|
var length = input.length;
|
||||||
|
if (length % 4 == 0) {
|
||||||
|
input = input.replace(/==?$/, '');
|
||||||
|
length = input.length;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
length % 4 == 1 ||
|
||||||
|
// http://whatwg.org/C#alphanumeric-ascii-characters
|
||||||
|
/[^+a-zA-Z0-9/]/.test(input)
|
||||||
|
) {
|
||||||
|
error(
|
||||||
|
'Invalid character: the string to be decoded is not correctly encoded.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
var bitCounter = 0;
|
||||||
|
var bitStorage;
|
||||||
|
var buffer;
|
||||||
|
var output = '';
|
||||||
|
var position = -1;
|
||||||
|
while (++position < length) {
|
||||||
|
buffer = TABLE.indexOf(input.charAt(position));
|
||||||
|
bitStorage = bitCounter % 4 ? bitStorage * 64 + buffer : buffer;
|
||||||
|
// Unless this is the first of a group of 4 characters…
|
||||||
|
if (bitCounter++ % 4) {
|
||||||
|
// …convert the first 8 bits to a single ASCII character.
|
||||||
|
output += String.fromCharCode(
|
||||||
|
0xFF & bitStorage >> (-2 * bitCounter & 6)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
};
|
||||||
|
|
||||||
|
// `encode` is designed to be fully compatible with `btoa` as described in the
|
||||||
|
// HTML Standard: http://whatwg.org/html/webappapis.html#dom-windowbase64-btoa
|
||||||
|
var encode = function(input) {
|
||||||
|
input = String(input);
|
||||||
|
if (/[^\0-\xFF]/.test(input)) {
|
||||||
|
// Note: no need to special-case astral symbols here, as surrogates are
|
||||||
|
// matched, and the input is supposed to only contain ASCII anyway.
|
||||||
|
error(
|
||||||
|
'The string to be encoded contains characters outside of the ' +
|
||||||
|
'Latin1 range.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
var padding = input.length % 3;
|
||||||
|
var output = '';
|
||||||
|
var position = -1;
|
||||||
|
var a;
|
||||||
|
var b;
|
||||||
|
var c;
|
||||||
|
var buffer;
|
||||||
|
// Make sure any padding is handled outside of the loop.
|
||||||
|
var length = input.length - padding;
|
||||||
|
|
||||||
|
while (++position < length) {
|
||||||
|
// Read three bytes, i.e. 24 bits.
|
||||||
|
a = input.charCodeAt(position) << 16;
|
||||||
|
b = input.charCodeAt(++position) << 8;
|
||||||
|
c = input.charCodeAt(++position);
|
||||||
|
buffer = a + b + c;
|
||||||
|
// Turn the 24 bits into four chunks of 6 bits each, and append the
|
||||||
|
// matching character for each of them to the output.
|
||||||
|
output += (
|
||||||
|
TABLE.charAt(buffer >> 18 & 0x3F) +
|
||||||
|
TABLE.charAt(buffer >> 12 & 0x3F) +
|
||||||
|
TABLE.charAt(buffer >> 6 & 0x3F) +
|
||||||
|
TABLE.charAt(buffer & 0x3F)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (padding == 2) {
|
||||||
|
a = input.charCodeAt(position) << 8;
|
||||||
|
b = input.charCodeAt(++position);
|
||||||
|
buffer = a + b;
|
||||||
|
output += (
|
||||||
|
TABLE.charAt(buffer >> 10) +
|
||||||
|
TABLE.charAt((buffer >> 4) & 0x3F) +
|
||||||
|
TABLE.charAt((buffer << 2) & 0x3F) +
|
||||||
|
'='
|
||||||
|
);
|
||||||
|
} else if (padding == 1) {
|
||||||
|
buffer = input.charCodeAt(position);
|
||||||
|
output += (
|
||||||
|
TABLE.charAt(buffer >> 2) +
|
||||||
|
TABLE.charAt((buffer << 4) & 0x3F) +
|
||||||
|
'=='
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
};
|
||||||
|
|
||||||
|
var base64 = {
|
||||||
|
'encode': encode,
|
||||||
|
'decode': decode,
|
||||||
|
'version': '1.0.0'
|
||||||
|
};
|
||||||
|
|
||||||
|
// Some AMD build optimizers, like r.js, check for specific condition patterns
|
||||||
|
// like the following:
|
||||||
|
if (
|
||||||
|
typeof define == 'function' &&
|
||||||
|
typeof define.amd == 'object' &&
|
||||||
|
define.amd
|
||||||
|
) {
|
||||||
|
define(function() {
|
||||||
|
return base64;
|
||||||
|
});
|
||||||
|
} else if (freeExports && !freeExports.nodeType) {
|
||||||
|
if (freeModule) { // in Node.js or RingoJS v0.8.0+
|
||||||
|
freeModule.exports = base64;
|
||||||
|
} else { // in Narwhal or RingoJS v0.7.0-
|
||||||
|
for (var key in base64) {
|
||||||
|
base64.hasOwnProperty(key) && (freeExports[key] = base64[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { // in Rhino or a web browser
|
||||||
|
root.base64 = base64;
|
||||||
|
}
|
||||||
|
|
||||||
|
}(this));
|
||||||
43
node_modules/base-64/package.json
generated
vendored
Normal file
43
node_modules/base-64/package.json
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"name": "base-64",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "A robust base64 encoder/decoder that is fully compatible with `atob()` and `btoa()`, written in JavaScript.",
|
||||||
|
"homepage": "https://mths.be/base64",
|
||||||
|
"main": "base64.js",
|
||||||
|
"keywords": [
|
||||||
|
"codec",
|
||||||
|
"decoder",
|
||||||
|
"encoder",
|
||||||
|
"base64",
|
||||||
|
"atob",
|
||||||
|
"btoa"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"author": {
|
||||||
|
"name": "Mathias Bynens",
|
||||||
|
"url": "https://mathiasbynens.be/"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/mathiasbynens/base64.git"
|
||||||
|
},
|
||||||
|
"bugs": "https://github.com/mathiasbynens/base64/issues",
|
||||||
|
"files": [
|
||||||
|
"LICENSE-MIT.txt",
|
||||||
|
"base64.js"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"test": "mocha tests/tests.js",
|
||||||
|
"build": "grunt build"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"coveralls": "^2.11.4",
|
||||||
|
"grunt": "^0.4.5",
|
||||||
|
"grunt-cli": "^1.3.2",
|
||||||
|
"grunt-shell": "^1.1.2",
|
||||||
|
"grunt-template": "^0.2.3",
|
||||||
|
"istanbul": "^0.4.0",
|
||||||
|
"mocha": "^6.2.0",
|
||||||
|
"regenerate": "^1.2.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
66
node_modules/byte-length/README.md
generated
vendored
Normal file
66
node_modules/byte-length/README.md
generated
vendored
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<h1 align="center">
|
||||||
|
<!-- Logo -->
|
||||||
|
<br/>
|
||||||
|
Byte-Length
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<!-- Stability -->
|
||||||
|
<a href="https://nodejs.org/api/documentation.html#documentation_stability_index">
|
||||||
|
<img src="https://img.shields.io/badge/stability-stable-brightgreen.svg" alt="API Stability"/>
|
||||||
|
</a>
|
||||||
|
<!-- TypeScript -->
|
||||||
|
<a href="http://typescriptlang.org">
|
||||||
|
<img src="https://img.shields.io/badge/%3C%2F%3E-typescript-blue.svg" alt="TypeScript"/>
|
||||||
|
</a>
|
||||||
|
<!-- Prettier -->
|
||||||
|
<a href="https://github.com/prettier/prettier">
|
||||||
|
<img src="https://img.shields.io/badge/styled_with-prettier-ff69b4.svg" alt="Styled with prettier"/>
|
||||||
|
</a>
|
||||||
|
<!-- Travis build -->
|
||||||
|
<a href="https://travis-ci.org/DylanPiercey/byte-length">
|
||||||
|
<img src="https://img.shields.io/travis/DylanPiercey/byte-length.svg" alt="Build status"/>
|
||||||
|
</a>
|
||||||
|
<!-- Coveralls coverage -->
|
||||||
|
<a href="https://coveralls.io/github/DylanPiercey/byte-length">
|
||||||
|
<img src="https://img.shields.io/coveralls/DylanPiercey/byte-length.svg" alt="Test Coverage"/>
|
||||||
|
</a>
|
||||||
|
<!-- NPM version -->
|
||||||
|
<a href="https://npmjs.org/package/byte-length">
|
||||||
|
<img src="https://img.shields.io/npm/v/byte-length.svg" alt="NPM Version"/>
|
||||||
|
</a>
|
||||||
|
<!-- Downloads -->
|
||||||
|
<a href="https://npmjs.org/package/byte-length">
|
||||||
|
<img src="https://img.shields.io/npm/dm/byte-length.svg" alt="Downloads"/>
|
||||||
|
</a>
|
||||||
|
<!-- Size -->
|
||||||
|
<a href="https://npmjs.org/package/byte-length">
|
||||||
|
<img src="https://img.shields.io/badge/size-422b-green.svg" alt="Browser Bundle Size"/>
|
||||||
|
</a>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
Calculate the real byte length of any string.
|
||||||
|
|
||||||
|
# Why
|
||||||
|
In node many will use `Buffer.byteLength`, however including the entire buffer shim in the browser just for getting the byte length of a string is not very conservative.
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
|
||||||
|
```console
|
||||||
|
npm install byte-length
|
||||||
|
```
|
||||||
|
|
||||||
|
# Example
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { byteLength } from "byte-length";
|
||||||
|
|
||||||
|
byteLength("hello"); //-> 5
|
||||||
|
byteLength("😀"); //-> 4
|
||||||
|
byteLength("fullwidth characters"); //-> 60
|
||||||
|
```
|
||||||
|
|
||||||
|
### Contributions
|
||||||
|
|
||||||
|
* Use `npm test` to run tests.
|
||||||
|
|
||||||
|
Please feel free to create a PR!
|
||||||
4
node_modules/byte-length/dist/index.d.ts
generated
vendored
Normal file
4
node_modules/byte-length/dist/index.d.ts
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export declare function byteLength(str: string | {
|
||||||
|
toString(): string;
|
||||||
|
[x: string]: any;
|
||||||
|
}): number;
|
||||||
27
node_modules/byte-length/dist/index.js
generated
vendored
Normal file
27
node_modules/byte-length/dist/index.js
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
/*
|
||||||
|
* Calculate the byte lengths for utf8 encoded strings.
|
||||||
|
*/
|
||||||
|
function byteLength(str) {
|
||||||
|
if (!str) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
str = str.toString();
|
||||||
|
var len = str.length;
|
||||||
|
for (var i = str.length; i--;) {
|
||||||
|
var code = str.charCodeAt(i);
|
||||||
|
if (0xdc00 <= code && code <= 0xdfff) {
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
if (0x7f < code && code <= 0x7ff) {
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
else if (0x7ff < code && code <= 0xffff) {
|
||||||
|
len += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
exports.byteLength = byteLength;
|
||||||
|
//# sourceMappingURL=index.js.map
|
||||||
1
node_modules/byte-length/dist/index.js.map
generated
vendored
Normal file
1
node_modules/byte-length/dist/index.js.map
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAAA;;GAEG;AACH,oBACE,GAAsD;IAEtD,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACT,MAAM,CAAC,CAAC,CAAC;IACX,CAAC;IAED,GAAG,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC;IACrB,IAAI,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC;IAErB,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,GAAI,CAAC;QAC/B,IAAM,IAAI,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAC/B,EAAE,CAAC,CAAC,MAAM,IAAI,IAAI,IAAI,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC;YACrC,CAAC,EAAE,CAAC;QACN,CAAC;QAED,EAAE,CAAC,CAAC,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC;YACjC,GAAG,EAAE,CAAC;QACR,CAAC;QAAC,IAAI,CAAC,EAAE,CAAC,CAAC,KAAK,GAAG,IAAI,IAAI,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC;YAC1C,GAAG,IAAI,CAAC,CAAC;QACX,CAAC;IACH,CAAC;IAED,MAAM,CAAC,GAAG,CAAC;AACb,CAAC;AAxBD,gCAwBC"}
|
||||||
54
node_modules/byte-length/package.json
generated
vendored
Normal file
54
node_modules/byte-length/package.json
generated
vendored
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
{
|
||||||
|
"name": "byte-length",
|
||||||
|
"description": "Get the real byte length of a string.",
|
||||||
|
"version": "1.0.2",
|
||||||
|
"author": "Dylan Piercey <pierceydylan@gmail.com>",
|
||||||
|
"bugs": "https://github.com/DylanPiercey/byte-length/issues",
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/mocha": "^2.2.43",
|
||||||
|
"@types/node": "^8.0.34",
|
||||||
|
"coveralls": "^3.0.0",
|
||||||
|
"husky": "^0.14.3",
|
||||||
|
"lint-staged": "^4.2.3",
|
||||||
|
"mocha": "^4.0.1",
|
||||||
|
"nyc": "^11.2.1",
|
||||||
|
"prettier": "^1.7.4",
|
||||||
|
"ts-node": "^3.3.0",
|
||||||
|
"tslint": "^5.7.0",
|
||||||
|
"tslint-config-prettier": "^1.5.0",
|
||||||
|
"typescript": "^2.5.3"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"homepage": "https://github.com/DylanPiercey/byte-length",
|
||||||
|
"keywords": [
|
||||||
|
"bytes",
|
||||||
|
"content-length",
|
||||||
|
"length",
|
||||||
|
"string"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"lint-staged": {
|
||||||
|
"*.ts": [
|
||||||
|
"prettier --write",
|
||||||
|
"tslint -t codeFrame -c tslint.json",
|
||||||
|
"git add"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/DylanPiercey/byte-length"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsc",
|
||||||
|
"coveralls": "cat coverage/lcov.info | coveralls",
|
||||||
|
"format-all": "find {src,test} -name '*.ts' | xargs prettier --write",
|
||||||
|
"mocha": "mocha -r ts-node/register ./test/**/*.test.ts",
|
||||||
|
"precommit": "lint-staged && npm test && npm run build",
|
||||||
|
"test": "nyc --extension=.ts --include=src/**/*.ts --reporter=lcov --reporter=text-summary npm run mocha",
|
||||||
|
"test-ci": "nyc --extension=.ts --include=src/**/*.ts --reporter=lcovonly --reporter=text npm run mocha"
|
||||||
|
},
|
||||||
|
"types": "dist/index.d.ts"
|
||||||
|
}
|
||||||
27
node_modules/charenc/LICENSE.mkd
generated
vendored
Normal file
27
node_modules/charenc/LICENSE.mkd
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
Copyright © 2011, Paul Vorbach. All rights reserved.
|
||||||
|
Copyright © 2009, Jeff Mott. All rights reserved.
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
* Neither the name Crypto-JS nor the names of its contributors may be used to
|
||||||
|
endorse or promote products derived from this software without specific prior
|
||||||
|
written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
1
node_modules/charenc/README.js
generated
vendored
Normal file
1
node_modules/charenc/README.js
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
**enc** provides crypto character encoding utilities.
|
||||||
33
node_modules/charenc/charenc.js
generated
vendored
Normal file
33
node_modules/charenc/charenc.js
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
var charenc = {
|
||||||
|
// UTF-8 encoding
|
||||||
|
utf8: {
|
||||||
|
// Convert a string to a byte array
|
||||||
|
stringToBytes: function(str) {
|
||||||
|
return charenc.bin.stringToBytes(unescape(encodeURIComponent(str)));
|
||||||
|
},
|
||||||
|
|
||||||
|
// Convert a byte array to a string
|
||||||
|
bytesToString: function(bytes) {
|
||||||
|
return decodeURIComponent(escape(charenc.bin.bytesToString(bytes)));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Binary encoding
|
||||||
|
bin: {
|
||||||
|
// Convert a string to a byte array
|
||||||
|
stringToBytes: function(str) {
|
||||||
|
for (var bytes = [], i = 0; i < str.length; i++)
|
||||||
|
bytes.push(str.charCodeAt(i) & 0xFF);
|
||||||
|
return bytes;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Convert a byte array to a string
|
||||||
|
bytesToString: function(bytes) {
|
||||||
|
for (var str = [], i = 0; i < bytes.length; i++)
|
||||||
|
str.push(String.fromCharCode(bytes[i]));
|
||||||
|
return str.join('');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = charenc;
|
||||||
24
node_modules/charenc/package.json
generated
vendored
Normal file
24
node_modules/charenc/package.json
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"author": "Paul Vorbach <paul@vorb.de> (http://vorb.de)",
|
||||||
|
"name": "charenc",
|
||||||
|
"description": "character encoding utilities",
|
||||||
|
"tags": [
|
||||||
|
"utf8",
|
||||||
|
"binary",
|
||||||
|
"byte",
|
||||||
|
"string"
|
||||||
|
],
|
||||||
|
"version": "0.0.2",
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://github.com/pvorb/node-charenc.git"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/pvorb/node-charenc/issues"
|
||||||
|
},
|
||||||
|
"main": "charenc.js",
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
}
|
||||||
27
node_modules/crypt/LICENSE.mkd
generated
vendored
Normal file
27
node_modules/crypt/LICENSE.mkd
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
Copyright © 2011, Paul Vorbach. All rights reserved.
|
||||||
|
Copyright © 2009, Jeff Mott. All rights reserved.
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
* Neither the name Crypto-JS nor the names of its contributors may be used to
|
||||||
|
endorse or promote products derived from this software without specific prior
|
||||||
|
written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
1
node_modules/crypt/README.mkd
generated
vendored
Normal file
1
node_modules/crypt/README.mkd
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
**crypt** provides utilities for encryption and hashing
|
||||||
96
node_modules/crypt/crypt.js
generated
vendored
Normal file
96
node_modules/crypt/crypt.js
generated
vendored
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
(function() {
|
||||||
|
var base64map
|
||||||
|
= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
|
||||||
|
|
||||||
|
crypt = {
|
||||||
|
// Bit-wise rotation left
|
||||||
|
rotl: function(n, b) {
|
||||||
|
return (n << b) | (n >>> (32 - b));
|
||||||
|
},
|
||||||
|
|
||||||
|
// Bit-wise rotation right
|
||||||
|
rotr: function(n, b) {
|
||||||
|
return (n << (32 - b)) | (n >>> b);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Swap big-endian to little-endian and vice versa
|
||||||
|
endian: function(n) {
|
||||||
|
// If number given, swap endian
|
||||||
|
if (n.constructor == Number) {
|
||||||
|
return crypt.rotl(n, 8) & 0x00FF00FF | crypt.rotl(n, 24) & 0xFF00FF00;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Else, assume array and swap all items
|
||||||
|
for (var i = 0; i < n.length; i++)
|
||||||
|
n[i] = crypt.endian(n[i]);
|
||||||
|
return n;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Generate an array of any length of random bytes
|
||||||
|
randomBytes: function(n) {
|
||||||
|
for (var bytes = []; n > 0; n--)
|
||||||
|
bytes.push(Math.floor(Math.random() * 256));
|
||||||
|
return bytes;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Convert a byte array to big-endian 32-bit words
|
||||||
|
bytesToWords: function(bytes) {
|
||||||
|
for (var words = [], i = 0, b = 0; i < bytes.length; i++, b += 8)
|
||||||
|
words[b >>> 5] |= bytes[i] << (24 - b % 32);
|
||||||
|
return words;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Convert big-endian 32-bit words to a byte array
|
||||||
|
wordsToBytes: function(words) {
|
||||||
|
for (var bytes = [], b = 0; b < words.length * 32; b += 8)
|
||||||
|
bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF);
|
||||||
|
return bytes;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Convert a byte array to a hex string
|
||||||
|
bytesToHex: function(bytes) {
|
||||||
|
for (var hex = [], i = 0; i < bytes.length; i++) {
|
||||||
|
hex.push((bytes[i] >>> 4).toString(16));
|
||||||
|
hex.push((bytes[i] & 0xF).toString(16));
|
||||||
|
}
|
||||||
|
return hex.join('');
|
||||||
|
},
|
||||||
|
|
||||||
|
// Convert a hex string to a byte array
|
||||||
|
hexToBytes: function(hex) {
|
||||||
|
for (var bytes = [], c = 0; c < hex.length; c += 2)
|
||||||
|
bytes.push(parseInt(hex.substr(c, 2), 16));
|
||||||
|
return bytes;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Convert a byte array to a base-64 string
|
||||||
|
bytesToBase64: function(bytes) {
|
||||||
|
for (var base64 = [], i = 0; i < bytes.length; i += 3) {
|
||||||
|
var triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
|
||||||
|
for (var j = 0; j < 4; j++)
|
||||||
|
if (i * 8 + j * 6 <= bytes.length * 8)
|
||||||
|
base64.push(base64map.charAt((triplet >>> 6 * (3 - j)) & 0x3F));
|
||||||
|
else
|
||||||
|
base64.push('=');
|
||||||
|
}
|
||||||
|
return base64.join('');
|
||||||
|
},
|
||||||
|
|
||||||
|
// Convert a base-64 string to a byte array
|
||||||
|
base64ToBytes: function(base64) {
|
||||||
|
// Remove non-base-64 characters
|
||||||
|
base64 = base64.replace(/[^A-Z0-9+\/]/ig, '');
|
||||||
|
|
||||||
|
for (var bytes = [], i = 0, imod4 = 0; i < base64.length;
|
||||||
|
imod4 = ++i % 4) {
|
||||||
|
if (imod4 == 0) continue;
|
||||||
|
bytes.push(((base64map.indexOf(base64.charAt(i - 1))
|
||||||
|
& (Math.pow(2, -2 * imod4 + 8) - 1)) << (imod4 * 2))
|
||||||
|
| (base64map.indexOf(base64.charAt(i)) >>> (6 - imod4 * 2)));
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = crypt;
|
||||||
|
})();
|
||||||
22
node_modules/crypt/package.json
generated
vendored
Normal file
22
node_modules/crypt/package.json
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"author": "Paul Vorbach <paul@vorb.de> (http://vorb.de)",
|
||||||
|
"name": "crypt",
|
||||||
|
"description": "utilities for encryption and hashing",
|
||||||
|
"tags": [
|
||||||
|
"hash",
|
||||||
|
"security"
|
||||||
|
],
|
||||||
|
"version": "0.0.2",
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://github.com/pvorb/node-crypt.git"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/pvorb/node-crypt/issues"
|
||||||
|
},
|
||||||
|
"main": "crypt.js",
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
}
|
||||||
88
node_modules/data-uri-to-buffer/README.md
generated
vendored
Normal file
88
node_modules/data-uri-to-buffer/README.md
generated
vendored
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
data-uri-to-buffer
|
||||||
|
==================
|
||||||
|
### Generate a Buffer instance from a [Data URI][rfc] string
|
||||||
|
[](https://travis-ci.org/TooTallNate/node-data-uri-to-buffer)
|
||||||
|
|
||||||
|
This module accepts a ["data" URI][rfc] String of data, and returns a
|
||||||
|
node.js `Buffer` instance with the decoded data.
|
||||||
|
|
||||||
|
|
||||||
|
Installation
|
||||||
|
------------
|
||||||
|
|
||||||
|
Install with `npm`:
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
$ npm install data-uri-to-buffer
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Example
|
||||||
|
-------
|
||||||
|
|
||||||
|
``` js
|
||||||
|
import dataUriToBuffer from 'data-uri-to-buffer';
|
||||||
|
|
||||||
|
// plain-text data is supported
|
||||||
|
let uri = 'data:,Hello%2C%20World!';
|
||||||
|
let decoded = dataUriToBuffer(uri);
|
||||||
|
console.log(decoded.toString());
|
||||||
|
// 'Hello, World!'
|
||||||
|
|
||||||
|
// base64-encoded data is supported
|
||||||
|
uri = 'data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D';
|
||||||
|
decoded = dataUriToBuffer(uri);
|
||||||
|
console.log(decoded.toString());
|
||||||
|
// 'Hello, World!'
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
API
|
||||||
|
---
|
||||||
|
|
||||||
|
### dataUriToBuffer(String uri) → Buffer
|
||||||
|
|
||||||
|
The `type` property on the Buffer instance gets set to the main type portion of
|
||||||
|
the "mediatype" portion of the "data" URI, or defaults to `"text/plain"` if not
|
||||||
|
specified.
|
||||||
|
|
||||||
|
The `typeFull` property on the Buffer instance gets set to the entire
|
||||||
|
"mediatype" portion of the "data" URI (including all parameters), or defaults
|
||||||
|
to `"text/plain;charset=US-ASCII"` if not specified.
|
||||||
|
|
||||||
|
The `charset` property on the Buffer instance gets set to the Charset portion of
|
||||||
|
the "mediatype" portion of the "data" URI, or defaults to `"US-ASCII"` if the
|
||||||
|
entire type is not specified, or defaults to `""` otherwise.
|
||||||
|
|
||||||
|
*Note*: If the only the main type is specified but not the charset, e.g.
|
||||||
|
`"data:text/plain,abc"`, the charset is set to the empty string. The spec only
|
||||||
|
defaults to US-ASCII as charset if the entire type is not specified.
|
||||||
|
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
|
||||||
|
(The MIT License)
|
||||||
|
|
||||||
|
Copyright (c) 2014 Nathan Rajlich <nathan@tootallnate.net>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
'Software'), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
[rfc]: http://tools.ietf.org/html/rfc2397
|
||||||
15
node_modules/data-uri-to-buffer/dist/index.d.ts
generated
vendored
Normal file
15
node_modules/data-uri-to-buffer/dist/index.d.ts
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/// <reference types="node" />
|
||||||
|
export interface MimeBuffer extends Buffer {
|
||||||
|
type: string;
|
||||||
|
typeFull: string;
|
||||||
|
charset: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns a `Buffer` instance from the given data URI `uri`.
|
||||||
|
*
|
||||||
|
* @param {String} uri Data URI to turn into a Buffer instance
|
||||||
|
* @returns {Buffer} Buffer instance from Data URI
|
||||||
|
* @api public
|
||||||
|
*/
|
||||||
|
export declare function dataUriToBuffer(uri: string): MimeBuffer;
|
||||||
|
export default dataUriToBuffer;
|
||||||
53
node_modules/data-uri-to-buffer/dist/index.js
generated
vendored
Normal file
53
node_modules/data-uri-to-buffer/dist/index.js
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/**
|
||||||
|
* Returns a `Buffer` instance from the given data URI `uri`.
|
||||||
|
*
|
||||||
|
* @param {String} uri Data URI to turn into a Buffer instance
|
||||||
|
* @returns {Buffer} Buffer instance from Data URI
|
||||||
|
* @api public
|
||||||
|
*/
|
||||||
|
export function dataUriToBuffer(uri) {
|
||||||
|
if (!/^data:/i.test(uri)) {
|
||||||
|
throw new TypeError('`uri` does not appear to be a Data URI (must begin with "data:")');
|
||||||
|
}
|
||||||
|
// strip newlines
|
||||||
|
uri = uri.replace(/\r?\n/g, '');
|
||||||
|
// split the URI up into the "metadata" and the "data" portions
|
||||||
|
const firstComma = uri.indexOf(',');
|
||||||
|
if (firstComma === -1 || firstComma <= 4) {
|
||||||
|
throw new TypeError('malformed data: URI');
|
||||||
|
}
|
||||||
|
// remove the "data:" scheme and parse the metadata
|
||||||
|
const meta = uri.substring(5, firstComma).split(';');
|
||||||
|
let charset = '';
|
||||||
|
let base64 = false;
|
||||||
|
const type = meta[0] || 'text/plain';
|
||||||
|
let typeFull = type;
|
||||||
|
for (let i = 1; i < meta.length; i++) {
|
||||||
|
if (meta[i] === 'base64') {
|
||||||
|
base64 = true;
|
||||||
|
}
|
||||||
|
else if (meta[i]) {
|
||||||
|
typeFull += `;${meta[i]}`;
|
||||||
|
if (meta[i].indexOf('charset=') === 0) {
|
||||||
|
charset = meta[i].substring(8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// defaults to US-ASCII only if type is not provided
|
||||||
|
if (!meta[0] && !charset.length) {
|
||||||
|
typeFull += ';charset=US-ASCII';
|
||||||
|
charset = 'US-ASCII';
|
||||||
|
}
|
||||||
|
// get the encoded data portion and decode URI-encoded chars
|
||||||
|
const encoding = base64 ? 'base64' : 'ascii';
|
||||||
|
const data = unescape(uri.substring(firstComma + 1));
|
||||||
|
const buffer = Buffer.from(data, encoding);
|
||||||
|
// set `.type` and `.typeFull` properties to MIME type
|
||||||
|
buffer.type = type;
|
||||||
|
buffer.typeFull = typeFull;
|
||||||
|
// set the `.charset` property
|
||||||
|
buffer.charset = charset;
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
export default dataUriToBuffer;
|
||||||
|
//# sourceMappingURL=index.js.map
|
||||||
1
node_modules/data-uri-to-buffer/dist/index.js.map
generated
vendored
Normal file
1
node_modules/data-uri-to-buffer/dist/index.js.map
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,GAAW;IAC1C,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QACzB,MAAM,IAAI,SAAS,CAClB,kEAAkE,CAClE,CAAC;KACF;IAED,iBAAiB;IACjB,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAEhC,+DAA+D;IAC/D,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,UAAU,KAAK,CAAC,CAAC,IAAI,UAAU,IAAI,CAAC,EAAE;QACzC,MAAM,IAAI,SAAS,CAAC,qBAAqB,CAAC,CAAC;KAC3C;IAED,mDAAmD;IACnD,MAAM,IAAI,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAErD,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,YAAY,CAAC;IACrC,IAAI,QAAQ,GAAG,IAAI,CAAC;IACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACrC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE;YACzB,MAAM,GAAG,IAAI,CAAC;SACd;aAAM,IAAG,IAAI,CAAC,CAAC,CAAC,EAAE;YAClB,QAAQ,IAAI,IAAM,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5B,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE;gBACtC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;aAC/B;SACD;KACD;IACD,oDAAoD;IACpD,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;QAChC,QAAQ,IAAI,mBAAmB,CAAC;QAChC,OAAO,GAAG,UAAU,CAAC;KACrB;IAED,4DAA4D;IAC5D,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC;IAC7C,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC;IACrD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAe,CAAC;IAEzD,sDAAsD;IACtD,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAE3B,8BAA8B;IAC9B,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;IAEzB,OAAO,MAAM,CAAC;AACf,CAAC;AAED,eAAe,eAAe,CAAC"}
|
||||||
62
node_modules/data-uri-to-buffer/package.json
generated
vendored
Normal file
62
node_modules/data-uri-to-buffer/package.json
generated
vendored
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
"name": "data-uri-to-buffer",
|
||||||
|
"version": "4.0.1",
|
||||||
|
"description": "Generate a Buffer instance from a Data URI string",
|
||||||
|
"type": "module",
|
||||||
|
"exports": "./dist/index.js",
|
||||||
|
"main": "./dist/index.js",
|
||||||
|
"types": "./dist/index.d.ts",
|
||||||
|
"files": [
|
||||||
|
"dist",
|
||||||
|
"src"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsc",
|
||||||
|
"test": "jest",
|
||||||
|
"prepublishOnly": "npm run build"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://github.com/TooTallNate/node-data-uri-to-buffer.git"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"data",
|
||||||
|
"uri",
|
||||||
|
"datauri",
|
||||||
|
"data-uri",
|
||||||
|
"buffer",
|
||||||
|
"convert",
|
||||||
|
"rfc2397",
|
||||||
|
"2397"
|
||||||
|
],
|
||||||
|
"author": "Nathan Rajlich <nathan@tootallnate.net> (http://n8.io/)",
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/TooTallNate/node-data-uri-to-buffer/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/TooTallNate/node-data-uri-to-buffer",
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/jest": "^27.0.2",
|
||||||
|
"@types/node": "^12.20.36",
|
||||||
|
"jest": "^27.3.1",
|
||||||
|
"ts-jest": "^27.0.7",
|
||||||
|
"typescript": "^4.4.4"
|
||||||
|
},
|
||||||
|
"jest": {
|
||||||
|
"preset": "ts-jest",
|
||||||
|
"globals": {
|
||||||
|
"ts-jest": {
|
||||||
|
"diagnostics": false,
|
||||||
|
"isolatedModules": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"verbose": false,
|
||||||
|
"testEnvironment": "node",
|
||||||
|
"testMatch": [
|
||||||
|
"<rootDir>/test/**/*.test.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
68
node_modules/data-uri-to-buffer/src/index.ts
generated
vendored
Normal file
68
node_modules/data-uri-to-buffer/src/index.ts
generated
vendored
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
export interface MimeBuffer extends Buffer {
|
||||||
|
type: string;
|
||||||
|
typeFull: string;
|
||||||
|
charset: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a `Buffer` instance from the given data URI `uri`.
|
||||||
|
*
|
||||||
|
* @param {String} uri Data URI to turn into a Buffer instance
|
||||||
|
* @returns {Buffer} Buffer instance from Data URI
|
||||||
|
* @api public
|
||||||
|
*/
|
||||||
|
export function dataUriToBuffer(uri: string): MimeBuffer {
|
||||||
|
if (!/^data:/i.test(uri)) {
|
||||||
|
throw new TypeError(
|
||||||
|
'`uri` does not appear to be a Data URI (must begin with "data:")'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// strip newlines
|
||||||
|
uri = uri.replace(/\r?\n/g, '');
|
||||||
|
|
||||||
|
// split the URI up into the "metadata" and the "data" portions
|
||||||
|
const firstComma = uri.indexOf(',');
|
||||||
|
if (firstComma === -1 || firstComma <= 4) {
|
||||||
|
throw new TypeError('malformed data: URI');
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove the "data:" scheme and parse the metadata
|
||||||
|
const meta = uri.substring(5, firstComma).split(';');
|
||||||
|
|
||||||
|
let charset = '';
|
||||||
|
let base64 = false;
|
||||||
|
const type = meta[0] || 'text/plain';
|
||||||
|
let typeFull = type;
|
||||||
|
for (let i = 1; i < meta.length; i++) {
|
||||||
|
if (meta[i] === 'base64') {
|
||||||
|
base64 = true;
|
||||||
|
} else if(meta[i]) {
|
||||||
|
typeFull += `;${ meta[i]}`;
|
||||||
|
if (meta[i].indexOf('charset=') === 0) {
|
||||||
|
charset = meta[i].substring(8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// defaults to US-ASCII only if type is not provided
|
||||||
|
if (!meta[0] && !charset.length) {
|
||||||
|
typeFull += ';charset=US-ASCII';
|
||||||
|
charset = 'US-ASCII';
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the encoded data portion and decode URI-encoded chars
|
||||||
|
const encoding = base64 ? 'base64' : 'ascii';
|
||||||
|
const data = unescape(uri.substring(firstComma + 1));
|
||||||
|
const buffer = Buffer.from(data, encoding) as MimeBuffer;
|
||||||
|
|
||||||
|
// set `.type` and `.typeFull` properties to MIME type
|
||||||
|
buffer.type = type;
|
||||||
|
buffer.typeFull = typeFull;
|
||||||
|
|
||||||
|
// set the `.charset` property
|
||||||
|
buffer.charset = charset;
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default dataUriToBuffer;
|
||||||
606
node_modules/fast-xml-parser/CHANGELOG.md
generated
vendored
Normal file
606
node_modules/fast-xml-parser/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,606 @@
|
|||||||
|
<small>Note: If you find missing information about particular minor version, that version must have been changed without any functional change in this library.</small>
|
||||||
|
|
||||||
|
**4.5.2 / 2025-02-18**
|
||||||
|
- Fix null CDATA to comply with undefined behavior (#701) (By [Matthieu BOHEAS](https://github.com/Kelgors))
|
||||||
|
- Fix(performance): Update check for leaf node in saveTextToParentTag function in OrderedObjParser.js (#707) (By [...](https://github.com/tomingtoming))
|
||||||
|
- Fix: emit full JSON string from CLI when no output filename specified (#710) (By [Matt Benson](https://github.com/mbenson))
|
||||||
|
|
||||||
|
**4.5.1 / 2024-12-15**
|
||||||
|
- Fix empty tag key name for v5 (#697). no impact on v4
|
||||||
|
- Fixes entity parsing when used in strict mode (#699)
|
||||||
|
|
||||||
|
**4.5.0 / 2024-09-03**
|
||||||
|
- feat #666: ignoreAttributes support function, and array of string or regex (By [ArtemM](https://github.com/mav-rik))
|
||||||
|
|
||||||
|
**4.4.1 / 2024-07-28**
|
||||||
|
- v5 fix: maximum length limit to currency value
|
||||||
|
- fix #634: build attributes with oneListGroup and attributesGroupName (#653)(By [Andreas Naziris](https://github.com/a-rasin))
|
||||||
|
- fix: get oneListGroup to work as expected for array of strings (#662)(By [Andreas Naziris](https://github.com/a-rasin))
|
||||||
|
|
||||||
|
**4.4.0 / 2024-05-18**
|
||||||
|
- fix #654: parse attribute list correctly for self closing stop node.
|
||||||
|
- fix: validator bug when closing tag is not opened. (#647) (By [Ryosuke Fukatani](https://github.com/RyosukeFukatani))
|
||||||
|
- fix #581: typings; return type of `tagValueProcessor` & `attributeValueProcessor` (#582) (By [monholm]())
|
||||||
|
|
||||||
|
**4.3.6 / 2024-03-16**
|
||||||
|
- Add support for parsing HTML numeric entities (#645) (By [Jonas Schade ](https://github.com/DerZade))
|
||||||
|
|
||||||
|
**4.3.5 / 2024-02-24**
|
||||||
|
- code for v5 is added for experimental use
|
||||||
|
|
||||||
|
**4.3.4 / 2024-01-10**
|
||||||
|
- fix: Don't escape entities in CDATA sections (#633) (By [wackbyte](https://github.com/wackbyte))
|
||||||
|
|
||||||
|
**4.3.3 / 2024-01-10**
|
||||||
|
- Remove unnecessary regex
|
||||||
|
|
||||||
|
**4.3.2 / 2023-10-02**
|
||||||
|
- fix `jObj.hasOwnProperty` when give input is null (By [Arda TANRIKULU](https://github.com/ardatan))
|
||||||
|
|
||||||
|
**4.3.1 / 2023-09-24**
|
||||||
|
- revert back "Fix typings for builder and parser to make return type generic" to avoid failure of existing projects. Need to decide a common approach.
|
||||||
|
|
||||||
|
**4.3.0 / 2023-09-20**
|
||||||
|
- Fix stopNodes to work with removeNSPrefix (#607) (#608) (By [Craig Andrews]https://github.com/candrews))
|
||||||
|
- Fix #610 ignore properties set to Object.prototype
|
||||||
|
- Fix typings for builder and parser to make return type generic (By [Sarah Dayan](https://github.com/sarahdayan))
|
||||||
|
|
||||||
|
**4.2.7 / 2023-07-30**
|
||||||
|
- Fix: builder should set text node correctly when only textnode is present (#589) (By [qianqing](https://github.com/joneqian))
|
||||||
|
- Fix: Fix for null and undefined attributes when building xml (#585) (#598). A null or undefined value should be ignored. (By [Eugenio Ceschia](https://github.com/cecia234))
|
||||||
|
|
||||||
|
**4.2.6 / 2023-07-17**
|
||||||
|
- Fix: Remove trailing slash from jPath for self-closing tags (#595) (By [Maciej Radzikowski](https://github.com/m-radzikowski))
|
||||||
|
|
||||||
|
**4.2.5 / 2023-06-22**
|
||||||
|
- change code implementation
|
||||||
|
|
||||||
|
**4.2.4 / 2023-06-06**
|
||||||
|
- fix security bug
|
||||||
|
|
||||||
|
**4.2.3 / 2023-06-05**
|
||||||
|
- fix security bug
|
||||||
|
|
||||||
|
**4.2.2 / 2023-04-18**
|
||||||
|
- fix #562: fix unpaired tag when it comes in last of a nested tag. Also throw error when unpaired tag is used as closing tag
|
||||||
|
|
||||||
|
**4.2.1 / 2023-04-18**
|
||||||
|
- fix: jpath after unpaired tags
|
||||||
|
|
||||||
|
**4.2.0 / 2023-04-09**
|
||||||
|
- support `updateTag` parser property
|
||||||
|
|
||||||
|
**4.1.4 / 2023-04-08**
|
||||||
|
- update typings to let user create XMLBuilder instance without options (#556) (By [Patrick](https://github.com/omggga))
|
||||||
|
- fix: IsArray option isn't parsing tags with 0 as value correctly #490 (#557) (By [Aleksandr Murashkin](https://github.com/p-kuen))
|
||||||
|
- feature: support `oneListGroup` to group repeated children tags udder single group
|
||||||
|
|
||||||
|
**4.1.3 / 2023-02-26**
|
||||||
|
- fix #546: Support complex entity value
|
||||||
|
|
||||||
|
**4.1.2 / 2023-02-12**
|
||||||
|
- Security Fix
|
||||||
|
|
||||||
|
**4.1.1 / 2023-02-03**
|
||||||
|
- Fix #540: ignoreAttributes breaks unpairedTags
|
||||||
|
- Refactor XML builder code
|
||||||
|
|
||||||
|
**4.1.0 / 2023-02-02**
|
||||||
|
- Fix '<' or '>' in DTD comment throwing an error. (#533) (By [Adam Baker](https://github.com/Cwazywierdo))
|
||||||
|
- Set "eNotation" to 'true' as default
|
||||||
|
|
||||||
|
**4.0.15 / 2023-01-25**
|
||||||
|
- make "eNotation" optional
|
||||||
|
|
||||||
|
**4.0.14 / 2023-01-22**
|
||||||
|
- fixed: add missed typing "eNotation" to parse values
|
||||||
|
|
||||||
|
**4.0.13 / 2023-01-07**
|
||||||
|
- preserveorder formatting (By [mdeknowis](https://github.com/mdeknowis))
|
||||||
|
- support `transformAttributeName` (By [Erik Rothoff Andersson](https://github.com/erkie))
|
||||||
|
|
||||||
|
**4.0.12 / 2022-11-19**
|
||||||
|
- fix typescript
|
||||||
|
|
||||||
|
**4.0.11 / 2022-10-05**
|
||||||
|
- fix #501: parse for entities only once
|
||||||
|
|
||||||
|
**4.0.10 / 2022-09-14**
|
||||||
|
- fix broken links in demo site (By [Yannick Lang](https://github.com/layaxx))
|
||||||
|
- fix #491: tagValueProcessor type definition (By [Andrea Francesco Speziale](https://github.com/andreafspeziale))
|
||||||
|
- Add jsdocs for tagValueProcessor
|
||||||
|
|
||||||
|
|
||||||
|
**4.0.9 / 2022-07-10**
|
||||||
|
- fix #470: stop-tag can have self-closing tag with same name
|
||||||
|
- fix #472: stopNode can have any special tag inside
|
||||||
|
- Allow !ATTLIST and !NOTATION with DOCTYPE
|
||||||
|
- Add transformTagName option to transform tag names when parsing (#469) (By [Erik Rothoff Andersson](https://github.com/erkie))
|
||||||
|
|
||||||
|
**4.0.8 / 2022-05-28**
|
||||||
|
- Fix CDATA parsing returning empty string when value = 0 (#451) (By [ndelanou](https://github.com/ndelanou))
|
||||||
|
- Fix stopNodes when same tag appears inside node (#456) (By [patrickshipe](https://github.com/patrickshipe))
|
||||||
|
- fix #468: prettify own properties only
|
||||||
|
|
||||||
|
**4.0.7 / 2022-03-18**
|
||||||
|
- support CDATA even if tag order is not preserved
|
||||||
|
- support Comments even if tag order is not preserved
|
||||||
|
- fix #446: XMLbuilder should not indent XML declaration
|
||||||
|
|
||||||
|
**4.0.6 / 2022-03-08**
|
||||||
|
- fix: call tagValueProcessor only once for array items
|
||||||
|
- fix: missing changed for #437
|
||||||
|
|
||||||
|
**4.0.5 / 2022-03-06**
|
||||||
|
- fix #437: call tagValueProcessor from XML builder
|
||||||
|
|
||||||
|
**4.0.4 / 2022-03-03**
|
||||||
|
- fix #435: should skip unpaired and self-closing nodes when set as stopnodes
|
||||||
|
|
||||||
|
**4.0.3 / 2022-02-15**
|
||||||
|
- fix: ReferenceError when Bundled with Strict (#431) (By [Andreas Heissenberger](https://github.com/aheissenberger))
|
||||||
|
|
||||||
|
|
||||||
|
**4.0.2 / 2022-02-04**
|
||||||
|
- builder supports `suppressUnpairedNode`
|
||||||
|
- parser supports `ignoreDeclaration` and `ignorePiTags`
|
||||||
|
- fix: when comment is parsed as text value if given as `<!--> ...` #423
|
||||||
|
- builder supports decoding `&`
|
||||||
|
|
||||||
|
**4.0.1 / 2022-01-08**
|
||||||
|
- fix builder for pi tag
|
||||||
|
- fix: support suppressBooleanAttrs by builder
|
||||||
|
|
||||||
|
**4.0.0 / 2022-01-06**
|
||||||
|
- Generating different combined, parser only, builder only, validator only browser bundles
|
||||||
|
- Keeping cjs modules as they can be imported in cjs and esm modules both. Otherwise refer `esm` branch.
|
||||||
|
|
||||||
|
**4.0.0-beta.8 / 2021-12-13**
|
||||||
|
- call tagValueProcessor for stop nodes
|
||||||
|
|
||||||
|
**4.0.0-beta.7 / 2021-12-09**
|
||||||
|
- fix Validator bug when an attribute has no value but '=' only
|
||||||
|
- XML Builder should suppress unpaired tags by default.
|
||||||
|
- documents update for missing features
|
||||||
|
- refactoring to use Object.assign
|
||||||
|
- refactoring to remove repeated code
|
||||||
|
|
||||||
|
**4.0.0-beta.6 / 2021-12-05**
|
||||||
|
- Support PI Tags processing
|
||||||
|
- Support `suppressBooleanAttributes` by XML Builder for attributes with value `true`.
|
||||||
|
|
||||||
|
**4.0.0-beta.5 / 2021-12-04**
|
||||||
|
- fix: when a tag with name "attributes"
|
||||||
|
|
||||||
|
**4.0.0-beta.4 / 2021-12-02**
|
||||||
|
- Support HTML document parsing
|
||||||
|
- skip stop nodes parsing when building the XML from JS object
|
||||||
|
- Support external entites without DOCTYPE
|
||||||
|
- update dev dependency: strnum v1.0.5 to fix long number issue
|
||||||
|
|
||||||
|
**4.0.0-beta.3 / 2021-11-30**
|
||||||
|
- support global stopNodes expression like "*.stop"
|
||||||
|
- support self-closing and paired unpaired tags
|
||||||
|
- fix: CDATA should not be parsed.
|
||||||
|
- Fix typings for XMLBuilder (#396)(By [Anders Emil Salvesen](https://github.com/andersem))
|
||||||
|
- supports XML entities, HTML entities, DOCTYPE entities
|
||||||
|
|
||||||
|
**⚠️ 4.0.0-beta.2 / 2021-11-19**
|
||||||
|
- rename `attrMap` to `attibutes` in parser output when `preserveOrder:true`
|
||||||
|
- supports unpairedTags
|
||||||
|
|
||||||
|
**⚠️ 4.0.0-beta.1 / 2021-11-18**
|
||||||
|
- Parser returns an array now
|
||||||
|
- to make the structure common
|
||||||
|
- and to return root level detail
|
||||||
|
- renamed `cdataTagName` to `cdataPropName`
|
||||||
|
- Added `commentPropName`
|
||||||
|
- fix typings
|
||||||
|
|
||||||
|
**⚠️ 4.0.0-beta.0 / 2021-11-16**
|
||||||
|
- Name change of many configuration properties.
|
||||||
|
- `attrNodeName` to `attributesGroupName`
|
||||||
|
- `attrValueProcessor` to `attributeValueProcessor`
|
||||||
|
- `parseNodeValue` to `parseTagValue`
|
||||||
|
- `ignoreNameSpace` to `removeNSPrefix`
|
||||||
|
- `numParseOptions` to `numberParseOptions`
|
||||||
|
- spelling correction for `suppressEmptyNode`
|
||||||
|
- Name change of cli and browser bundle to **fxparser**
|
||||||
|
- `isArray` option is added to parse a tag into array
|
||||||
|
- `preserveOrder` option is added to render XML in such a way that the result js Object maintains the order of properties same as in XML.
|
||||||
|
- Processing behaviour of `tagValueProcessor` and `attributeValueProcessor` are changes with extra input parameters
|
||||||
|
- j2xparser is renamed to XMLBuilder.
|
||||||
|
- You need to build XML parser instance for given options first before parsing XML.
|
||||||
|
- fix #327, #336: throw error when extra text after XML content
|
||||||
|
- fix #330: attribute value can have '\n',
|
||||||
|
- fix #350: attrbiutes can be separated by '\n' from tagname
|
||||||
|
|
||||||
|
3.21.1 / 2021-10-31
|
||||||
|
- Correctly format JSON elements with a text prop but no attribute props ( By [haddadnj](https://github.com/haddadnj) )
|
||||||
|
|
||||||
|
3.21.0 / 2021-10-25
|
||||||
|
- feat: added option `rootNodeName` to set tag name for array input when converting js object to XML.
|
||||||
|
- feat: added option `alwaysCreateTextNode` to force text node creation (by: *@massimo-ua*)
|
||||||
|
- ⚠️ feat: Better error location for unclosed tags. (by *@Gei0r*)
|
||||||
|
- Some error messages would be changed when validating XML. Eg
|
||||||
|
- `{ InvalidXml: "Invalid '[ \"rootNode\"]' found." }` → `{InvalidTag: "Unclosed tag 'rootNode'."}`
|
||||||
|
- `{ InvalidTag: "Closing tag 'rootNode' is expected inplace of 'rootnode'." }` → `{ InvalidTag: "Expected closing tag 'rootNode' (opened in line 1) instead of closing tag 'rootnode'."}`
|
||||||
|
- ⚠️ feat: Column in error response when validating XML
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
"code": "InvalidAttr",
|
||||||
|
"msg": "Attribute 'abc' is repeated.",
|
||||||
|
"line": 1,
|
||||||
|
"col": 22
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
3.20.1 / 2021-09-25
|
||||||
|
- update strnum package
|
||||||
|
|
||||||
|
3.20.0 / 2021-09-10
|
||||||
|
- Use strnum npm package to parse string to number
|
||||||
|
- breaking change: long number will be parsed to scientific notation.
|
||||||
|
|
||||||
|
3.19.0 / 2021-03-14
|
||||||
|
- License changed to MIT original
|
||||||
|
- Fix #321 : namespace tag parsing
|
||||||
|
|
||||||
|
3.18.0 / 2021-02-05
|
||||||
|
- Support RegEx and function in arrayMode option
|
||||||
|
- Fix #317 : validate nested PI tags
|
||||||
|
|
||||||
|
3.17.4 / 2020-06-07
|
||||||
|
- Refactor some code to support IE11
|
||||||
|
- Fix: `<tag >` space as attribute string
|
||||||
|
|
||||||
|
3.17.3 / 2020-05-23
|
||||||
|
- Fix: tag name separated by \n \t
|
||||||
|
- Fix: throw error for unclosed tags
|
||||||
|
|
||||||
|
3.17.2 / 2020-05-23
|
||||||
|
- Fixed an issue in processing doctype tag
|
||||||
|
- Fixed tagName where it should not have whitespace chars
|
||||||
|
|
||||||
|
3.17.1 / 2020-05-19
|
||||||
|
- Fixed an issue in checking opening tag
|
||||||
|
|
||||||
|
3.17.0 / 2020-05-18
|
||||||
|
- parser: fix '<' issue when it comes in aatr value
|
||||||
|
- parser: refactoring to remove dependency from regex
|
||||||
|
- validator: fix IE 11 issue for error messages
|
||||||
|
- updated dev dependencies
|
||||||
|
- separated benchmark module to sub-module
|
||||||
|
- breaking change: comments will not be removed from CDATA data
|
||||||
|
|
||||||
|
3.16.0 / 2020-01-12
|
||||||
|
- validaor: fix for ampersand characters (#215)
|
||||||
|
- refactoring to support unicode chars in tag name
|
||||||
|
- update typing for validator error
|
||||||
|
|
||||||
|
3.15.1 / 2019-12-09
|
||||||
|
- validaor: fix multiple roots are not allowed
|
||||||
|
|
||||||
|
3.15.0 / 2019-11-23
|
||||||
|
- validaor: improve error messaging
|
||||||
|
- validator: add line number in case of error
|
||||||
|
- validator: add more error scenarios to make it more descriptive
|
||||||
|
|
||||||
|
3.14.0 / 2019-10-25
|
||||||
|
- arrayMode for XML to JS obj parsing
|
||||||
|
|
||||||
|
3.13.0 / 2019-10-02
|
||||||
|
- pass tag/attr name to tag/attr value processor
|
||||||
|
- inbuilt optional validation with XML parser
|
||||||
|
|
||||||
|
3.12.21 / 2019-10-02
|
||||||
|
- Fix validator for unclosed XMLs
|
||||||
|
- move nimnjs dependency to dev dependency
|
||||||
|
- update dependencies
|
||||||
|
|
||||||
|
3.12.20 / 2019-08-16
|
||||||
|
- Revert: Fix #167: '>' in attribute value as it is causing high performance degrade.
|
||||||
|
|
||||||
|
3.12.19 / 2019-07-28
|
||||||
|
- Fix js to xml parser should work for date values. (broken: `tagValueProcessor` will receive the original value instead of string always) (breaking change)
|
||||||
|
|
||||||
|
3.12.18 / 2019-07-27
|
||||||
|
- remove configstore dependency
|
||||||
|
|
||||||
|
3.12.17 / 2019-07-14
|
||||||
|
- Fix #167: '>' in attribute value
|
||||||
|
|
||||||
|
3.12.16 / 2019-03-23
|
||||||
|
- Support a new option "stopNodes". (#150)
|
||||||
|
Accept the list of tags which are not required to be parsed. Instead, all the nested tag and data will be assigned as string.
|
||||||
|
- Don't show post-install message
|
||||||
|
|
||||||
|
3.12.12 / 2019-01-11
|
||||||
|
- fix : IE parseInt, parseFloat error
|
||||||
|
|
||||||
|
3.12.11 / 2018-12-24
|
||||||
|
- fix #132: "/" should not be parsed as boolean attr in case of self closing tags
|
||||||
|
|
||||||
|
3.12.9 / 2018-11-23
|
||||||
|
- fix #129 : validator should not fail when an atrribute name is 'length'
|
||||||
|
|
||||||
|
3.12.8 / 2018-11-22
|
||||||
|
- fix #128 : use 'attrValueProcessor' to process attribute value in json2xml parser
|
||||||
|
|
||||||
|
3.12.6 / 2018-11-10
|
||||||
|
- Fix #126: check for type
|
||||||
|
|
||||||
|
3.12.4 / 2018-09-12
|
||||||
|
- Fix: include tasks in npm package
|
||||||
|
|
||||||
|
3.12.3 / 2018-09-12
|
||||||
|
- Fix CLI issue raised in last PR
|
||||||
|
|
||||||
|
3.12.2 / 2018-09-11
|
||||||
|
- Fix formatting for JSON to XML output
|
||||||
|
- Migrate to webpack (PR merged)
|
||||||
|
- fix cli (PR merged)
|
||||||
|
|
||||||
|
3.12.0 / 2018-08-06
|
||||||
|
- Support hexadecimal values
|
||||||
|
- Support true number parsing
|
||||||
|
|
||||||
|
3.11.2 / 2018-07-23
|
||||||
|
- Update Demo for more options
|
||||||
|
- Update license information
|
||||||
|
- Update readme for formatting, users, and spelling mistakes
|
||||||
|
- Add missing typescript definition for j2xParser
|
||||||
|
- refactoring: change filenames
|
||||||
|
|
||||||
|
3.11.1 / 2018-06-05
|
||||||
|
- fix #93: read the text after self closing tag
|
||||||
|
|
||||||
|
3.11.0 / 2018-05-20
|
||||||
|
- return defaultOptions if there are not options in buildOptions function
|
||||||
|
- added localeRange declaration in parser.d.ts
|
||||||
|
- Added support of cyrillic characters in validator XML
|
||||||
|
- fixed bug in validator work when XML data with byte order marker
|
||||||
|
|
||||||
|
3.10.0 / 2018-05-13
|
||||||
|
- Added support of cyrillic characters in parsing XML to JSON
|
||||||
|
|
||||||
|
3.9.11 / 2018-05-09
|
||||||
|
- fix https://github.com/NaturalIntelligence/fast-xml-parser/issues/80 fix nimn chars
|
||||||
|
- update package information
|
||||||
|
- fix https://github.com/NaturalIntelligence/fast-xml-parser/issues/86: json 2 xml parser : property with null value should be parsed to self closing tag.
|
||||||
|
- update online demo
|
||||||
|
- revert zombiejs to old version to support old version of node
|
||||||
|
- update dependencies
|
||||||
|
|
||||||
|
3.3.10 / 2018-04-23
|
||||||
|
- fix #77 : parse even if closing tag has space before '>'
|
||||||
|
- include all css & js lib in demo app
|
||||||
|
- remove babel dependencies until needed
|
||||||
|
|
||||||
|
3.3.9 / 2018-04-18
|
||||||
|
- fix #74 : TS2314 TypeScript compiler error
|
||||||
|
|
||||||
|
3.3.8 / 2018-04-17
|
||||||
|
- fix #73 : IE doesn't support Object.assign
|
||||||
|
|
||||||
|
3.3.7 / 2018-04-14
|
||||||
|
- fix: use let insted of const in for loop of validator
|
||||||
|
- Merge pull request
|
||||||
|
https://github.com/NaturalIntelligence/fast-xml-parser/issues/71 from bb/master
|
||||||
|
first draft of typings for typescript
|
||||||
|
https://github.com/NaturalIntelligence/fast-xml-parser/issues/69
|
||||||
|
- Merge pull request
|
||||||
|
https://github.com/NaturalIntelligence/fast-xml-parser/issues/70 from bb/patch-1
|
||||||
|
fix some typos in readme
|
||||||
|
|
||||||
|
3.3.6 / 2018-03-21
|
||||||
|
- change arrow functions to full notation for IE compatibility
|
||||||
|
|
||||||
|
3.3.5 / 2018-03-15
|
||||||
|
- fix https://github.com/NaturalIntelligence/fast-xml-parser/issues/67 : attrNodeName invalid behavior
|
||||||
|
- fix: remove decodeHTML char condition
|
||||||
|
|
||||||
|
3.3.4 / 2018-03-14
|
||||||
|
- remove dependency on "he" package
|
||||||
|
- refactor code to separate methods in separate files.
|
||||||
|
- draft code for transforming XML to json string. It is not officially documented due to performance issue.
|
||||||
|
|
||||||
|
3.3.0 / 2018-03-05
|
||||||
|
- use common default options for XML parsing for consistency. And add `parseToNimn` method.
|
||||||
|
- update nexttodo
|
||||||
|
- update README about XML to Nimn transformation and remove special notes about 3.x release
|
||||||
|
- update CONTRIBUTING.ms mentioning nexttodo
|
||||||
|
- add negative case for XML PIs
|
||||||
|
- validate xml processing instruction tags https://github.com/NaturalIntelligence/fast-xml-parser/issues/62
|
||||||
|
- nimndata: handle array with object
|
||||||
|
- nimndata: node with nested node and text node
|
||||||
|
- nimndata: handle attributes and text node
|
||||||
|
- nimndata: add options, handle array
|
||||||
|
- add xml to nimn data converter
|
||||||
|
- x2j: direct access property with tagname
|
||||||
|
- update changelog
|
||||||
|
- fix validator when single quote presents in value enclosed with double quotes or vice versa
|
||||||
|
- Revert "remove unneded nimnjs dependency, move opencollective to devDependencies and replace it
|
||||||
|
with more light opencollective-postinstall"
|
||||||
|
This reverts commit d47aa7181075d82db4fee97fd8ea32b056fe3f46.
|
||||||
|
- Merge pull request: https://github.com/NaturalIntelligence/fast-xml-parser/issues/63 from HaroldPutman/suppress-undefined
|
||||||
|
Keep undefined nodes out of the XML output : This is useful when you are deleting nodes from the JSON and rewriting XML.
|
||||||
|
|
||||||
|
3.2.4 / 2018-03-01
|
||||||
|
- fix #59 fix in validator when open quote presents in attribute value
|
||||||
|
- Create nexttodo.md
|
||||||
|
- exclude static from bitHound tests
|
||||||
|
- add package lock
|
||||||
|
|
||||||
|
3.2.3 / 2018-02-28
|
||||||
|
- Merge pull request from Delagen/master: fix namespaces can contain the same characters as xml names
|
||||||
|
|
||||||
|
3.2.2 / 2018-02-22
|
||||||
|
- fix: attribute xmlns should not be removed if ignoreNameSpace is false
|
||||||
|
- create CONTRIBUTING.md
|
||||||
|
|
||||||
|
3.2.1 / 2018-02-17
|
||||||
|
- fix: empty attribute should be parsed
|
||||||
|
|
||||||
|
3.2.0 / 2018-02-16
|
||||||
|
- Merge pull request : Dev to Master
|
||||||
|
- Update README and version
|
||||||
|
- j2x:add performance test
|
||||||
|
- j2x: Remove extra empty line before closing tag
|
||||||
|
- j2x: suppress empty nodes to self closing node if configured
|
||||||
|
- j2x: provide option to give indentation depth
|
||||||
|
- j2x: make optional formatting
|
||||||
|
- j2x: encodeHTMLchat
|
||||||
|
- j2x: handle cdata tag
|
||||||
|
- j2x: handle grouped attributes
|
||||||
|
- convert json to xml
|
||||||
|
- nested object
|
||||||
|
- array
|
||||||
|
- attributes
|
||||||
|
- text value
|
||||||
|
- small refactoring
|
||||||
|
- Merge pull request: Update cli.js to let user validate XML file or data
|
||||||
|
- Add option for rendering CDATA as separate property
|
||||||
|
|
||||||
|
3.0.1 / 2018-02-09
|
||||||
|
- fix CRLF: replace it with single space in attributes value only.
|
||||||
|
|
||||||
|
3.0.0 / 2018-02-08
|
||||||
|
- change online tool with new changes
|
||||||
|
- update info about new options
|
||||||
|
- separate tag value processing to separate function
|
||||||
|
- make HTML decoding optional
|
||||||
|
- give an option to allow boolean attributes
|
||||||
|
- change cli options as per v3
|
||||||
|
- Correct comparison table format on README
|
||||||
|
- update v3 information
|
||||||
|
- some performance improvement changes
|
||||||
|
- Make regex object local to the method and move some common methods to util
|
||||||
|
- Change parser to
|
||||||
|
- handle multiple instances of CDATA
|
||||||
|
- make triming of value optionals
|
||||||
|
- HTML decode attribute and text value
|
||||||
|
- refactor code to separate files
|
||||||
|
- Ignore newline chars without RE (in validator)
|
||||||
|
- validate for XML prolog
|
||||||
|
- Validate DOCTYPE without RE
|
||||||
|
- Update validator to return error response
|
||||||
|
- Update README to add detail about V3
|
||||||
|
- Separate xmlNode model class
|
||||||
|
- include vscode debug config
|
||||||
|
- fix for repeated object
|
||||||
|
- fix attribute regex for boolean attributes
|
||||||
|
- Fix validator for invalid attributes
|
||||||
|
2.9.4 / 2018-02-02
|
||||||
|
- Merge pull request: Decode HTML characters
|
||||||
|
- refactor source folder name
|
||||||
|
- ignore bundle / browser js to be published to npm
|
||||||
|
2.9.3 / 2018-01-26
|
||||||
|
- Merge pull request: Correctly remove CRLF line breaks
|
||||||
|
- Enable to parse attribute in online editor
|
||||||
|
- Fix testing demo app test
|
||||||
|
- Describe parsing options
|
||||||
|
- Add options for online demo
|
||||||
|
2.9.2 / 2018-01-18
|
||||||
|
- Remove check if tag starting with "XML"
|
||||||
|
- Fix: when there are spaces before / after CDATA
|
||||||
|
|
||||||
|
2.9.1 / 2018-01-16
|
||||||
|
- Fix: newline should be replaced with single space
|
||||||
|
- Fix: for single and multiline comments
|
||||||
|
- validate xml with CDATA
|
||||||
|
- Fix: the issue when there is no space between 2 attributes
|
||||||
|
- Fix: https://github.com/NaturalIntelligence/fast-xml-parser/issues/33: when there is newline char in attr val, it doesn't parse
|
||||||
|
- Merge pull request: fix ignoreNamespace
|
||||||
|
- fix: don't wrap attributes if only namespace attrs
|
||||||
|
- fix: use portfinder for run tests, update deps
|
||||||
|
- fix: don't treat namespaces as attributes when ignoreNamespace enabled
|
||||||
|
|
||||||
|
2.9.0 / 2018-01-10
|
||||||
|
- Rewrite the validator to handle large files.
|
||||||
|
Ignore DOCTYPE validation.
|
||||||
|
- Fix: When attribute value has equal sign
|
||||||
|
|
||||||
|
2.8.3 / 2017-12-15
|
||||||
|
- Fix: when a tag has value along with subtags
|
||||||
|
|
||||||
|
2.8.2 / 2017-12-04
|
||||||
|
- Fix value parsing for IE
|
||||||
|
|
||||||
|
2.8.1 / 2017-12-01
|
||||||
|
- fix: validator should return false instead of err when invalid XML
|
||||||
|
|
||||||
|
2.8.0 / 2017-11-29
|
||||||
|
- Add CLI option to ignore value conversion
|
||||||
|
- Fix variable name when filename is given on CLI
|
||||||
|
- Update CLI help text
|
||||||
|
- Merge pull request: xml2js: Accept standard input
|
||||||
|
- Test Node 8
|
||||||
|
- Update dependencies
|
||||||
|
- Bundle readToEnd
|
||||||
|
- Add ability to read from standard input
|
||||||
|
|
||||||
|
2.7.4 / 2017-09-22
|
||||||
|
- Merge pull request: Allow wrap attributes with subobject to compatible with other parsers output
|
||||||
|
|
||||||
|
2.7.3 / 2017-08-02
|
||||||
|
- fix: handle CDATA with regx
|
||||||
|
|
||||||
|
2.7.2 / 2017-07-30
|
||||||
|
- Change travis config for yarn caching
|
||||||
|
- fix validator: when tag property is same as array property
|
||||||
|
- Merge pull request: Failing test case in validator for valid SVG
|
||||||
|
|
||||||
|
2.7.1 / 2017-07-26
|
||||||
|
- Fix: Handle val 0
|
||||||
|
|
||||||
|
2.7.0 / 2017-07-25
|
||||||
|
- Fix test for arrayMode
|
||||||
|
- Merge pull request: Add arrayMode option to parse any nodes as arrays
|
||||||
|
|
||||||
|
2.6.0 / 2017-07-14
|
||||||
|
- code improvement
|
||||||
|
- Add unit tests for value conversion for attr
|
||||||
|
- Merge pull request: option of an attribute value conversion to a number (textAttrConversion) the same way as the textNodeConversion option does. Default value is false.
|
||||||
|
|
||||||
|
2.5.1 / 2017-07-01
|
||||||
|
- Fix XML element name pattern
|
||||||
|
- Fix XML element name pattern while parsing
|
||||||
|
- Fix validation for xml tag element
|
||||||
|
|
||||||
|
2.5.0 / 2017-06-25
|
||||||
|
- Improve Validator performance
|
||||||
|
- update attr matching regex
|
||||||
|
- Add perf tests
|
||||||
|
- Improve atrr regex to handle all cases
|
||||||
|
|
||||||
|
2.4.4 / 2017-06-08
|
||||||
|
- Bug fix: when an attribute has single or double quote in value
|
||||||
|
|
||||||
|
2.4.3 / 2017-06-05
|
||||||
|
- Bug fix: when multiple CDATA tags are given
|
||||||
|
- Merge pull request: add option "textNodeConversion"
|
||||||
|
- add option "textNodeConversion"
|
||||||
|
|
||||||
|
2.4.1 / 2017-04-14
|
||||||
|
- fix tests
|
||||||
|
- Bug fix: preserve initial space of node value
|
||||||
|
- Handle CDATA
|
||||||
|
|
||||||
|
2.3.1 / 2017-03-15
|
||||||
|
- Bug fix: when single self closing tag
|
||||||
|
- Merge pull request: fix .codeclimate.yml
|
||||||
|
- Update .codeclimate.yml - Fixed config so it does not error anymore.
|
||||||
|
- Update .codeclimate.yml
|
||||||
|
|
||||||
|
2.3.0 / 2017-02-26
|
||||||
|
- Code improvement
|
||||||
|
- add bithound config
|
||||||
|
- Update usage
|
||||||
|
- Update travis to generate bundle js before running tests
|
||||||
|
- 1.Browserify, 2. add more tests for validator
|
||||||
|
- Add validator
|
||||||
|
- Fix CLI default parameter bug
|
||||||
|
|
||||||
|
2.2.1 / 2017-02-05
|
||||||
|
- Bug fix: CLI default option
|
||||||
21
node_modules/fast-xml-parser/LICENSE
generated
vendored
Normal file
21
node_modules/fast-xml-parser/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2017 Amit Kumar Gupta
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
237
node_modules/fast-xml-parser/README.md
generated
vendored
Normal file
237
node_modules/fast-xml-parser/README.md
generated
vendored
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
# [fast-xml-parser](https://www.npmjs.com/package/fast-xml-parser)
|
||||||
|
[![NPM quality][quality-image]][quality-url]
|
||||||
|
[](https://coveralls.io/github/NaturalIntelligence/fast-xml-parser?branch=master)
|
||||||
|
[<img src="https://img.shields.io/badge/Try-me-blue.svg?colorA=FFA500&colorB=0000FF" alt="Try me"/>](https://naturalintelligence.github.io/fast-xml-parser/)
|
||||||
|
[](https://npm.im/fast-xml-parser)
|
||||||
|
|
||||||
|
|
||||||
|
Validate XML, Parse XML to JS Object, or Build XML from JS Object without C/C++ based libraries and no callback.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<small>Checkout our new library [Text2Chart](https://solothought.com/text2chart/flow) that constructs flow chart out of simple text. Very helpful in creating or alayzing an algorithm, and documentation purpose</small>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
Sponsor this project
|
||||||
|
|
||||||
|
<a href="https://github.com/sponsors/NaturalIntelligence">
|
||||||
|
<img src="https://raw.githubusercontent.com/NaturalIntelligence/ThankYouBackers/main/github_sponsor.png" width="180" />
|
||||||
|
</a>
|
||||||
|
<a href="https://opencollective.com/fast-xml-parser/donate" target="_blank">
|
||||||
|
<img src="https://opencollective.com/fast-xml-parser/donate/button@2x.png?color=blue" width=180 />
|
||||||
|
</a>
|
||||||
|
<a href="https://paypal.me/naturalintelligence"> <img src="static/img/support_paypal.svg" alt="donate button" width="180"/></a>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
### Current Sponsors
|
||||||
|
|
||||||
|
Check the complete list at [ThankYouBackers](https://github.com/NaturalIntelligence/ThankYouBackers) for our sponsors and supporters.
|
||||||
|
|
||||||
|
Through Github
|
||||||
|
|
||||||
|
<a href="https://github.com/skunkteam" target="_blank"><img src="https://avatars.githubusercontent.com/u/46373671?s=60" width="60px"></a>
|
||||||
|
<a href="https://github.com/getsentry" target="_blank"><img src="https://avatars.githubusercontent.com/u/1396951?s=60" width="60px"></a>
|
||||||
|
|
||||||
|
Through OpenCollective
|
||||||
|
|
||||||
|
<a href="https://opencollective.com/fast-xml-parser/sponsor/0/website" target="_blank"><img src="https://opencollective.com/fast-xml-parser/sponsor/0/avatar.svg"></a>
|
||||||
|
<a href="https://opencollective.com/fast-xml-parser/sponsor/1/website" target="_blank"><img src="https://opencollective.com/fast-xml-parser/sponsor/1/avatar.svg"></a>
|
||||||
|
<a href="https://opencollective.com/fast-xml-parser/sponsor/2/website" target="_blank"><img src="https://opencollective.com/fast-xml-parser/sponsor/2/avatar.svg"></a>
|
||||||
|
<a href="https://opencollective.com/fast-xml-parser/sponsor/3/website" target="_blank"><img src="https://opencollective.com/fast-xml-parser/sponsor/3/avatar.svg"></a>
|
||||||
|
<a href="https://opencollective.com/fast-xml-parser/sponsor/4/website" target="_blank"><img src="https://opencollective.com/fast-xml-parser/sponsor/4/avatar.svg"></a>
|
||||||
|
<a href="https://opencollective.com/fast-xml-parser/sponsor/5/website" target="_blank"><img src="https://opencollective.com/fast-xml-parser/sponsor/5/avatar.svg"></a>
|
||||||
|
<a href="https://opencollective.com/fast-xml-parser/sponsor/6/website" target="_blank"><img src="https://opencollective.com/fast-xml-parser/sponsor/6/avatar.svg"></a>
|
||||||
|
<a href="https://opencollective.com/fast-xml-parser/sponsor/7/website" target="_blank"><img src="https://opencollective.com/fast-xml-parser/sponsor/7/avatar.svg"></a>
|
||||||
|
<a href="https://opencollective.com/fast-xml-parser/sponsor/8/website" target="_blank"><img src="https://opencollective.com/fast-xml-parser/sponsor/8/avatar.svg"></a>
|
||||||
|
<a href="https://opencollective.com/fast-xml-parser/sponsor/9/website" target="_blank"><img src="https://opencollective.com/fast-xml-parser/sponsor/9/avatar.svg"></a>
|
||||||
|
-->
|
||||||
|
|
||||||
|

|
||||||
|
- <a href="https://github.com/cocopon" target="_blank">Hiroki Kokubun</a>
|
||||||
|
|
||||||
|
> This is a donation. No goods or services are expected in return. Any requests for refunds for those purposes will be rejected.
|
||||||
|
## Users
|
||||||
|
|
||||||
|
<a href="https://github.com/renovatebot/renovate" title="renovate" ><img src="https://avatars1.githubusercontent.com/u/38656520" width="60px" ></a>
|
||||||
|
<a href="https://vmware.com/" title="vmware" > <img src="https://avatars0.githubusercontent.com/u/473334" width="60px" ></a>
|
||||||
|
<a href="https://opensource.microsoft.com/" title="microsoft" > <img src="https://avatars0.githubusercontent.com/u/6154722" width="60px" ></a>
|
||||||
|
<a href="http://ibm.github.io/" title="IBM" > <img src="https://avatars2.githubusercontent.com/u/1459110" width="60px" ></a>
|
||||||
|
<a href="http://www.smartbear.com" title="SmartBear Software" > <img src="https://avatars2.githubusercontent.com/u/1644671" width="60px" ></a>
|
||||||
|
<a href="http://nasa.github.io/" title="NASA" > <img src="https://avatars0.githubusercontent.com/u/848102" width="60px" ></a>
|
||||||
|
<a href="https://github.com/prettier" title="Prettier" > <img src="https://avatars0.githubusercontent.com/u/25822731" width="60px" ></a>
|
||||||
|
<a href="http://brain.js.org/" title="brain.js" > <img src="https://avatars2.githubusercontent.com/u/23732838" width="60px" ></a>
|
||||||
|
<a href="https://github.com/aws" title="AWS SDK" > <img src="https://avatars.githubusercontent.com/u/2232217" width="60px" ></a>
|
||||||
|
<a href="http://www.fda.gov/" title="Food and Drug Administration " > <img src="https://avatars2.githubusercontent.com/u/6471964" width="60px" ></a>
|
||||||
|
<a href="http://www.magento.com/" title="Magento" > <img src="https://avatars2.githubusercontent.com/u/168457" width="60px" ></a>
|
||||||
|
<a href="https://github.com/SAP" title="SAP" > <img src="https://user-images.githubusercontent.com/7692328/204835214-d9d25b58-e3df-408d-87a3-c7d36b578ee4.png" width="60px" ></a>
|
||||||
|
<a href="https://github.com/postmanlabs" title="postman" > <img src="https://user-images.githubusercontent.com/7692328/204835529-e9e290ad-696a-49ad-9d34-08e955704715.png" width="60px" ></a>
|
||||||
|
<a href="https://github.com/react-native-community" title="React Native Community" > <img src="https://avatars.githubusercontent.com/u/20269980?v=4" width="60px" ></a>
|
||||||
|
<a href="https://github.com/googleapis" title="Google APIs" > <img src="https://avatars.githubusercontent.com/u/16785467?v=4" width="60px" ></a>
|
||||||
|
<a href="https://github.com/langchain-ai" title="Langchain AI" > <img src="https://avatars.githubusercontent.com/u/126733545?v=4" width="60px" ></a>
|
||||||
|
<a href="https://github.com/withastro" title="Astro websie builder" > <img src="https://avatars.githubusercontent.com/u/44914786?v=4" width="60px" ></a>
|
||||||
|
<a href="https://github.com/baidu" title="Baidu" > <img src="https://avatars.githubusercontent.com/u/13245940?v=4" width="60px" ></a>
|
||||||
|
[more](./USERs.md)
|
||||||
|
|
||||||
|
<small>The list of users are mostly published by Github or communicated directly. Feel free to contact if you find any information wrong.</small>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Main Features
|
||||||
|
|
||||||
|
<img align="right" src="static/img/fxp_logo.png" width="180px" alt="FXP logo"/>
|
||||||
|
|
||||||
|
* Validate XML data syntactically
|
||||||
|
* Parse XML to JS Object
|
||||||
|
* Build XML from JS Object
|
||||||
|
* Compatible to node js packages, in browser, and in CLI (click try me button above for demo)
|
||||||
|
* Faster than any other pure JS implementation.
|
||||||
|
* It can handle big files (tested up to 100mb).
|
||||||
|
* Controlled parsing using various options
|
||||||
|
* XML Entities, HTML entities, and DOCTYPE entites are supported.
|
||||||
|
* unpaired tags (Eg `<br>` in HTML), stop nodes (Eg `<script>` in HTML) are supported.
|
||||||
|
* You can restore almost same XML from JSON
|
||||||
|
* Supports comments
|
||||||
|
* It can preserve Order of tags in JS object
|
||||||
|
* You can control if a single tag should be parsed into array.
|
||||||
|
* Supports parsing of PI (Processing Instruction) tags with XML declaration tags
|
||||||
|
* And many more other features.
|
||||||
|
|
||||||
|
## v5
|
||||||
|
I developed v5 in Apr 2023. And I didn't get the chance to complete all the features. I've ensured that new features don't impact performance. With v5, you have more control on parsing output. Check [docs](./docs/v5) for syntax help and basic understanding.
|
||||||
|
|
||||||
|
Please leave a comment in discussion forum for your suggestions and if you really need v5.
|
||||||
|
|
||||||
|
## How to use
|
||||||
|
|
||||||
|
To use as package dependency
|
||||||
|
`$ npm install fast-xml-parser`
|
||||||
|
or
|
||||||
|
`$ yarn add fast-xml-parser`
|
||||||
|
|
||||||
|
To use as system command
|
||||||
|
`$ npm install fast-xml-parser -g`
|
||||||
|
|
||||||
|
To use it on a **webpage** include it from a [CDN](https://cdnjs.com/libraries/fast-xml-parser)
|
||||||
|
|
||||||
|
**Example**
|
||||||
|
|
||||||
|
As CLI command
|
||||||
|
```bash
|
||||||
|
$ fxparser some.xml
|
||||||
|
```
|
||||||
|
|
||||||
|
In a node js project
|
||||||
|
```js
|
||||||
|
const { XMLParser, XMLBuilder, XMLValidator} = require("fast-xml-parser");
|
||||||
|
|
||||||
|
const parser = new XMLParser();
|
||||||
|
let jObj = parser.parse(XMLdata);
|
||||||
|
|
||||||
|
const builder = new XMLBuilder();
|
||||||
|
const xmlContent = builder.build(jObj);
|
||||||
|
```
|
||||||
|
|
||||||
|
In a HTML page
|
||||||
|
```html
|
||||||
|
<script src="path/to/fxp.min.js"></script>
|
||||||
|
:
|
||||||
|
<script>
|
||||||
|
const parser = new fxparser.XMLParser();
|
||||||
|
parser.parse(xmlContent);
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
Bundle size
|
||||||
|
|
||||||
|
| Bundle Name | Size |
|
||||||
|
| ------------------ | ---- |
|
||||||
|
| fxbuilder.min.js | 6.5K |
|
||||||
|
| fxparser.min.js | 20K |
|
||||||
|
| fxp.min.js | 26K |
|
||||||
|
| fxvalidator.min.js | 5.7K |
|
||||||
|
|
||||||
|
### Documents
|
||||||
|
<table>
|
||||||
|
<tr><td>v3</td><td>v4</td><td>v5</td></tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="./docs/v3/docs.md">documents</a>
|
||||||
|
</td>
|
||||||
|
<td><ol>
|
||||||
|
<li><a href="./docs/v4/1.GettingStarted.md">Getting Started</a></li>
|
||||||
|
<li><a href="./docs/v4/2.XMLparseOptions.md">XML Parser</a></li>
|
||||||
|
<li><a href="./docs/v4/3.XMLBuilder.md">XML Builder</a></li>
|
||||||
|
<li><a href="./docs/v4/4.XMLValidator.md">XML Validator</a></li>
|
||||||
|
<li><a href="./docs/v4/5.Entities.md">Entities</a></li>
|
||||||
|
<li><a href="./docs/v4/6.HTMLParsing.md">HTML Document Parsing</a></li>
|
||||||
|
<li><a href="./docs/v4/7.PITags.md">PI Tag processing</a></li>
|
||||||
|
</ol></td>
|
||||||
|
<td><ol>
|
||||||
|
<li></li><a href="./docs/v5/1.GettingStarted.md">Getting Started</a></li>
|
||||||
|
<li><a href="./docs/v5/2.Features.md">Features</a></li>
|
||||||
|
<li><a href="./docs/v5/3.Options.md">Options</a></li>
|
||||||
|
<li><a href="./docs/v5/4.OutputBuilders.md">Output Builders</a></li>
|
||||||
|
<li><a href="./docs/v5/5.ValueParsers.md">Value Parsers</a></li>
|
||||||
|
</ol></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
**note**: version 5 is released with version 4 tfor experimental use. Based on it's demand, it'll be developed and the features can be different in final release.
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
<small>negative means error</small>
|
||||||
|
|
||||||
|
### XML Parser
|
||||||
|
|
||||||
|
<img align="left" src="./docs/imgs/XMLParser_v4.png" width="45%" />
|
||||||
|
<img src="./docs/imgs/XMLParser_large_v4.png" width="47%" />
|
||||||
|
|
||||||
|
* Y-axis: requests per second
|
||||||
|
* X-axis: File size
|
||||||
|
|
||||||
|
### XML Builder
|
||||||
|
|
||||||
|
<img src="./docs/imgs/XMLBuilder_v4.png" width="50%" />
|
||||||
|
* Y-axis: requests per second
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- [](https://github.com/NaturalIntelligence/ads/) -->
|
||||||
|
|
||||||
|
|
||||||
|
## Usage Trend
|
||||||
|
|
||||||
|
[Usage Trend of fast-xml-parser](https://npm-compare.com/fast-xml-parser#timeRange=THREE_YEARS)
|
||||||
|
|
||||||
|
<a href="https://npm-compare.com/fast-xml-parser#timeRange=THREE_YEARS" target="_blank">
|
||||||
|
<img src="https://npm-compare.com/img/npm-trend/THREE_YEARS/fast-xml-parser.png" width="50%" alt="NPM Usage Trend of fast-xml-parser" />
|
||||||
|
</a>
|
||||||
|
|
||||||
|
## Supporters
|
||||||
|
### Contributors
|
||||||
|
|
||||||
|
This project exists thanks to [all](graphs/contributors) the people who contribute. [[Contribute](docs/CONTRIBUTING.md)].
|
||||||
|
<!-- <a href="graphs/contributors"><img src="https://opencollective.com/fast-xml-parser/contributors.svg?width=890&button=false" /></a> -->
|
||||||
|
<!--
|
||||||
|
### Lead Maintainers
|
||||||
|

|
||||||
|
[](https://github.com/Delagen)
|
||||||
|
|
||||||
|
### All Contributors -->
|
||||||
|
<a href="graphs/contributors"><img src="https://opencollective.com/fast-xml-parser/contributors.svg?width=890&button=false" /></a>
|
||||||
|
|
||||||
|
### Backers
|
||||||
|
|
||||||
|
Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/fast-xml-parser#backer)]
|
||||||
|
|
||||||
|
<a href="https://opencollective.com/fast-xml-parser#backers" target="_blank"><img src="https://opencollective.com/fast-xml-parser/backers.svg?width=890"></a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# License
|
||||||
|
* MIT License
|
||||||
|
|
||||||
|

|
||||||
72
node_modules/fast-xml-parser/package.json
generated
vendored
Normal file
72
node_modules/fast-xml-parser/package.json
generated
vendored
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
{
|
||||||
|
"name": "fast-xml-parser",
|
||||||
|
"version": "4.5.3",
|
||||||
|
"description": "Validate XML, Parse XML, Build XML without C/C++ based libraries",
|
||||||
|
"main": "./src/fxp.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "nyc --reporter=lcov --reporter=text jasmine spec/*spec.js",
|
||||||
|
"test-types": "tsc --noEmit spec/typings/typings-test.ts",
|
||||||
|
"unit": "jasmine",
|
||||||
|
"coverage": "nyc report --reporter html --reporter text -t .nyc_output --report-dir .nyc_output/summary",
|
||||||
|
"perf": "node ./benchmark/perfTest3.js",
|
||||||
|
"lint": "eslint src/*.js spec/*.js",
|
||||||
|
"bundle": "webpack --config webpack-prod.config.js",
|
||||||
|
"prettier": "prettier --write src/**/*.js",
|
||||||
|
"publish-please": "publish-please",
|
||||||
|
"checkReadiness": "publish-please --dry-run"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"fxparser": "./src/cli/cli.js"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/NaturalIntelligence/fast-xml-parser"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"fast",
|
||||||
|
"xml",
|
||||||
|
"json",
|
||||||
|
"parser",
|
||||||
|
"xml2js",
|
||||||
|
"x2js",
|
||||||
|
"xml2json",
|
||||||
|
"js",
|
||||||
|
"cli",
|
||||||
|
"validator",
|
||||||
|
"validate",
|
||||||
|
"transformer",
|
||||||
|
"assert",
|
||||||
|
"js2xml",
|
||||||
|
"json2xml",
|
||||||
|
"html"
|
||||||
|
],
|
||||||
|
"author": "Amit Gupta (https://solothought.com)",
|
||||||
|
"license": "MIT",
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.13.10",
|
||||||
|
"@babel/plugin-transform-runtime": "^7.13.10",
|
||||||
|
"@babel/preset-env": "^7.13.10",
|
||||||
|
"@babel/register": "^7.13.8",
|
||||||
|
"@types/node": "20",
|
||||||
|
"babel-loader": "^8.2.2",
|
||||||
|
"eslint": "^8.3.0",
|
||||||
|
"he": "^1.2.0",
|
||||||
|
"jasmine": "^3.6.4",
|
||||||
|
"nyc": "^15.1.0",
|
||||||
|
"prettier": "^1.19.1",
|
||||||
|
"publish-please": "^5.5.2",
|
||||||
|
"typescript": "5",
|
||||||
|
"webpack": "^5.64.4",
|
||||||
|
"webpack-cli": "^4.9.1"
|
||||||
|
},
|
||||||
|
"typings": "src/fxp.d.ts",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/NaturalIntelligence"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"strnum": "^1.1.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
93
node_modules/fast-xml-parser/src/cli/cli.js
generated
vendored
Executable file
93
node_modules/fast-xml-parser/src/cli/cli.js
generated
vendored
Executable file
@ -0,0 +1,93 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
'use strict';
|
||||||
|
/*eslint-disable no-console*/
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const {XMLParser, XMLValidator} = require("../fxp");
|
||||||
|
const readToEnd = require('./read').readToEnd;
|
||||||
|
|
||||||
|
const version = require('./../../package.json').version;
|
||||||
|
if (process.argv[2] === '--help' || process.argv[2] === '-h') {
|
||||||
|
console.log(require("./man"));
|
||||||
|
} else if (process.argv[2] === '--version') {
|
||||||
|
console.log(version);
|
||||||
|
} else {
|
||||||
|
const options = {
|
||||||
|
removeNSPrefix: true,
|
||||||
|
ignoreAttributes: false,
|
||||||
|
parseTagValue: true,
|
||||||
|
parseAttributeValue: true,
|
||||||
|
};
|
||||||
|
let fileName = '';
|
||||||
|
let outputFileName;
|
||||||
|
let validate = false;
|
||||||
|
let validateOnly = false;
|
||||||
|
for (let i = 2; i < process.argv.length; i++) {
|
||||||
|
if (process.argv[i] === '-ns') {
|
||||||
|
options.removeNSPrefix = false;
|
||||||
|
} else if (process.argv[i] === '-a') {
|
||||||
|
options.ignoreAttributes = true;
|
||||||
|
} else if (process.argv[i] === '-c') {
|
||||||
|
options.parseTagValue = false;
|
||||||
|
options.parseAttributeValue = false;
|
||||||
|
} else if (process.argv[i] === '-o') {
|
||||||
|
outputFileName = process.argv[++i];
|
||||||
|
} else if (process.argv[i] === '-v') {
|
||||||
|
validate = true;
|
||||||
|
} else if (process.argv[i] === '-V') {
|
||||||
|
validateOnly = true;
|
||||||
|
} else {
|
||||||
|
//filename
|
||||||
|
fileName = process.argv[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const callback = function(xmlData) {
|
||||||
|
let output = '';
|
||||||
|
if (validate) {
|
||||||
|
const parser = new XMLParser(options);
|
||||||
|
output = parser.parse(xmlData,validate);
|
||||||
|
} else if (validateOnly) {
|
||||||
|
output = XMLValidator.validate(xmlData);
|
||||||
|
process.exitCode = output === true ? 0 : 1;
|
||||||
|
} else {
|
||||||
|
const parser = new XMLParser(options);
|
||||||
|
output = JSON.stringify(parser.parse(xmlData,validate), null, 4);
|
||||||
|
}
|
||||||
|
if (outputFileName) {
|
||||||
|
writeToFile(outputFileName, output);
|
||||||
|
} else {
|
||||||
|
console.log(JSON.stringify(output, null, 2));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
if (!fileName) {
|
||||||
|
readToEnd(process.stdin, function(err, data) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
callback(data.toString());
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
fs.readFile(fileName, function(err, data) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
callback(data.toString());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log('Seems an invalid file or stream.' + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeToFile(fileName, data) {
|
||||||
|
fs.writeFile(fileName, data, function(err) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
console.log('JSON output has been written to ' + fileName);
|
||||||
|
});
|
||||||
|
}
|
||||||
12
node_modules/fast-xml-parser/src/cli/man.js
generated
vendored
Normal file
12
node_modules/fast-xml-parser/src/cli/man.js
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
module.exports = `Fast XML Parser 4.0.0
|
||||||
|
----------------
|
||||||
|
$ fxparser [-ns|-a|-c|-v|-V] <filename> [-o outputfile.json]
|
||||||
|
$ cat xmlfile.xml | fxparser [-ns|-a|-c|-v|-V] [-o outputfile.json]
|
||||||
|
|
||||||
|
Options
|
||||||
|
----------------
|
||||||
|
-ns: remove namespace from tag and atrribute name.
|
||||||
|
-a: don't parse attributes.
|
||||||
|
-c: parse values to premitive type.
|
||||||
|
-v: validate before parsing.
|
||||||
|
-V: validate only.`
|
||||||
92
node_modules/fast-xml-parser/src/cli/read.js
generated
vendored
Normal file
92
node_modules/fast-xml-parser/src/cli/read.js
generated
vendored
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
// Copyright 2013 Timothy J Fontaine <tjfontaine@gmail.com>
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the 'Software'), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Read any stream all the way to the end and trigger a single cb
|
||||||
|
|
||||||
|
const http = require('http');
|
||||||
|
|
||||||
|
const rte = require('readtoend');
|
||||||
|
|
||||||
|
http.get('http://nodejs.org', function(response) {
|
||||||
|
rte.readToEnd(response, function(err, body) {
|
||||||
|
console.log(body);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
let stream = require('stream');
|
||||||
|
const util = require('util');
|
||||||
|
|
||||||
|
if (!stream.Transform) {
|
||||||
|
stream = require('readable-stream');
|
||||||
|
}
|
||||||
|
|
||||||
|
function ReadToEnd(opts) {
|
||||||
|
if (!(this instanceof ReadToEnd)) {
|
||||||
|
return new ReadToEnd(opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.Transform.call(this, opts);
|
||||||
|
|
||||||
|
this._rte_encoding = opts.encoding || 'utf8';
|
||||||
|
|
||||||
|
this._buff = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ReadToEnd;
|
||||||
|
util.inherits(ReadToEnd, stream.Transform);
|
||||||
|
|
||||||
|
ReadToEnd.prototype._transform = function(chunk, encoding, done) {
|
||||||
|
this._buff += chunk.toString(this._rte_encoding);
|
||||||
|
this.push(chunk);
|
||||||
|
done();
|
||||||
|
};
|
||||||
|
|
||||||
|
ReadToEnd.prototype._flush = function(done) {
|
||||||
|
this.emit('complete', undefined, this._buff);
|
||||||
|
done();
|
||||||
|
};
|
||||||
|
|
||||||
|
ReadToEnd.readToEnd = function(stream, options, cb) {
|
||||||
|
if (!cb) {
|
||||||
|
cb = options;
|
||||||
|
options = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const dest = new ReadToEnd(options);
|
||||||
|
|
||||||
|
stream.pipe(dest);
|
||||||
|
|
||||||
|
stream.on('error', function(err) {
|
||||||
|
stream.unpipe(dest);
|
||||||
|
cb(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
dest.on('complete', cb);
|
||||||
|
|
||||||
|
dest.resume();
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
};
|
||||||
418
node_modules/fast-xml-parser/src/fxp.d.ts
generated
vendored
Normal file
418
node_modules/fast-xml-parser/src/fxp.d.ts
generated
vendored
Normal file
@ -0,0 +1,418 @@
|
|||||||
|
type X2jOptions = {
|
||||||
|
/**
|
||||||
|
* Preserve the order of tags in resulting JS object
|
||||||
|
*
|
||||||
|
* Defaults to `false`
|
||||||
|
*/
|
||||||
|
preserveOrder?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Give a prefix to the attribute name in the resulting JS object
|
||||||
|
*
|
||||||
|
* Defaults to '@_'
|
||||||
|
*/
|
||||||
|
attributeNamePrefix?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A name to group all attributes of a tag under, or `false` to disable
|
||||||
|
*
|
||||||
|
* Defaults to `false`
|
||||||
|
*/
|
||||||
|
attributesGroupName?: false | string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the next node in the resulting JS
|
||||||
|
*
|
||||||
|
* Defaults to `#text`
|
||||||
|
*/
|
||||||
|
textNodeName?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to ignore attributes when parsing
|
||||||
|
*
|
||||||
|
* When `true` - ignores all the attributes
|
||||||
|
*
|
||||||
|
* When `false` - parses all the attributes
|
||||||
|
*
|
||||||
|
* When `Array<string | RegExp>` - filters out attributes that match provided patterns
|
||||||
|
*
|
||||||
|
* When `Function` - calls the function for each attribute and filters out those for which the function returned `true`
|
||||||
|
*
|
||||||
|
* Defaults to `true`
|
||||||
|
*/
|
||||||
|
ignoreAttributes?: boolean | (string | RegExp)[] | ((attrName: string, jPath: string) => boolean);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to remove namespace string from tag and attribute names
|
||||||
|
*
|
||||||
|
* Defaults to `false`
|
||||||
|
*/
|
||||||
|
removeNSPrefix?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to allow attributes without value
|
||||||
|
*
|
||||||
|
* Defaults to `false`
|
||||||
|
*/
|
||||||
|
allowBooleanAttributes?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to parse tag value with `strnum` package
|
||||||
|
*
|
||||||
|
* Defaults to `true`
|
||||||
|
*/
|
||||||
|
parseTagValue?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to parse tag value with `strnum` package
|
||||||
|
*
|
||||||
|
* Defaults to `false`
|
||||||
|
*/
|
||||||
|
parseAttributeValue?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to remove surrounding whitespace from tag or attribute value
|
||||||
|
*
|
||||||
|
* Defaults to `true`
|
||||||
|
*/
|
||||||
|
trimValues?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Give a property name to set CDATA values to instead of merging to tag's text value
|
||||||
|
*
|
||||||
|
* Defaults to `false`
|
||||||
|
*/
|
||||||
|
cdataPropName?: false | string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set, parse comments and set as this property
|
||||||
|
*
|
||||||
|
* Defaults to `false`
|
||||||
|
*/
|
||||||
|
commentPropName?: false | string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Control how tag value should be parsed. Called only if tag value is not empty
|
||||||
|
*
|
||||||
|
* @returns {undefined|null} `undefined` or `null` to set original value.
|
||||||
|
* @returns {unknown}
|
||||||
|
*
|
||||||
|
* 1. Different value or value with different data type to set new value.
|
||||||
|
* 2. Same value to set parsed value if `parseTagValue: true`.
|
||||||
|
*
|
||||||
|
* Defaults to `(tagName, val, jPath, hasAttributes, isLeafNode) => val`
|
||||||
|
*/
|
||||||
|
tagValueProcessor?: (tagName: string, tagValue: string, jPath: string, hasAttributes: boolean, isLeafNode: boolean) => unknown;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Control how attribute value should be parsed
|
||||||
|
*
|
||||||
|
* @param attrName
|
||||||
|
* @param attrValue
|
||||||
|
* @param jPath
|
||||||
|
* @returns {undefined|null} `undefined` or `null` to set original value
|
||||||
|
* @returns {unknown}
|
||||||
|
*
|
||||||
|
* Defaults to `(attrName, val, jPath) => val`
|
||||||
|
*/
|
||||||
|
attributeValueProcessor?: (attrName: string, attrValue: string, jPath: string) => unknown;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options to pass to `strnum` for parsing numbers
|
||||||
|
*
|
||||||
|
* Defaults to `{ hex: true, leadingZeros: true, eNotation: true }`
|
||||||
|
*/
|
||||||
|
numberParseOptions?: strnumOptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Nodes to stop parsing at
|
||||||
|
*
|
||||||
|
* Defaults to `[]`
|
||||||
|
*/
|
||||||
|
stopNodes?: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of tags without closing tags
|
||||||
|
*
|
||||||
|
* Defaults to `[]`
|
||||||
|
*/
|
||||||
|
unpairedTags?: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to always create a text node
|
||||||
|
*
|
||||||
|
* Defaults to `false`
|
||||||
|
*/
|
||||||
|
alwaysCreateTextNode?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether a tag should be parsed as an array
|
||||||
|
*
|
||||||
|
* @param tagName
|
||||||
|
* @param jPath
|
||||||
|
* @param isLeafNode
|
||||||
|
* @param isAttribute
|
||||||
|
* @returns {boolean}
|
||||||
|
*
|
||||||
|
* Defaults to `() => false`
|
||||||
|
*/
|
||||||
|
isArray?: (tagName: string, jPath: string, isLeafNode: boolean, isAttribute: boolean) => boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to process default and DOCTYPE entities
|
||||||
|
*
|
||||||
|
* Defaults to `true`
|
||||||
|
*/
|
||||||
|
processEntities?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to process HTML entities
|
||||||
|
*
|
||||||
|
* Defaults to `false`
|
||||||
|
*/
|
||||||
|
htmlEntities?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to ignore the declaration tag from output
|
||||||
|
*
|
||||||
|
* Defaults to `false`
|
||||||
|
*/
|
||||||
|
ignoreDeclaration?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to ignore Pi tags
|
||||||
|
*
|
||||||
|
* Defaults to `false`
|
||||||
|
*/
|
||||||
|
ignorePiTags?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform tag names
|
||||||
|
*
|
||||||
|
* Defaults to `false`
|
||||||
|
*/
|
||||||
|
transformTagName?: ((tagName: string) => string) | false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform attribute names
|
||||||
|
*
|
||||||
|
* Defaults to `false`
|
||||||
|
*/
|
||||||
|
transformAttributeName?: ((attributeName: string) => string) | false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change the tag name when a different name is returned. Skip the tag from parsed result when false is returned.
|
||||||
|
* Modify `attrs` object to control attributes for the given tag.
|
||||||
|
*
|
||||||
|
* @returns {string} new tag name.
|
||||||
|
* @returns false to skip the tag
|
||||||
|
*
|
||||||
|
* Defaults to `(tagName, jPath, attrs) => tagName`
|
||||||
|
*/
|
||||||
|
updateTag?: (tagName: string, jPath: string, attrs: {[k: string]: string}) => string | boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
type strnumOptions = {
|
||||||
|
hex: boolean;
|
||||||
|
leadingZeros: boolean,
|
||||||
|
skipLike?: RegExp,
|
||||||
|
eNotation?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
type validationOptions = {
|
||||||
|
/**
|
||||||
|
* Whether to allow attributes without value
|
||||||
|
*
|
||||||
|
* Defaults to `false`
|
||||||
|
*/
|
||||||
|
allowBooleanAttributes?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of tags without closing tags
|
||||||
|
*
|
||||||
|
* Defaults to `[]`
|
||||||
|
*/
|
||||||
|
unpairedTags?: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
type XmlBuilderOptions = {
|
||||||
|
/**
|
||||||
|
* Give a prefix to the attribute name in the resulting JS object
|
||||||
|
*
|
||||||
|
* Defaults to '@_'
|
||||||
|
*/
|
||||||
|
attributeNamePrefix?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A name to group all attributes of a tag under, or `false` to disable
|
||||||
|
*
|
||||||
|
* Defaults to `false`
|
||||||
|
*/
|
||||||
|
attributesGroupName?: false | string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the next node in the resulting JS
|
||||||
|
*
|
||||||
|
* Defaults to `#text`
|
||||||
|
*/
|
||||||
|
textNodeName?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to ignore attributes when building
|
||||||
|
*
|
||||||
|
* When `true` - ignores all the attributes
|
||||||
|
*
|
||||||
|
* When `false` - builds all the attributes
|
||||||
|
*
|
||||||
|
* When `Array<string | RegExp>` - filters out attributes that match provided patterns
|
||||||
|
*
|
||||||
|
* When `Function` - calls the function for each attribute and filters out those for which the function returned `true`
|
||||||
|
*
|
||||||
|
* Defaults to `true`
|
||||||
|
*/
|
||||||
|
ignoreAttributes?: boolean | (string | RegExp)[] | ((attrName: string, jPath: string) => boolean);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Give a property name to set CDATA values to instead of merging to tag's text value
|
||||||
|
*
|
||||||
|
* Defaults to `false`
|
||||||
|
*/
|
||||||
|
cdataPropName?: false | string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set, parse comments and set as this property
|
||||||
|
*
|
||||||
|
* Defaults to `false`
|
||||||
|
*/
|
||||||
|
commentPropName?: false | string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to make output pretty instead of single line
|
||||||
|
*
|
||||||
|
* Defaults to `false`
|
||||||
|
*/
|
||||||
|
format?: boolean;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If `format` is set to `true`, sets the indent string
|
||||||
|
*
|
||||||
|
* Defaults to ` `
|
||||||
|
*/
|
||||||
|
indentBy?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Give a name to a top-level array
|
||||||
|
*
|
||||||
|
* Defaults to `undefined`
|
||||||
|
*/
|
||||||
|
arrayNodeName?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create empty tags for tags with no text value
|
||||||
|
*
|
||||||
|
* Defaults to `false`
|
||||||
|
*/
|
||||||
|
suppressEmptyNode?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Suppress an unpaired tag
|
||||||
|
*
|
||||||
|
* Defaults to `true`
|
||||||
|
*/
|
||||||
|
suppressUnpairedNode?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Don't put a value for boolean attributes
|
||||||
|
*
|
||||||
|
* Defaults to `true`
|
||||||
|
*/
|
||||||
|
suppressBooleanAttributes?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Preserve the order of tags in resulting JS object
|
||||||
|
*
|
||||||
|
* Defaults to `false`
|
||||||
|
*/
|
||||||
|
preserveOrder?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of tags without closing tags
|
||||||
|
*
|
||||||
|
* Defaults to `[]`
|
||||||
|
*/
|
||||||
|
unpairedTags?: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Nodes to stop parsing at
|
||||||
|
*
|
||||||
|
* Defaults to `[]`
|
||||||
|
*/
|
||||||
|
stopNodes?: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Control how tag value should be parsed. Called only if tag value is not empty
|
||||||
|
*
|
||||||
|
* @returns {undefined|null} `undefined` or `null` to set original value.
|
||||||
|
* @returns {unknown}
|
||||||
|
*
|
||||||
|
* 1. Different value or value with different data type to set new value.
|
||||||
|
* 2. Same value to set parsed value if `parseTagValue: true`.
|
||||||
|
*
|
||||||
|
* Defaults to `(tagName, val, jPath, hasAttributes, isLeafNode) => val`
|
||||||
|
*/
|
||||||
|
tagValueProcessor?: (name: string, value: unknown) => unknown;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Control how attribute value should be parsed
|
||||||
|
*
|
||||||
|
* @param attrName
|
||||||
|
* @param attrValue
|
||||||
|
* @param jPath
|
||||||
|
* @returns {undefined|null} `undefined` or `null` to set original value
|
||||||
|
* @returns {unknown}
|
||||||
|
*
|
||||||
|
* Defaults to `(attrName, val, jPath) => val`
|
||||||
|
*/
|
||||||
|
attributeValueProcessor?: (name: string, value: unknown) => unknown;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to process default and DOCTYPE entities
|
||||||
|
*
|
||||||
|
* Defaults to `true`
|
||||||
|
*/
|
||||||
|
processEntities?: boolean;
|
||||||
|
|
||||||
|
|
||||||
|
oneListGroup?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ESchema = string | object | Array<string|object>;
|
||||||
|
|
||||||
|
type ValidationError = {
|
||||||
|
err: {
|
||||||
|
code: string;
|
||||||
|
msg: string,
|
||||||
|
line: number,
|
||||||
|
col: number
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export class XMLParser {
|
||||||
|
constructor(options?: X2jOptions);
|
||||||
|
parse(xmlData: string | Buffer ,validationOptions?: validationOptions | boolean): any;
|
||||||
|
/**
|
||||||
|
* Add Entity which is not by default supported by this library
|
||||||
|
* @param entityIdentifier {string} Eg: 'ent' for &ent;
|
||||||
|
* @param entityValue {string} Eg: '\r'
|
||||||
|
*/
|
||||||
|
addEntity(entityIdentifier: string, entityValue: string): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class XMLValidator{
|
||||||
|
static validate( xmlData: string, options?: validationOptions): true | ValidationError;
|
||||||
|
}
|
||||||
|
export class XMLBuilder {
|
||||||
|
constructor(options?: XmlBuilderOptions);
|
||||||
|
build(jObj: any): any;
|
||||||
|
}
|
||||||
11
node_modules/fast-xml-parser/src/fxp.js
generated
vendored
Normal file
11
node_modules/fast-xml-parser/src/fxp.js
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const validator = require('./validator');
|
||||||
|
const XMLParser = require('./xmlparser/XMLParser');
|
||||||
|
const XMLBuilder = require('./xmlbuilder/json2xml');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
XMLParser: XMLParser,
|
||||||
|
XMLValidator: validator,
|
||||||
|
XMLBuilder: XMLBuilder
|
||||||
|
}
|
||||||
20
node_modules/fast-xml-parser/src/ignoreAttributes.js
generated
vendored
Normal file
20
node_modules/fast-xml-parser/src/ignoreAttributes.js
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
function getIgnoreAttributesFn(ignoreAttributes) {
|
||||||
|
if (typeof ignoreAttributes === 'function') {
|
||||||
|
return ignoreAttributes
|
||||||
|
}
|
||||||
|
if (Array.isArray(ignoreAttributes)) {
|
||||||
|
return (attrName) => {
|
||||||
|
for (const pattern of ignoreAttributes) {
|
||||||
|
if (typeof pattern === 'string' && attrName === pattern) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (pattern instanceof RegExp && pattern.test(attrName)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return () => false
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = getIgnoreAttributesFn
|
||||||
72
node_modules/fast-xml-parser/src/util.js
generated
vendored
Normal file
72
node_modules/fast-xml-parser/src/util.js
generated
vendored
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
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';
|
||||||
|
const nameChar = nameStartChar + '\\-.\\d\\u00B7\\u0300-\\u036F\\u203F-\\u2040';
|
||||||
|
const nameRegexp = '[' + nameStartChar + '][' + nameChar + ']*'
|
||||||
|
const regexName = new RegExp('^' + nameRegexp + '$');
|
||||||
|
|
||||||
|
const getAllMatches = function(string, regex) {
|
||||||
|
const matches = [];
|
||||||
|
let match = regex.exec(string);
|
||||||
|
while (match) {
|
||||||
|
const allmatches = [];
|
||||||
|
allmatches.startIndex = regex.lastIndex - match[0].length;
|
||||||
|
const len = match.length;
|
||||||
|
for (let index = 0; index < len; index++) {
|
||||||
|
allmatches.push(match[index]);
|
||||||
|
}
|
||||||
|
matches.push(allmatches);
|
||||||
|
match = regex.exec(string);
|
||||||
|
}
|
||||||
|
return matches;
|
||||||
|
};
|
||||||
|
|
||||||
|
const isName = function(string) {
|
||||||
|
const match = regexName.exec(string);
|
||||||
|
return !(match === null || typeof match === 'undefined');
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.isExist = function(v) {
|
||||||
|
return typeof v !== 'undefined';
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.isEmptyObject = function(obj) {
|
||||||
|
return Object.keys(obj).length === 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy all the properties of a into b.
|
||||||
|
* @param {*} target
|
||||||
|
* @param {*} a
|
||||||
|
*/
|
||||||
|
exports.merge = function(target, a, arrayMode) {
|
||||||
|
if (a) {
|
||||||
|
const keys = Object.keys(a); // will return an array of own properties
|
||||||
|
const len = keys.length; //don't make it inline
|
||||||
|
for (let i = 0; i < len; i++) {
|
||||||
|
if (arrayMode === 'strict') {
|
||||||
|
target[keys[i]] = [ a[keys[i]] ];
|
||||||
|
} else {
|
||||||
|
target[keys[i]] = a[keys[i]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/* exports.merge =function (b,a){
|
||||||
|
return Object.assign(b,a);
|
||||||
|
} */
|
||||||
|
|
||||||
|
exports.getValue = function(v) {
|
||||||
|
if (exports.isExist(v)) {
|
||||||
|
return v;
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// const fakeCall = function(a) {return a;};
|
||||||
|
// const fakeCallNoReturn = function() {};
|
||||||
|
|
||||||
|
exports.isName = isName;
|
||||||
|
exports.getAllMatches = getAllMatches;
|
||||||
|
exports.nameRegexp = nameRegexp;
|
||||||
16
node_modules/fast-xml-parser/src/v5/CharsSymbol.js
generated
vendored
Normal file
16
node_modules/fast-xml-parser/src/v5/CharsSymbol.js
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
modules.export = {
|
||||||
|
"<" : "<", //tag start
|
||||||
|
">" : ">", //tag end
|
||||||
|
"/" : "/", //close tag
|
||||||
|
"!" : "!", //comment or docttype
|
||||||
|
"!--" : "!--", //comment
|
||||||
|
"-->" : "-->", //comment end
|
||||||
|
"?" : "?", //pi
|
||||||
|
"?>" : "?>", //pi end
|
||||||
|
"?xml" : "?xml", //pi end
|
||||||
|
"![" : "![", //cdata
|
||||||
|
"]]>" : "]]>", //cdata end
|
||||||
|
"[" : "[",
|
||||||
|
"-" : "-",
|
||||||
|
"D" : "D",
|
||||||
|
}
|
||||||
107
node_modules/fast-xml-parser/src/v5/EntitiesParser.js
generated
vendored
Normal file
107
node_modules/fast-xml-parser/src/v5/EntitiesParser.js
generated
vendored
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
const ampEntity = { regex: /&(amp|#38|#x26);/g, val : "&"};
|
||||||
|
const htmlEntities = {
|
||||||
|
"space": { regex: /&(nbsp|#160);/g, val: " " },
|
||||||
|
// "lt" : { regex: /&(lt|#60);/g, val: "<" },
|
||||||
|
// "gt" : { regex: /&(gt|#62);/g, val: ">" },
|
||||||
|
// "amp" : { regex: /&(amp|#38);/g, val: "&" },
|
||||||
|
// "quot" : { regex: /&(quot|#34);/g, val: "\"" },
|
||||||
|
// "apos" : { regex: /&(apos|#39);/g, val: "'" },
|
||||||
|
"cent" : { regex: /&(cent|#162);/g, val: "¢" },
|
||||||
|
"pound" : { regex: /&(pound|#163);/g, val: "£" },
|
||||||
|
"yen" : { regex: /&(yen|#165);/g, val: "¥" },
|
||||||
|
"euro" : { regex: /&(euro|#8364);/g, val: "€" },
|
||||||
|
"copyright" : { regex: /&(copy|#169);/g, val: "©" },
|
||||||
|
"reg" : { regex: /&(reg|#174);/g, val: "®" },
|
||||||
|
"inr" : { regex: /&(inr|#8377);/g, val: "₹" },
|
||||||
|
"num_dec": { regex: /&#([0-9]{1,7});/g, val : (_, str) => String.fromCharCode(Number.parseInt(str, 10)) },
|
||||||
|
"num_hex": { regex: /&#x([0-9a-fA-F]{1,6});/g, val : (_, str) => String.fromCharCode(Number.parseInt(str, 16)) },
|
||||||
|
};
|
||||||
|
|
||||||
|
class EntitiesParser{
|
||||||
|
constructor(replaceHtmlEntities) {
|
||||||
|
this.replaceHtmlEntities = replaceHtmlEntities;
|
||||||
|
this.docTypeEntities = {};
|
||||||
|
this.lastEntities = {
|
||||||
|
"apos" : { regex: /&(apos|#39|#x27);/g, val : "'"},
|
||||||
|
"gt" : { regex: /&(gt|#62|#x3E);/g, val : ">"},
|
||||||
|
"lt" : { regex: /&(lt|#60|#x3C);/g, val : "<"},
|
||||||
|
"quot" : { regex: /&(quot|#34|#x22);/g, val : "\""},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
addExternalEntities(externalEntities){
|
||||||
|
const entKeys = Object.keys(externalEntities);
|
||||||
|
for (let i = 0; i < entKeys.length; i++) {
|
||||||
|
const ent = entKeys[i];
|
||||||
|
this.addExternalEntity(ent,externalEntities[ent])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addExternalEntity(key,val){
|
||||||
|
validateEntityName(key);
|
||||||
|
if(val.indexOf("&") !== -1) {
|
||||||
|
reportWarning(`Entity ${key} is not added as '&' is found in value;`)
|
||||||
|
return;
|
||||||
|
}else{
|
||||||
|
this.lastEntities[ent] = {
|
||||||
|
regex: new RegExp("&"+key+";","g"),
|
||||||
|
val : val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addDocTypeEntities(entities){
|
||||||
|
const entKeys = Object.keys(entities);
|
||||||
|
for (let i = 0; i < entKeys.length; i++) {
|
||||||
|
const ent = entKeys[i];
|
||||||
|
this.docTypeEntities[ent] = {
|
||||||
|
regex: new RegExp("&"+ent+";","g"),
|
||||||
|
val : entities[ent]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parse(val){
|
||||||
|
return this.replaceEntitiesValue(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Replace DOCTYPE entities
|
||||||
|
* 2. Replace external entities
|
||||||
|
* 3. Replace HTML entities if asked
|
||||||
|
* @param {string} val
|
||||||
|
*/
|
||||||
|
replaceEntitiesValue(val){
|
||||||
|
if(typeof val === "string" && val.length > 0){
|
||||||
|
for(let entityName in this.docTypeEntities){
|
||||||
|
const entity = this.docTypeEntities[entityName];
|
||||||
|
val = val.replace( entity.regx, entity.val);
|
||||||
|
}
|
||||||
|
for(let entityName in this.lastEntities){
|
||||||
|
const entity = this.lastEntities[entityName];
|
||||||
|
val = val.replace( entity.regex, entity.val);
|
||||||
|
}
|
||||||
|
if(this.replaceHtmlEntities){
|
||||||
|
for(let entityName in htmlEntities){
|
||||||
|
const entity = htmlEntities[entityName];
|
||||||
|
val = val.replace( entity.regex, entity.val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val = val.replace( ampEntity.regex, ampEntity.val);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//an entity name should not contains special characters that may be used in regex
|
||||||
|
//Eg !?\\\/[]$%{}^&*()<>
|
||||||
|
const specialChar = "!?\\\/[]$%{}^&*()<>|+";
|
||||||
|
|
||||||
|
function validateEntityName(name){
|
||||||
|
for (let i = 0; i < specialChar.length; i++) {
|
||||||
|
const ch = specialChar[i];
|
||||||
|
if(name.indexOf(ch) !== -1) throw new Error(`Invalid character ${ch} in entity name`);
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = EntitiesParser;
|
||||||
64
node_modules/fast-xml-parser/src/v5/OptionsBuilder.js
generated
vendored
Executable file
64
node_modules/fast-xml-parser/src/v5/OptionsBuilder.js
generated
vendored
Executable file
@ -0,0 +1,64 @@
|
|||||||
|
|
||||||
|
const JsObjOutputBuilder = require("./OutputBuilders/JsObjBuilder");
|
||||||
|
|
||||||
|
const defaultOptions = {
|
||||||
|
preserveOrder: false,
|
||||||
|
removeNSPrefix: false, // remove NS from tag name or attribute name if true
|
||||||
|
//ignoreRootElement : false,
|
||||||
|
stopNodes: [], //nested tags will not be parsed even for errors
|
||||||
|
// isArray: () => false, //User will set it
|
||||||
|
htmlEntities: false,
|
||||||
|
// skipEmptyListItem: false
|
||||||
|
tags:{
|
||||||
|
unpaired: [],
|
||||||
|
nameFor:{
|
||||||
|
cdata: false,
|
||||||
|
comment: false,
|
||||||
|
text: '#text'
|
||||||
|
},
|
||||||
|
separateTextProperty: false,
|
||||||
|
},
|
||||||
|
attributes:{
|
||||||
|
ignore: false,
|
||||||
|
booleanType: true,
|
||||||
|
entities: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
// select: ["img[src]"],
|
||||||
|
// stop: ["anim", "[ads]"]
|
||||||
|
only: [], // rest tags will be skipped. It will result in flat array
|
||||||
|
hierarchy: false, //will be used when a particular tag is set to be parsed.
|
||||||
|
skip: [], // will be skipped from parse result. on('skip') will be triggered
|
||||||
|
|
||||||
|
select: [], // on('select', tag => tag ) will be called if match
|
||||||
|
stop: [], //given tagPath will not be parsed. innerXML will be set as string value
|
||||||
|
OutputBuilder: new JsObjOutputBuilder(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const buildOptions = function(options) {
|
||||||
|
const finalOptions = { ... defaultOptions};
|
||||||
|
copyProperties(finalOptions,options)
|
||||||
|
return finalOptions;
|
||||||
|
};
|
||||||
|
|
||||||
|
function copyProperties(target, source) {
|
||||||
|
for (let key in source) {
|
||||||
|
if (source.hasOwnProperty(key)) {
|
||||||
|
if (key === 'OutputBuilder') {
|
||||||
|
target[key] = source[key];
|
||||||
|
}else if (typeof source[key] === 'object' && !Array.isArray(source[key])) {
|
||||||
|
// Recursively copy nested properties
|
||||||
|
if (typeof target[key] === 'undefined') {
|
||||||
|
target[key] = {};
|
||||||
|
}
|
||||||
|
copyProperties(target[key], source[key]);
|
||||||
|
} else {
|
||||||
|
// Copy non-nested properties
|
||||||
|
target[key] = source[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.buildOptions = buildOptions;
|
||||||
|
exports.defaultOptions = defaultOptions;
|
||||||
71
node_modules/fast-xml-parser/src/v5/OutputBuilders/BaseOutputBuilder.js
generated
vendored
Normal file
71
node_modules/fast-xml-parser/src/v5/OutputBuilders/BaseOutputBuilder.js
generated
vendored
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
class BaseOutputBuilder{
|
||||||
|
constructor(){
|
||||||
|
// this.attributes = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
addAttribute(name, value){
|
||||||
|
if(this.options.onAttribute){
|
||||||
|
//TODO: better to pass tag path
|
||||||
|
const v = this.options.onAttribute(name, value, this.tagName);
|
||||||
|
if(v) this.attributes[v.name] = v.value;
|
||||||
|
}else{
|
||||||
|
name = this.options.attributes.prefix + name + this.options.attributes.suffix;
|
||||||
|
this.attributes[name] = this.parseValue(value, this.options.attributes.valueParsers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* parse value by chain of parsers
|
||||||
|
* @param {string} val
|
||||||
|
* @returns {any} parsed value if matching parser found
|
||||||
|
*/
|
||||||
|
parseValue = function(val, valParsers){
|
||||||
|
for (let i = 0; i < valParsers.length; i++) {
|
||||||
|
let valParser = valParsers[i];
|
||||||
|
if(typeof valParser === "string"){
|
||||||
|
valParser = this.registeredParsers[valParser];
|
||||||
|
}
|
||||||
|
if(valParser){
|
||||||
|
val = valParser.parse(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To add a nested empty tag.
|
||||||
|
* @param {string} key
|
||||||
|
* @param {any} val
|
||||||
|
*/
|
||||||
|
_addChild(key, val){}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* skip the comment if property is not set
|
||||||
|
*/
|
||||||
|
addComment(text){
|
||||||
|
if(this.options.nameFor.comment)
|
||||||
|
this._addChild(this.options.nameFor.comment, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
//store CDATA separately if property is set
|
||||||
|
//otherwise add to tag's value
|
||||||
|
addCdata(text){
|
||||||
|
if (this.options.nameFor.cdata) {
|
||||||
|
this._addChild(this.options.nameFor.cdata, text);
|
||||||
|
} else {
|
||||||
|
this.addRawValue(text || "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addRawValue = text => this.addValue(text);
|
||||||
|
|
||||||
|
addDeclaration(){
|
||||||
|
if(!this.options.declaration){
|
||||||
|
}else{
|
||||||
|
this.addPi("?xml");
|
||||||
|
}
|
||||||
|
this.attributes = {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = BaseOutputBuilder;
|
||||||
103
node_modules/fast-xml-parser/src/v5/OutputBuilders/JsArrBuilder.js
generated
vendored
Normal file
103
node_modules/fast-xml-parser/src/v5/OutputBuilders/JsArrBuilder.js
generated
vendored
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
const {buildOptions,registerCommonValueParsers} = require("./ParserOptionsBuilder");
|
||||||
|
|
||||||
|
class OutputBuilder{
|
||||||
|
constructor(options){
|
||||||
|
this.options = buildOptions(options);
|
||||||
|
this.registeredParsers = registerCommonValueParsers(this.options);
|
||||||
|
}
|
||||||
|
|
||||||
|
registerValueParser(name,parserInstance){//existing name will override the parser without warning
|
||||||
|
this.registeredParsers[name] = parserInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
getInstance(parserOptions){
|
||||||
|
return new JsArrBuilder(parserOptions, this.options, this.registeredParsers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const rootName = '!js_arr';
|
||||||
|
const BaseOutputBuilder = require("./BaseOutputBuilder");
|
||||||
|
|
||||||
|
class JsArrBuilder extends BaseOutputBuilder{
|
||||||
|
|
||||||
|
constructor(parserOptions, options,registeredParsers) {
|
||||||
|
super();
|
||||||
|
this.tagsStack = [];
|
||||||
|
this.parserOptions = parserOptions;
|
||||||
|
this.options = options;
|
||||||
|
this.registeredParsers = registeredParsers;
|
||||||
|
|
||||||
|
this.root = new Node(rootName);
|
||||||
|
this.currentNode = this.root;
|
||||||
|
this.attributes = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
addTag(tag){
|
||||||
|
//when a new tag is added, it should be added as child of current node
|
||||||
|
//TODO: shift this check to the parser
|
||||||
|
if(tag.name === "__proto__") tag.name = "#__proto__";
|
||||||
|
|
||||||
|
this.tagsStack.push(this.currentNode);
|
||||||
|
this.currentNode = new Node(tag.name, this.attributes);
|
||||||
|
this.attributes = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the node should be added by checking user's preference
|
||||||
|
* @param {Node} node
|
||||||
|
* @returns boolean: true if the node should not be added
|
||||||
|
*/
|
||||||
|
closeTag(){
|
||||||
|
const node = this.currentNode;
|
||||||
|
this.currentNode = this.tagsStack.pop(); //set parent node in scope
|
||||||
|
if(this.options.onClose !== undefined){
|
||||||
|
//TODO TagPathMatcher
|
||||||
|
const resultTag = this.options.onClose(node,
|
||||||
|
new TagPathMatcher(this.tagsStack,node));
|
||||||
|
|
||||||
|
if(resultTag) return;
|
||||||
|
}
|
||||||
|
this.currentNode.child.push(node); //to parent node
|
||||||
|
}
|
||||||
|
|
||||||
|
//Called by parent class methods
|
||||||
|
_addChild(key, val){
|
||||||
|
// if(key === "__proto__") tagName = "#__proto__";
|
||||||
|
this.currentNode.child.push( {[key]: val });
|
||||||
|
// this.currentNode.leafType = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add text value child node
|
||||||
|
* @param {string} text
|
||||||
|
*/
|
||||||
|
addValue(text){
|
||||||
|
this.currentNode.child.push( {[this.options.nameFor.text]: this.parseValue(text, this.options.tags.valueParsers) });
|
||||||
|
}
|
||||||
|
|
||||||
|
addPi(name){
|
||||||
|
//TODO: set pi flag
|
||||||
|
if(!this.options.ignorePiTags){
|
||||||
|
const node = new Node(name, this.attributes);
|
||||||
|
this.currentNode[":@"] = this.attributes;
|
||||||
|
this.currentNode.child.push(node);
|
||||||
|
}
|
||||||
|
this.attributes = {};
|
||||||
|
}
|
||||||
|
getOutput(){
|
||||||
|
return this.root.child[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Node{
|
||||||
|
constructor(tagname, attributes){
|
||||||
|
this.tagname = tagname;
|
||||||
|
this.child = []; //nested tags, text, cdata, comments
|
||||||
|
if(attributes && Object.keys(attributes).length > 0)
|
||||||
|
this[":@"] = attributes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = OutputBuilder;
|
||||||
102
node_modules/fast-xml-parser/src/v5/OutputBuilders/JsMinArrBuilder.js
generated
vendored
Normal file
102
node_modules/fast-xml-parser/src/v5/OutputBuilders/JsMinArrBuilder.js
generated
vendored
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
const {buildOptions,registerCommonValueParsers} = require("./ParserOptionsBuilder");
|
||||||
|
|
||||||
|
class OutputBuilder{
|
||||||
|
constructor(options){
|
||||||
|
this.options = buildOptions(options);
|
||||||
|
this.registeredParsers = registerCommonValueParsers(this.options);
|
||||||
|
}
|
||||||
|
|
||||||
|
registerValueParser(name,parserInstance){//existing name will override the parser without warning
|
||||||
|
this.registeredParsers[name] = parserInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
getInstance(parserOptions){
|
||||||
|
return new JsMinArrBuilder(parserOptions, this.options, this.registeredParsers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const BaseOutputBuilder = require("./BaseOutputBuilder");
|
||||||
|
const rootName = '^';
|
||||||
|
|
||||||
|
class JsMinArrBuilder extends BaseOutputBuilder{
|
||||||
|
|
||||||
|
constructor(parserOptions, options,registeredParsers) {
|
||||||
|
super();
|
||||||
|
this.tagsStack = [];
|
||||||
|
this.parserOptions = parserOptions;
|
||||||
|
this.options = options;
|
||||||
|
this.registeredParsers = registeredParsers;
|
||||||
|
|
||||||
|
this.root = {[rootName]: []};
|
||||||
|
this.currentNode = this.root;
|
||||||
|
this.currentNodeTagName = rootName;
|
||||||
|
this.attributes = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
addTag(tag){
|
||||||
|
//when a new tag is added, it should be added as child of current node
|
||||||
|
//TODO: shift this check to the parser
|
||||||
|
if(tag.name === "__proto__") tag.name = "#__proto__";
|
||||||
|
|
||||||
|
this.tagsStack.push([this.currentNodeTagName,this.currentNode]); //this.currentNode is parent node here
|
||||||
|
this.currentNodeTagName = tag.name;
|
||||||
|
this.currentNode = { [tag.name]:[]}
|
||||||
|
if(Object.keys(this.attributes).length > 0){
|
||||||
|
this.currentNode[":@"] = this.attributes;
|
||||||
|
this.attributes = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the node should be added by checking user's preference
|
||||||
|
* @param {Node} node
|
||||||
|
* @returns boolean: true if the node should not be added
|
||||||
|
*/
|
||||||
|
closeTag(){
|
||||||
|
const node = this.currentNode;
|
||||||
|
const nodeName = this.currentNodeTagName;
|
||||||
|
const arr = this.tagsStack.pop(); //set parent node in scope
|
||||||
|
this.currentNodeTagName = arr[0];
|
||||||
|
this.currentNode = arr[1];
|
||||||
|
|
||||||
|
if(this.options.onClose !== undefined){
|
||||||
|
//TODO TagPathMatcher
|
||||||
|
const resultTag = this.options.onClose(node,
|
||||||
|
new TagPathMatcher(this.tagsStack,node));
|
||||||
|
|
||||||
|
if(resultTag) return;
|
||||||
|
}
|
||||||
|
this.currentNode[this.currentNodeTagName].push(node); //to parent node
|
||||||
|
}
|
||||||
|
|
||||||
|
//Called by parent class methods
|
||||||
|
_addChild(key, val){
|
||||||
|
// if(key === "__proto__") tagName = "#__proto__";
|
||||||
|
this.currentNode.push( {[key]: val });
|
||||||
|
// this.currentNode.leafType = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add text value child node
|
||||||
|
* @param {string} text
|
||||||
|
*/
|
||||||
|
addValue(text){
|
||||||
|
this.currentNode[this.currentNodeTagName].push( {[this.options.nameFor.text]: this.parseValue(text, this.options.tags.valueParsers) });
|
||||||
|
}
|
||||||
|
|
||||||
|
addPi(name){
|
||||||
|
if(!this.options.ignorePiTags){
|
||||||
|
const node = { [name]:[]}
|
||||||
|
if(this.attributes){
|
||||||
|
node[":@"] = this.attributes;
|
||||||
|
}
|
||||||
|
this.currentNode.push(node);
|
||||||
|
}
|
||||||
|
this.attributes = {};
|
||||||
|
}
|
||||||
|
getOutput(){
|
||||||
|
return this.root[rootName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = OutputBuilder;
|
||||||
156
node_modules/fast-xml-parser/src/v5/OutputBuilders/JsObjBuilder.js
generated
vendored
Normal file
156
node_modules/fast-xml-parser/src/v5/OutputBuilders/JsObjBuilder.js
generated
vendored
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
|
||||||
|
|
||||||
|
const {buildOptions,registerCommonValueParsers} = require("./ParserOptionsBuilder");
|
||||||
|
|
||||||
|
class OutputBuilder{
|
||||||
|
constructor(builderOptions){
|
||||||
|
this.options = buildOptions(builderOptions);
|
||||||
|
this.registeredParsers = registerCommonValueParsers(this.options);
|
||||||
|
}
|
||||||
|
|
||||||
|
registerValueParser(name,parserInstance){//existing name will override the parser without warning
|
||||||
|
this.registeredParsers[name] = parserInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
getInstance(parserOptions){
|
||||||
|
return new JsObjBuilder(parserOptions, this.options, this.registeredParsers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const BaseOutputBuilder = require("./BaseOutputBuilder");
|
||||||
|
const rootName = '^';
|
||||||
|
|
||||||
|
class JsObjBuilder extends BaseOutputBuilder{
|
||||||
|
|
||||||
|
constructor(parserOptions, builderOptions,registeredParsers) {
|
||||||
|
super();
|
||||||
|
//hold the raw detail of a tag and sequence with reference to the output
|
||||||
|
this.tagsStack = [];
|
||||||
|
this.parserOptions = parserOptions;
|
||||||
|
this.options = builderOptions;
|
||||||
|
this.registeredParsers = registeredParsers;
|
||||||
|
|
||||||
|
this.root = {};
|
||||||
|
this.parent = this.root;
|
||||||
|
this.tagName = rootName;
|
||||||
|
this.value = {};
|
||||||
|
this.textValue = "";
|
||||||
|
this.attributes = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
addTag(tag){
|
||||||
|
|
||||||
|
let value = "";
|
||||||
|
if( !isEmpty(this.attributes)){
|
||||||
|
value = {};
|
||||||
|
if(this.options.attributes.groupBy){
|
||||||
|
value[this.options.attributes.groupBy] = this.attributes;
|
||||||
|
}else{
|
||||||
|
value = this.attributes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.tagsStack.push([this.tagName, this.textValue, this.value]); //parent tag, parent text value, parent tag value (jsobj)
|
||||||
|
this.tagName = tag.name;
|
||||||
|
this.value = value;
|
||||||
|
this.textValue = "";
|
||||||
|
this.attributes = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the node should be added by checking user's preference
|
||||||
|
* @param {Node} node
|
||||||
|
* @returns boolean: true if the node should not be added
|
||||||
|
*/
|
||||||
|
closeTag(){
|
||||||
|
const tagName = this.tagName;
|
||||||
|
let value = this.value;
|
||||||
|
let textValue = this.textValue;
|
||||||
|
|
||||||
|
//update tag text value
|
||||||
|
if(typeof value !== "object" && !Array.isArray(value)){
|
||||||
|
value = this.parseValue(textValue.trim(), this.options.tags.valueParsers);
|
||||||
|
}else if(textValue.length > 0){
|
||||||
|
value[this.options.nameFor.text] = this.parseValue(textValue.trim(), this.options.tags.valueParsers);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let resultTag= {
|
||||||
|
tagName: tagName,
|
||||||
|
value: value
|
||||||
|
};
|
||||||
|
|
||||||
|
if(this.options.onTagClose !== undefined){
|
||||||
|
//TODO TagPathMatcher
|
||||||
|
resultTag = this.options.onClose(tagName, value, this.textValue, new TagPathMatcher(this.tagsStack,node));
|
||||||
|
|
||||||
|
if(!resultTag) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//set parent node in scope
|
||||||
|
let arr = this.tagsStack.pop();
|
||||||
|
let parentTag = arr[2];
|
||||||
|
parentTag=this._addChildTo(resultTag.tagName, resultTag.value, parentTag);
|
||||||
|
|
||||||
|
this.tagName = arr[0];
|
||||||
|
this.textValue = arr[1];
|
||||||
|
this.value = parentTag;
|
||||||
|
}
|
||||||
|
|
||||||
|
_addChild(key, val){
|
||||||
|
if(typeof this.value === "string"){
|
||||||
|
this.value = { [this.options.nameFor.text] : this.value };
|
||||||
|
}
|
||||||
|
|
||||||
|
this._addChildTo(key, val, this.value);
|
||||||
|
// this.currentNode.leafType = false;
|
||||||
|
this.attributes = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
_addChildTo(key, val, node){
|
||||||
|
if(typeof node === 'string') node = {};
|
||||||
|
if(!node[key]){
|
||||||
|
node[key] = val;
|
||||||
|
}else{ //Repeated
|
||||||
|
if(!Array.isArray(node[key])){ //but not stored as array
|
||||||
|
node[key] = [node[key]];
|
||||||
|
}
|
||||||
|
node[key].push(val);
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add text value child node
|
||||||
|
* @param {string} text
|
||||||
|
*/
|
||||||
|
addValue(text){
|
||||||
|
//TODO: use bytes join
|
||||||
|
if(this.textValue.length > 0) this.textValue += " " + text;
|
||||||
|
else this.textValue = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
addPi(name){
|
||||||
|
let value = "";
|
||||||
|
if( !isEmpty(this.attributes)){
|
||||||
|
value = {};
|
||||||
|
if(this.options.attributes.groupBy){
|
||||||
|
value[this.options.attributes.groupBy] = this.attributes;
|
||||||
|
}else{
|
||||||
|
value = this.attributes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._addChild(name, value);
|
||||||
|
|
||||||
|
}
|
||||||
|
getOutput(){
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isEmpty(obj) {
|
||||||
|
return Object.keys(obj).length === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = OutputBuilder;
|
||||||
99
node_modules/fast-xml-parser/src/v5/OutputBuilders/ParserOptionsBuilder.js
generated
vendored
Normal file
99
node_modules/fast-xml-parser/src/v5/OutputBuilders/ParserOptionsBuilder.js
generated
vendored
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
const trimParser = require("../valueParsers/trim")
|
||||||
|
const booleanParser = require("../valueParsers/booleanParser")
|
||||||
|
const currencyParser = require("../valueParsers/currency")
|
||||||
|
const numberParser = require("../valueParsers/number")
|
||||||
|
|
||||||
|
const defaultOptions={
|
||||||
|
nameFor:{
|
||||||
|
text: "#text",
|
||||||
|
comment: "",
|
||||||
|
cdata: "",
|
||||||
|
},
|
||||||
|
// onTagClose: () => {},
|
||||||
|
// onAttribute: () => {},
|
||||||
|
piTag: false,
|
||||||
|
declaration: false, //"?xml"
|
||||||
|
tags: {
|
||||||
|
valueParsers: [
|
||||||
|
// "trim",
|
||||||
|
// "boolean",
|
||||||
|
// "number",
|
||||||
|
// "currency",
|
||||||
|
// "date",
|
||||||
|
]
|
||||||
|
},
|
||||||
|
attributes:{
|
||||||
|
prefix: "@_",
|
||||||
|
suffix: "",
|
||||||
|
groupBy: "",
|
||||||
|
|
||||||
|
valueParsers: [
|
||||||
|
// "trim",
|
||||||
|
// "boolean",
|
||||||
|
// "number",
|
||||||
|
// "currency",
|
||||||
|
// "date",
|
||||||
|
]
|
||||||
|
},
|
||||||
|
dataType:{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO
|
||||||
|
const withJoin = ["trim","join", /*"entities",*/"number","boolean","currency"/*, "date"*/]
|
||||||
|
const withoutJoin = ["trim", /*"entities",*/"number","boolean","currency"/*, "date"*/]
|
||||||
|
|
||||||
|
function buildOptions(options){
|
||||||
|
//clone
|
||||||
|
const finalOptions = { ... defaultOptions};
|
||||||
|
|
||||||
|
//add config missed in cloning
|
||||||
|
finalOptions.tags.valueParsers.push(...withJoin)
|
||||||
|
if(!this.preserveOrder)
|
||||||
|
finalOptions.tags.valueParsers.push(...withoutJoin);
|
||||||
|
|
||||||
|
//add config missed in cloning
|
||||||
|
finalOptions.attributes.valueParsers.push(...withJoin)
|
||||||
|
|
||||||
|
//override configuration
|
||||||
|
copyProperties(finalOptions,options);
|
||||||
|
return finalOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyProperties(target, source) {
|
||||||
|
for (let key in source) {
|
||||||
|
if (source.hasOwnProperty(key)) {
|
||||||
|
if (typeof source[key] === 'object' && !Array.isArray(source[key])) {
|
||||||
|
// Recursively copy nested properties
|
||||||
|
if (typeof target[key] === 'undefined') {
|
||||||
|
target[key] = {};
|
||||||
|
}
|
||||||
|
copyProperties(target[key], source[key]);
|
||||||
|
} else {
|
||||||
|
// Copy non-nested properties
|
||||||
|
target[key] = source[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function registerCommonValueParsers(options){
|
||||||
|
return {
|
||||||
|
"trim": new trimParser(),
|
||||||
|
// "join": this.entityParser.parse,
|
||||||
|
"boolean": new booleanParser(),
|
||||||
|
"number": new numberParser({
|
||||||
|
hex: true,
|
||||||
|
leadingZeros: true,
|
||||||
|
eNotation: true
|
||||||
|
}),
|
||||||
|
"currency": new currencyParser(),
|
||||||
|
// "date": this.entityParser.parse,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
buildOptions : buildOptions,
|
||||||
|
registerCommonValueParsers: registerCommonValueParsers
|
||||||
|
}
|
||||||
0
node_modules/fast-xml-parser/src/v5/Report.js
generated
vendored
Normal file
0
node_modules/fast-xml-parser/src/v5/Report.js
generated
vendored
Normal file
81
node_modules/fast-xml-parser/src/v5/TagPath.js
generated
vendored
Normal file
81
node_modules/fast-xml-parser/src/v5/TagPath.js
generated
vendored
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
class TagPath{
|
||||||
|
constructor(pathStr){
|
||||||
|
let text = "";
|
||||||
|
let tName = "";
|
||||||
|
let pos;
|
||||||
|
let aName = "";
|
||||||
|
let aVal = "";
|
||||||
|
this.stack = []
|
||||||
|
|
||||||
|
for (let i = 0; i < pathStr.length; i++) {
|
||||||
|
let ch = pathStr[i];
|
||||||
|
if(ch === " ") {
|
||||||
|
if(text.length === 0) continue;
|
||||||
|
tName = text; text = "";
|
||||||
|
}else if(ch === "["){
|
||||||
|
if(tName.length === 0){
|
||||||
|
tName = text; text = "";
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
for (; i < pathStr.length; i++) {
|
||||||
|
ch = pathStr[i];
|
||||||
|
if(ch=== "=") continue;
|
||||||
|
else if(ch=== "]") {aName = text.trim(); text=""; break; i--;}
|
||||||
|
else if(ch === "'" || ch === '"'){
|
||||||
|
let attrEnd = pathStr.indexOf(ch,i+1);
|
||||||
|
aVal = pathStr.substring(i+1, attrEnd);
|
||||||
|
i = attrEnd;
|
||||||
|
}else{
|
||||||
|
text +=ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else if(ch !== " " && text.length === 0 && tName.length > 0){//reading tagName
|
||||||
|
//save previous tag
|
||||||
|
this.stack.push(new TagPathNode(tName,pos,aName,aVal));
|
||||||
|
text = ch; tName = ""; aName = ""; aVal = "";
|
||||||
|
}else{
|
||||||
|
text+=ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//last tag in the path
|
||||||
|
if(tName.length >0 || text.length>0){
|
||||||
|
this.stack.push(new TagPathNode(text||tName,pos,aName,aVal));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match(tagStack,node){
|
||||||
|
if(this.stack[0].name !== "*"){
|
||||||
|
if(this.stack.length !== tagStack.length +1) return false;
|
||||||
|
|
||||||
|
//loop through tagPath and tagStack and match
|
||||||
|
for (let i = 0; i < this.tagStack.length; i++) {
|
||||||
|
if(!this.stack[i].match(tagStack[i])) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!this.stack[this.stack.length - 1].match(node)) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TagPathNode{
|
||||||
|
constructor(name,position,attrName,attrVal){
|
||||||
|
this.name = name;
|
||||||
|
this.position = position;
|
||||||
|
this.attrName = attrName,
|
||||||
|
this.attrVal = attrVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
match(node){
|
||||||
|
let matching = true;
|
||||||
|
matching = node.name === this.name;
|
||||||
|
if(this.position) matching = node.position === this.position;
|
||||||
|
if(this.attrName) matching = node.attrs[this.attrName !== undefined];
|
||||||
|
if(this.attrVal) matching = node.attrs[this.attrName !== this.attrVal];
|
||||||
|
return matching;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log((new TagPath("* b[b]")).stack);
|
||||||
|
// console.log((new TagPath("a[a] b[b] c")).stack);
|
||||||
|
// console.log((new TagPath(" b [ b= 'cf sdadwa' ] a ")).stack);
|
||||||
15
node_modules/fast-xml-parser/src/v5/TagPathMatcher.js
generated
vendored
Normal file
15
node_modules/fast-xml-parser/src/v5/TagPathMatcher.js
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
const TagPath = require("./TagPath");
|
||||||
|
|
||||||
|
class TagPathMatcher{
|
||||||
|
constructor(stack,node){
|
||||||
|
this.stack = stack;
|
||||||
|
this.node= node;
|
||||||
|
}
|
||||||
|
|
||||||
|
match(path){
|
||||||
|
const tagPath = new TagPath(path);
|
||||||
|
return tagPath.match(this.stack, this.node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = TagPathMatcher;
|
||||||
85
node_modules/fast-xml-parser/src/v5/XMLParser.js
generated
vendored
Executable file
85
node_modules/fast-xml-parser/src/v5/XMLParser.js
generated
vendored
Executable file
@ -0,0 +1,85 @@
|
|||||||
|
const { buildOptions} = require("./OptionsBuilder");
|
||||||
|
const Xml2JsParser = require("./Xml2JsParser");
|
||||||
|
|
||||||
|
class XMLParser{
|
||||||
|
|
||||||
|
constructor(options){
|
||||||
|
this.externalEntities = {};
|
||||||
|
this.options = buildOptions(options);
|
||||||
|
// console.log(this.options)
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse XML data string to JS object
|
||||||
|
* @param {string|Buffer} xmlData
|
||||||
|
* @param {boolean|Object} validationOption
|
||||||
|
*/
|
||||||
|
parse(xmlData){
|
||||||
|
if(Array.isArray(xmlData) && xmlData.byteLength !== undefined){
|
||||||
|
return this.parse(xmlData);
|
||||||
|
}else if( xmlData.toString){
|
||||||
|
xmlData = xmlData.toString();
|
||||||
|
}else{
|
||||||
|
throw new Error("XML data is accepted in String or Bytes[] form.")
|
||||||
|
}
|
||||||
|
// if( validationOption){
|
||||||
|
// if(validationOption === true) validationOption = {}; //validate with default options
|
||||||
|
|
||||||
|
// const result = validator.validate(xmlData, validationOption);
|
||||||
|
// if (result !== true) {
|
||||||
|
// throw Error( `${result.err.msg}:${result.err.line}:${result.err.col}` )
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
const parser = new Xml2JsParser(this.options);
|
||||||
|
parser.entityParser.addExternalEntities(this.externalEntities);
|
||||||
|
return parser.parse(xmlData);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse XML data buffer to JS object
|
||||||
|
* @param {string|Buffer} xmlData
|
||||||
|
* @param {boolean|Object} validationOption
|
||||||
|
*/
|
||||||
|
parseBytesArr(xmlData){
|
||||||
|
if(Array.isArray(xmlData) && xmlData.byteLength !== undefined){
|
||||||
|
}else{
|
||||||
|
throw new Error("XML data is accepted in Bytes[] form.")
|
||||||
|
}
|
||||||
|
const parser = new Xml2JsParser(this.options);
|
||||||
|
parser.entityParser.addExternalEntities(this.externalEntities);
|
||||||
|
return parser.parseBytesArr(xmlData);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse XML data stream to JS object
|
||||||
|
* @param {fs.ReadableStream} xmlDataStream
|
||||||
|
*/
|
||||||
|
parseStream(xmlDataStream){
|
||||||
|
if(!isStream(xmlDataStream)) throw new Error("FXP: Invalid stream input");
|
||||||
|
|
||||||
|
const orderedObjParser = new Xml2JsParser(this.options);
|
||||||
|
orderedObjParser.entityParser.addExternalEntities(this.externalEntities);
|
||||||
|
return orderedObjParser.parseStream(xmlDataStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add Entity which is not by default supported by this library
|
||||||
|
* @param {string} key
|
||||||
|
* @param {string} value
|
||||||
|
*/
|
||||||
|
addEntity(key, value){
|
||||||
|
if(value.indexOf("&") !== -1){
|
||||||
|
throw new Error("Entity value can't have '&'")
|
||||||
|
}else if(key.indexOf("&") !== -1 || key.indexOf(";") !== -1){
|
||||||
|
throw new Error("An entity must be set without '&' and ';'. Eg. use '#xD' for '
'")
|
||||||
|
}else if(value === "&"){
|
||||||
|
throw new Error("An entity with value '&' is not permitted");
|
||||||
|
}else{
|
||||||
|
this.externalEntities[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isStream(stream){
|
||||||
|
if(stream && typeof stream.read === "function" && typeof stream.on === "function" && typeof stream.readableEnded === "boolean") return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = XMLParser;
|
||||||
237
node_modules/fast-xml-parser/src/v5/Xml2JsParser.js
generated
vendored
Normal file
237
node_modules/fast-xml-parser/src/v5/Xml2JsParser.js
generated
vendored
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
const StringSource = require("./inputSource/StringSource");
|
||||||
|
const BufferSource = require("./inputSource/BufferSource");
|
||||||
|
const {readTagExp,readClosingTagName} = require("./XmlPartReader");
|
||||||
|
const {readComment, readCdata,readDocType,readPiTag} = require("./XmlSpecialTagsReader");
|
||||||
|
const TagPath = require("./TagPath");
|
||||||
|
const TagPathMatcher = require("./TagPathMatcher");
|
||||||
|
const EntitiesParser = require('./EntitiesParser');
|
||||||
|
|
||||||
|
//To hold the data of current tag
|
||||||
|
//This is usually used to compare jpath expression against current tag
|
||||||
|
class TagDetail{
|
||||||
|
constructor(name){
|
||||||
|
this.name = name;
|
||||||
|
this.position = 0;
|
||||||
|
// this.attributes = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Xml2JsParser {
|
||||||
|
constructor(options) {
|
||||||
|
this.options = options;
|
||||||
|
|
||||||
|
this.currentTagDetail = null;
|
||||||
|
this.tagTextData = "";
|
||||||
|
this.tagsStack = [];
|
||||||
|
this.entityParser = new EntitiesParser(options.htmlEntities);
|
||||||
|
this.stopNodes = [];
|
||||||
|
for (let i = 0; i < this.options.stopNodes.length; i++) {
|
||||||
|
this.stopNodes.push(new TagPath(this.options.stopNodes[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parse(strData) {
|
||||||
|
this.source = new StringSource(strData);
|
||||||
|
this.parseXml();
|
||||||
|
return this.outputBuilder.getOutput();
|
||||||
|
}
|
||||||
|
parseBytesArr(data) {
|
||||||
|
this.source = new BufferSource(data );
|
||||||
|
this.parseXml();
|
||||||
|
return this.outputBuilder.getOutput();
|
||||||
|
}
|
||||||
|
|
||||||
|
parseXml() {
|
||||||
|
//TODO: Separate TagValueParser as separate class. So no scope issue in node builder class
|
||||||
|
|
||||||
|
//OutputBuilder should be set in XML Parser
|
||||||
|
this.outputBuilder = this.options.OutputBuilder.getInstance(this.options);
|
||||||
|
this.root = { root: true};
|
||||||
|
this.currentTagDetail = this.root;
|
||||||
|
|
||||||
|
while(this.source.canRead()){
|
||||||
|
let ch = this.source.readCh();
|
||||||
|
if (ch === "") break;
|
||||||
|
|
||||||
|
if(ch === "<"){//tagStart
|
||||||
|
let nextChar = this.source.readChAt(0);
|
||||||
|
if (nextChar === "" ) throw new Error("Unexpected end of source");
|
||||||
|
|
||||||
|
|
||||||
|
if(nextChar === "!" || nextChar === "?"){
|
||||||
|
this.source.updateBufferBoundary();
|
||||||
|
//previously collected text should be added to current node
|
||||||
|
this.addTextNode();
|
||||||
|
|
||||||
|
this.readSpecialTag(nextChar);// Read DOCTYPE, comment, CDATA, PI tag
|
||||||
|
}else if(nextChar === "/"){
|
||||||
|
this.source.updateBufferBoundary();
|
||||||
|
this.readClosingTag();
|
||||||
|
// console.log(this.source.buffer.length, this.source.readable);
|
||||||
|
// console.log(this.tagsStack.length);
|
||||||
|
}else{//opening tag
|
||||||
|
this.readOpeningTag();
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
this.tagTextData += ch;
|
||||||
|
}
|
||||||
|
}//End While loop
|
||||||
|
if(this.tagsStack.length > 0 || ( this.tagTextData !== "undefined" && this.tagTextData.trimEnd().length > 0) ) throw new Error("Unexpected data in the end of document");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* read closing paired tag. Set parent tag in scope.
|
||||||
|
* skip a node on user's choice
|
||||||
|
*/
|
||||||
|
readClosingTag(){
|
||||||
|
const tagName = this.processTagName(readClosingTagName(this.source));
|
||||||
|
// console.log(tagName, this.tagsStack.length);
|
||||||
|
this.validateClosingTag(tagName);
|
||||||
|
// All the text data collected, belongs to current tag.
|
||||||
|
if(!this.currentTagDetail.root) this.addTextNode();
|
||||||
|
this.outputBuilder.closeTag();
|
||||||
|
// Since the tag is closed now, parent tag comes in scope
|
||||||
|
this.currentTagDetail = this.tagsStack.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
validateClosingTag(tagName){
|
||||||
|
// This can't be unpaired tag, or a stop tag.
|
||||||
|
if(this.isUnpaired(tagName) || this.isStopNode(tagName)) throw new Error(`Unexpected closing tag '${tagName}'`);
|
||||||
|
// This must match with last opening tag
|
||||||
|
else if(tagName !== this.currentTagDetail.name)
|
||||||
|
throw new Error(`Unexpected closing tag '${tagName}' expecting '${this.currentTagDetail.name}'`)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read paired, unpaired, self-closing, stop and special tags.
|
||||||
|
* Create a new node
|
||||||
|
* Push paired tag in stack.
|
||||||
|
*/
|
||||||
|
readOpeningTag(){
|
||||||
|
//save previously collected text data to current node
|
||||||
|
this.addTextNode();
|
||||||
|
|
||||||
|
//create new tag
|
||||||
|
let tagExp = readTagExp(this, ">" );
|
||||||
|
|
||||||
|
// process and skip from tagsStack For unpaired tag, self closing tag, and stop node
|
||||||
|
const tagDetail = new TagDetail(tagExp.tagName);
|
||||||
|
if(this.isUnpaired(tagExp.tagName)) {
|
||||||
|
//TODO: this will lead 2 extra stack operation
|
||||||
|
this.outputBuilder.addTag(tagDetail);
|
||||||
|
this.outputBuilder.closeTag();
|
||||||
|
} else if(tagExp.selfClosing){
|
||||||
|
this.outputBuilder.addTag(tagDetail);
|
||||||
|
this.outputBuilder.closeTag();
|
||||||
|
} else if(this.isStopNode(this.currentTagDetail)){
|
||||||
|
// TODO: let's user set a stop node boundary detector for complex contents like script tag
|
||||||
|
//TODO: pass tag name only to avoid string operations
|
||||||
|
const content = source.readUptoCloseTag(`</${tagExp.tagName}`);
|
||||||
|
this.outputBuilder.addTag(tagDetail);
|
||||||
|
this.outputBuilder.addValue(content);
|
||||||
|
this.outputBuilder.closeTag();
|
||||||
|
}else{//paired tag
|
||||||
|
//set new nested tag in scope.
|
||||||
|
this.tagsStack.push(this.currentTagDetail);
|
||||||
|
this.outputBuilder.addTag(tagDetail);
|
||||||
|
this.currentTagDetail = tagDetail;
|
||||||
|
}
|
||||||
|
// console.log(tagExp.tagName,this.tagsStack.length);
|
||||||
|
// this.options.onClose()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
readSpecialTag(startCh){
|
||||||
|
if(startCh == "!"){
|
||||||
|
let nextChar = this.source.readCh();
|
||||||
|
if (nextChar === null || nextChar === undefined) throw new Error("Unexpected ending of the source");
|
||||||
|
|
||||||
|
if(nextChar === "-"){//comment
|
||||||
|
readComment(this);
|
||||||
|
}else if(nextChar === "["){//CDATA
|
||||||
|
readCdata(this);
|
||||||
|
}else if(nextChar === "D"){//DOCTYPE
|
||||||
|
readDocType(this);
|
||||||
|
}
|
||||||
|
}else if(startCh === "?"){
|
||||||
|
readPiTag(this);
|
||||||
|
}else{
|
||||||
|
throw new Error(`Invalid tag '<${startCh}' at ${this.source.line}:${this.source.col}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addTextNode = function() {
|
||||||
|
// if(this.currentTagDetail){
|
||||||
|
//save text as child node
|
||||||
|
// if(this.currentTagDetail.tagname !== '!xml')
|
||||||
|
if (this.tagTextData !== undefined && this.tagTextData !== "") { //store previously collected data as textNode
|
||||||
|
if(this.tagTextData.trim().length > 0){
|
||||||
|
//TODO: shift parsing to output builder
|
||||||
|
|
||||||
|
this.outputBuilder.addValue(this.replaceEntities(this.tagTextData));
|
||||||
|
}
|
||||||
|
this.tagTextData = "";
|
||||||
|
}
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
processAttrName(name){
|
||||||
|
if(name === "__proto__") name = "#__proto__";
|
||||||
|
name = resolveNameSpace(name, this.removeNSPrefix);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
processTagName(name){
|
||||||
|
if(name === "__proto__") name = "#__proto__";
|
||||||
|
name = resolveNameSpace(name, this.removeNSPrefix);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate tags path from tagsStack
|
||||||
|
*/
|
||||||
|
tagsPath(tagName){
|
||||||
|
//TODO: return TagPath Object. User can call match method with path
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
isUnpaired(tagName){
|
||||||
|
return this.options.tags.unpaired.indexOf(tagName) !== -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* valid expressions are
|
||||||
|
* tag nested
|
||||||
|
* * nested
|
||||||
|
* tag nested[attribute]
|
||||||
|
* tag nested[attribute=""]
|
||||||
|
* tag nested[attribute!=""]
|
||||||
|
* tag nested:0 //for future
|
||||||
|
* @param {string} tagName
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
isStopNode(node){
|
||||||
|
for (let i = 0; i < this.stopNodes.length; i++) {
|
||||||
|
const givenPath = this.stopNodes[i];
|
||||||
|
if(givenPath.match(this.tagsStack, node)) return true;
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
replaceEntities(text){
|
||||||
|
//TODO: if option is set then replace entities
|
||||||
|
return this.entityParser.parse(text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveNameSpace(name, removeNSPrefix) {
|
||||||
|
if (removeNSPrefix) {
|
||||||
|
const parts = name.split(':');
|
||||||
|
if(parts.length === 2){
|
||||||
|
if (parts[0] === 'xmlns') return '';
|
||||||
|
else return parts[1];
|
||||||
|
}else reportError(`Multiple namespaces ${name}`)
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Xml2JsParser;
|
||||||
216
node_modules/fast-xml-parser/src/v5/XmlPartReader.js
generated
vendored
Normal file
216
node_modules/fast-xml-parser/src/v5/XmlPartReader.js
generated
vendored
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find paired tag for a stop node
|
||||||
|
* @param {string} xmlDoc
|
||||||
|
* @param {string} tagName
|
||||||
|
* @param {number} i : start index
|
||||||
|
*/
|
||||||
|
function readStopNode(xmlDoc, tagName, i){
|
||||||
|
const startIndex = i;
|
||||||
|
// Starting at 1 since we already have an open tag
|
||||||
|
let openTagCount = 1;
|
||||||
|
|
||||||
|
for (; i < xmlDoc.length; i++) {
|
||||||
|
if( xmlDoc[i] === "<"){
|
||||||
|
if (xmlDoc[i+1] === "/") {//close tag
|
||||||
|
const closeIndex = findSubStrIndex(xmlDoc, ">", i, `${tagName} is not closed`);
|
||||||
|
let closeTagName = xmlDoc.substring(i+2,closeIndex).trim();
|
||||||
|
if(closeTagName === tagName){
|
||||||
|
openTagCount--;
|
||||||
|
if (openTagCount === 0) {
|
||||||
|
return {
|
||||||
|
tagContent: xmlDoc.substring(startIndex, i),
|
||||||
|
i : closeIndex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i=closeIndex;
|
||||||
|
} else if(xmlDoc[i+1] === '?') {
|
||||||
|
const closeIndex = findSubStrIndex(xmlDoc, "?>", i+1, "StopNode is not closed.")
|
||||||
|
i=closeIndex;
|
||||||
|
} else if(xmlDoc.substr(i + 1, 3) === '!--') {
|
||||||
|
const closeIndex = findSubStrIndex(xmlDoc, "-->", i+3, "StopNode is not closed.")
|
||||||
|
i=closeIndex;
|
||||||
|
} else if(xmlDoc.substr(i + 1, 2) === '![') {
|
||||||
|
const closeIndex = findSubStrIndex(xmlDoc, "]]>", i, "StopNode is not closed.") - 2;
|
||||||
|
i=closeIndex;
|
||||||
|
} else {
|
||||||
|
const tagData = readTagExp(xmlDoc, i, '>')
|
||||||
|
|
||||||
|
if (tagData) {
|
||||||
|
const openTagName = tagData && tagData.tagName;
|
||||||
|
if (openTagName === tagName && tagData.tagExp[tagData.tagExp.length-1] !== "/") {
|
||||||
|
openTagCount++;
|
||||||
|
}
|
||||||
|
i=tagData.closeIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}//end for loop
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read closing tag name
|
||||||
|
* @param {Source} source
|
||||||
|
* @returns tag name
|
||||||
|
*/
|
||||||
|
function readClosingTagName(source){
|
||||||
|
let text = ""; //temporary data
|
||||||
|
while(source.canRead()){
|
||||||
|
let ch = source.readCh();
|
||||||
|
// if (ch === null || ch === undefined) break;
|
||||||
|
// source.updateBuffer();
|
||||||
|
|
||||||
|
if (ch === ">") return text.trimEnd();
|
||||||
|
else text += ch;
|
||||||
|
}
|
||||||
|
throw new Error(`Unexpected end of source. Reading '${substr}'`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read XML tag and build attributes map
|
||||||
|
* This function can be used to read normal tag, pi tag.
|
||||||
|
* This function can't be used to read comment, CDATA, DOCTYPE.
|
||||||
|
* Eg <tag attr = ' some"' attr= ">" bool>
|
||||||
|
* @param {string} xmlDoc
|
||||||
|
* @param {number} startIndex starting index
|
||||||
|
* @returns tag expression includes tag name & attribute string
|
||||||
|
*/
|
||||||
|
function readTagExp(parser) {
|
||||||
|
let inSingleQuotes = false;
|
||||||
|
let inDoubleQuotes = false;
|
||||||
|
let i;
|
||||||
|
let EOE = false;
|
||||||
|
|
||||||
|
for (i = 0; parser.source.canRead(i); i++) {
|
||||||
|
const char = parser.source.readChAt(i);
|
||||||
|
|
||||||
|
if (char === "'" && !inDoubleQuotes) {
|
||||||
|
inSingleQuotes = !inSingleQuotes;
|
||||||
|
} else if (char === '"' && !inSingleQuotes) {
|
||||||
|
inDoubleQuotes = !inDoubleQuotes;
|
||||||
|
} else if (char === '>' && !inSingleQuotes && !inDoubleQuotes) {
|
||||||
|
// If not inside quotes, stop reading at '>'
|
||||||
|
EOE = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if(inSingleQuotes || inDoubleQuotes){
|
||||||
|
throw new Error("Invalid attribute expression. Quote is not properly closed");
|
||||||
|
}else if(!EOE) throw new Error("Unexpected closing of source. Waiting for '>'");
|
||||||
|
|
||||||
|
|
||||||
|
const exp = parser.source.readStr(i);
|
||||||
|
parser.source.updateBufferBoundary(i + 1);
|
||||||
|
return buildTagExpObj(exp, parser)
|
||||||
|
}
|
||||||
|
|
||||||
|
function readPiExp(parser) {
|
||||||
|
let inSingleQuotes = false;
|
||||||
|
let inDoubleQuotes = false;
|
||||||
|
let i;
|
||||||
|
let EOE = false;
|
||||||
|
|
||||||
|
for (i = 0; parser.source.canRead(i) ; i++) {
|
||||||
|
const currentChar = parser.source.readChAt(i);
|
||||||
|
const nextChar = parser.source.readChAt(i+1);
|
||||||
|
|
||||||
|
if (currentChar === "'" && !inDoubleQuotes) {
|
||||||
|
inSingleQuotes = !inSingleQuotes;
|
||||||
|
} else if (currentChar === '"' && !inSingleQuotes) {
|
||||||
|
inDoubleQuotes = !inDoubleQuotes;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!inSingleQuotes && !inDoubleQuotes) {
|
||||||
|
if (currentChar === '?' && nextChar === '>') {
|
||||||
|
EOE = true;
|
||||||
|
break; // Exit the loop when '?>' is found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(inSingleQuotes || inDoubleQuotes){
|
||||||
|
throw new Error("Invalid attribute expression. Quote is not properly closed in PI tag expression");
|
||||||
|
}else if(!EOE) throw new Error("Unexpected closing of source. Waiting for '?>'");
|
||||||
|
|
||||||
|
if(!parser.options.attributes.ignore){
|
||||||
|
//TODO: use regex to verify attributes if not set to ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
const exp = parser.source.readStr(i);
|
||||||
|
parser.source.updateBufferBoundary(i + 1);
|
||||||
|
return buildTagExpObj(exp, parser)
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildTagExpObj(exp, parser){
|
||||||
|
const tagExp = {
|
||||||
|
tagName: "",
|
||||||
|
selfClosing: false
|
||||||
|
};
|
||||||
|
let attrsExp = "";
|
||||||
|
|
||||||
|
// Check for self-closing tag before setting the name
|
||||||
|
if(exp[exp.length -1] === "/") {
|
||||||
|
tagExp.selfClosing = true;
|
||||||
|
exp = exp.slice(0, -1); // Remove the trailing slash
|
||||||
|
}
|
||||||
|
|
||||||
|
//separate tag name
|
||||||
|
let i = 0;
|
||||||
|
for (; i < exp.length; i++) {
|
||||||
|
const char = exp[i];
|
||||||
|
if(char === " "){
|
||||||
|
tagExp.tagName = exp.substring(0, i);
|
||||||
|
attrsExp = exp.substring(i + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//only tag
|
||||||
|
if(tagExp.tagName.length === 0 && i === exp.length)tagExp.tagName = exp;
|
||||||
|
|
||||||
|
tagExp.tagName = tagExp.tagName.trimEnd();
|
||||||
|
|
||||||
|
if(!parser.options.attributes.ignore && attrsExp.length > 0){
|
||||||
|
parseAttributesExp(attrsExp,parser)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tagExp;
|
||||||
|
}
|
||||||
|
|
||||||
|
const attrsRegx = new RegExp('([^\\s=]+)\\s*(=\\s*([\'"])([\\s\\S]*?)\\3)?', 'gm');
|
||||||
|
|
||||||
|
function parseAttributesExp(attrStr, parser) {
|
||||||
|
const matches = getAllMatches(attrStr, attrsRegx);
|
||||||
|
const len = matches.length; //don't make it inline
|
||||||
|
for (let i = 0; i < len; i++) {
|
||||||
|
let attrName = parser.processAttrName(matches[i][1]);
|
||||||
|
let attrVal = parser.replaceEntities(matches[i][4] || true);
|
||||||
|
|
||||||
|
parser.outputBuilder.addAttribute(attrName, attrVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const getAllMatches = function(string, regex) {
|
||||||
|
const matches = [];
|
||||||
|
let match = regex.exec(string);
|
||||||
|
while (match) {
|
||||||
|
const allmatches = [];
|
||||||
|
allmatches.startIndex = regex.lastIndex - match[0].length;
|
||||||
|
const len = match.length;
|
||||||
|
for (let index = 0; index < len; index++) {
|
||||||
|
allmatches.push(match[index]);
|
||||||
|
}
|
||||||
|
matches.push(allmatches);
|
||||||
|
match = regex.exec(string);
|
||||||
|
}
|
||||||
|
return matches;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
readStopNode: readStopNode,
|
||||||
|
readClosingTagName: readClosingTagName,
|
||||||
|
readTagExp: readTagExp,
|
||||||
|
readPiExp: readPiExp,
|
||||||
|
}
|
||||||
118
node_modules/fast-xml-parser/src/v5/XmlSpecialTagsReader.js
generated
vendored
Normal file
118
node_modules/fast-xml-parser/src/v5/XmlSpecialTagsReader.js
generated
vendored
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
const {readPiExp} = require("./XmlPartReader");
|
||||||
|
|
||||||
|
function readCdata(parser){
|
||||||
|
//<![ are already read till this point
|
||||||
|
let str = parser.source.readStr(6); //CDATA[
|
||||||
|
parser.source.updateBufferBoundary(6);
|
||||||
|
|
||||||
|
if(str !== "CDATA[") throw new Error(`Invalid CDATA expression at ${parser.source.line}:${parser.source.cols}`);
|
||||||
|
|
||||||
|
let text = parser.source.readUpto("]]>");
|
||||||
|
parser.outputBuilder.addCdata(text);
|
||||||
|
}
|
||||||
|
function readPiTag(parser){
|
||||||
|
//<? are already read till this point
|
||||||
|
let tagExp = readPiExp(parser, "?>");
|
||||||
|
if(!tagExp) throw new Error("Invalid Pi Tag expression.");
|
||||||
|
|
||||||
|
if (tagExp.tagName === "?xml") {//TODO: test if tagName is just xml
|
||||||
|
parser.outputBuilder.addDeclaration();
|
||||||
|
} else {
|
||||||
|
parser.outputBuilder.addPi("?"+tagExp.tagName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function readComment(parser){
|
||||||
|
//<!- are already read till this point
|
||||||
|
let ch = parser.source.readCh();
|
||||||
|
if(ch !== "-") throw new Error(`Invalid comment expression at ${parser.source.line}:${parser.source.cols}`);
|
||||||
|
|
||||||
|
let text = parser.source.readUpto("-->");
|
||||||
|
parser.outputBuilder.addComment(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
const DOCTYPE_tags = {
|
||||||
|
"EL":/^EMENT\s+([^\s>]+)\s+(ANY|EMPTY|\(.+\)\s*$)/m,
|
||||||
|
"AT":/^TLIST\s+[^\s]+\s+[^\s]+\s+[^\s]+\s+[^\s]+\s+$/m,
|
||||||
|
"NO":/^TATION.+$/m
|
||||||
|
}
|
||||||
|
function readDocType(parser){
|
||||||
|
//<!D are already read till this point
|
||||||
|
let str = parser.source.readStr(6); //OCTYPE
|
||||||
|
parser.source.updateBufferBoundary(6);
|
||||||
|
|
||||||
|
if(str !== "OCTYPE") throw new Error(`Invalid DOCTYPE expression at ${parser.source.line}:${parser.source.cols}`);
|
||||||
|
|
||||||
|
let hasBody = false, lastch = "";
|
||||||
|
|
||||||
|
while(parser.source.canRead()){
|
||||||
|
//TODO: use readChAt like used in partReader
|
||||||
|
let ch = parser.source.readCh();
|
||||||
|
if(hasBody){
|
||||||
|
if (ch === '<') { //Determine the tag type
|
||||||
|
let str = parser.source.readStr(2);
|
||||||
|
parser.source.updateBufferBoundary(2);
|
||||||
|
if(str === "EN"){ //ENTITY
|
||||||
|
let str = parser.source.readStr(4);
|
||||||
|
parser.source.updateBufferBoundary(4);
|
||||||
|
if(str !== "TITY") throw new Error("Invalid DOCTYPE ENTITY expression");
|
||||||
|
|
||||||
|
registerEntity(parser);
|
||||||
|
}else if(str === "!-") {//comment
|
||||||
|
readComment(parser);
|
||||||
|
}else{ //ELEMENT, ATTLIST, NOTATION
|
||||||
|
let dTagExp = parser.source.readUpto(">");
|
||||||
|
const regx = DOCTYPE_tags[str];
|
||||||
|
if(regx){
|
||||||
|
const match = dTagExp.match(regx);
|
||||||
|
if(!match) throw new Error("Invalid DOCTYPE");
|
||||||
|
}else throw new Error("Invalid DOCTYPE");
|
||||||
|
}
|
||||||
|
}else if( ch === '>' && lastch === "]"){//end of doctype
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}else if( ch === '>'){//end of doctype
|
||||||
|
return;
|
||||||
|
}else if( ch === '['){
|
||||||
|
hasBody = true;
|
||||||
|
}else{
|
||||||
|
lastch = ch;
|
||||||
|
}
|
||||||
|
}//End While loop
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function registerEntity(parser){
|
||||||
|
//read Entity
|
||||||
|
let attrBoundary="";
|
||||||
|
let name ="", val ="";
|
||||||
|
while(source.canRead()){
|
||||||
|
let ch = source.readCh();
|
||||||
|
|
||||||
|
if(attrBoundary){
|
||||||
|
if (ch === attrBoundary){
|
||||||
|
val = text;
|
||||||
|
text = ""
|
||||||
|
}
|
||||||
|
}else if(ch === " " || ch === "\t"){
|
||||||
|
if(!name){
|
||||||
|
name = text.trimStart();
|
||||||
|
text = "";
|
||||||
|
}
|
||||||
|
}else if (ch === '"' || ch === "'") {//start of attrBoundary
|
||||||
|
attrBoundary = ch;
|
||||||
|
}else if(ch === ">"){
|
||||||
|
parser.entityParser.addExternalEntity(name,val);
|
||||||
|
return;
|
||||||
|
}else{
|
||||||
|
text+=ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
readCdata: readCdata,
|
||||||
|
readComment:readComment,
|
||||||
|
readDocType:readDocType,
|
||||||
|
readPiTag:readPiTag
|
||||||
|
}
|
||||||
118
node_modules/fast-xml-parser/src/v5/inputSource/BufferSource.js
generated
vendored
Normal file
118
node_modules/fast-xml-parser/src/v5/inputSource/BufferSource.js
generated
vendored
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
const Constants = {
|
||||||
|
space: 32,
|
||||||
|
tab: 9
|
||||||
|
}
|
||||||
|
class BufferSource{
|
||||||
|
constructor(bytesArr){
|
||||||
|
this.line = 1;
|
||||||
|
this.cols = 0;
|
||||||
|
this.buffer = bytesArr;
|
||||||
|
this.startIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
readCh() {
|
||||||
|
return String.fromCharCode(this.buffer[this.startIndex++]);
|
||||||
|
}
|
||||||
|
|
||||||
|
readChAt(index) {
|
||||||
|
return String.fromCharCode(this.buffer[this.startIndex+index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
readStr(n,from){
|
||||||
|
if(typeof from === "undefined") from = this.startIndex;
|
||||||
|
return this.buffer.slice(from, from + n).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
readUpto(stopStr) {
|
||||||
|
const inputLength = this.buffer.length;
|
||||||
|
const stopLength = stopStr.length;
|
||||||
|
const stopBuffer = Buffer.from(stopStr);
|
||||||
|
|
||||||
|
for (let i = this.startIndex; i < inputLength; i++) {
|
||||||
|
let match = true;
|
||||||
|
for (let j = 0; j < stopLength; j++) {
|
||||||
|
if (this.buffer[i + j] !== stopBuffer[j]) {
|
||||||
|
match = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
const result = this.buffer.slice(this.startIndex, i).toString();
|
||||||
|
this.startIndex = i + stopLength;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(`Unexpected end of source. Reading '${stopStr}'`);
|
||||||
|
}
|
||||||
|
|
||||||
|
readUptoCloseTag(stopStr) { //stopStr: "</tagname"
|
||||||
|
const inputLength = this.buffer.length;
|
||||||
|
const stopLength = stopStr.length;
|
||||||
|
const stopBuffer = Buffer.from(stopStr);
|
||||||
|
let stopIndex = 0;
|
||||||
|
//0: non-matching, 1: matching stop string, 2: matching closing
|
||||||
|
let match = 0;
|
||||||
|
|
||||||
|
for (let i = this.startIndex; i < inputLength; i++) {
|
||||||
|
if(match === 1){//initial part matched
|
||||||
|
if(stopIndex === 0) stopIndex = i;
|
||||||
|
if(this.buffer[i] === Constants.space || this.buffer[i] === Constants.tab) continue;
|
||||||
|
else if(this.buffer[i] === '>'){ //TODO: if it should be equivalent ASCII
|
||||||
|
match = 2;
|
||||||
|
//tag boundary found
|
||||||
|
// this.startIndex
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
match = 1;
|
||||||
|
for (let j = 0; j < stopLength; j++) {
|
||||||
|
if (this.buffer[i + j] !== stopBuffer[j]) {
|
||||||
|
match = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (match === 2) {//matched closing part
|
||||||
|
const result = this.buffer.slice(this.startIndex, stopIndex - 1 ).toString();
|
||||||
|
this.startIndex = i + 1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(`Unexpected end of source. Reading '${stopStr}'`);
|
||||||
|
}
|
||||||
|
|
||||||
|
readFromBuffer(n, shouldUpdate) {
|
||||||
|
let ch;
|
||||||
|
if (n === 1) {
|
||||||
|
ch = this.buffer[this.startIndex];
|
||||||
|
if (ch === 10) {
|
||||||
|
this.line++;
|
||||||
|
this.cols = 1;
|
||||||
|
} else {
|
||||||
|
this.cols++;
|
||||||
|
}
|
||||||
|
ch = String.fromCharCode(ch);
|
||||||
|
} else {
|
||||||
|
this.cols += n;
|
||||||
|
ch = this.buffer.slice(this.startIndex, this.startIndex + n).toString();
|
||||||
|
}
|
||||||
|
if (shouldUpdate) this.updateBuffer(n);
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateBufferBoundary(n = 1) { //n: number of characters read
|
||||||
|
this.startIndex += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
canRead(n){
|
||||||
|
n = n || this.startIndex;
|
||||||
|
return this.buffer.length - n + 1 > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = BufferSource;
|
||||||
123
node_modules/fast-xml-parser/src/v5/inputSource/StringSource.js
generated
vendored
Normal file
123
node_modules/fast-xml-parser/src/v5/inputSource/StringSource.js
generated
vendored
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
const whiteSpaces = [" ", "\n", "\t"];
|
||||||
|
|
||||||
|
|
||||||
|
class StringSource{
|
||||||
|
constructor(str){
|
||||||
|
this.line = 1;
|
||||||
|
this.cols = 0;
|
||||||
|
this.buffer = str;
|
||||||
|
//a boundary pointer to indicate where from the buffer dat should be read
|
||||||
|
// data before this pointer can be deleted to free the memory
|
||||||
|
this.startIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
readCh() {
|
||||||
|
return this.buffer[this.startIndex++];
|
||||||
|
}
|
||||||
|
|
||||||
|
readChAt(index) {
|
||||||
|
return this.buffer[this.startIndex+index];
|
||||||
|
}
|
||||||
|
|
||||||
|
readStr(n,from){
|
||||||
|
if(typeof from === "undefined") from = this.startIndex;
|
||||||
|
return this.buffer.substring(from, from + n);
|
||||||
|
}
|
||||||
|
|
||||||
|
readUpto(stopStr) {
|
||||||
|
const inputLength = this.buffer.length;
|
||||||
|
const stopLength = stopStr.length;
|
||||||
|
|
||||||
|
for (let i = this.startIndex; i < inputLength; i++) {
|
||||||
|
let match = true;
|
||||||
|
for (let j = 0; j < stopLength; j++) {
|
||||||
|
if (this.buffer[i + j] !== stopStr[j]) {
|
||||||
|
match = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
const result = this.buffer.substring(this.startIndex, i);
|
||||||
|
this.startIndex = i + stopLength;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(`Unexpected end of source. Reading '${stopStr}'`);
|
||||||
|
}
|
||||||
|
|
||||||
|
readUptoCloseTag(stopStr) { //stopStr: "</tagname"
|
||||||
|
const inputLength = this.buffer.length;
|
||||||
|
const stopLength = stopStr.length;
|
||||||
|
let stopIndex = 0;
|
||||||
|
//0: non-matching, 1: matching stop string, 2: matching closing
|
||||||
|
let match = 0;
|
||||||
|
|
||||||
|
for (let i = this.startIndex; i < inputLength; i++) {
|
||||||
|
if(match === 1){//initial part matched
|
||||||
|
if(stopIndex === 0) stopIndex = i;
|
||||||
|
if(this.buffer[i] === ' ' || this.buffer[i] === '\t') continue;
|
||||||
|
else if(this.buffer[i] === '>'){
|
||||||
|
match = 2;
|
||||||
|
//tag boundary found
|
||||||
|
// this.startIndex
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
match = 1;
|
||||||
|
for (let j = 0; j < stopLength; j++) {
|
||||||
|
if (this.buffer[i + j] !== stopStr[j]) {
|
||||||
|
match = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (match === 2) {//matched closing part
|
||||||
|
const result = this.buffer.substring(this.startIndex, stopIndex - 1 );
|
||||||
|
this.startIndex = i + 1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(`Unexpected end of source. Reading '${stopStr}'`);
|
||||||
|
}
|
||||||
|
|
||||||
|
readFromBuffer(n, updateIndex){
|
||||||
|
let ch;
|
||||||
|
if(n===1){
|
||||||
|
ch = this.buffer[this.startIndex];
|
||||||
|
// if(ch === "\n") {
|
||||||
|
// this.line++;
|
||||||
|
// this.cols = 1;
|
||||||
|
// }else{
|
||||||
|
// this.cols++;
|
||||||
|
// }
|
||||||
|
}else{
|
||||||
|
ch = this.buffer.substring(this.startIndex, this.startIndex + n);
|
||||||
|
// if("".indexOf("\n") !== -1){
|
||||||
|
// //TODO: handle the scenario when there are multiple lines
|
||||||
|
// //TODO: col should be set to number of chars after last '\n'
|
||||||
|
// // this.cols = 1;
|
||||||
|
// }else{
|
||||||
|
// this.cols += n;
|
||||||
|
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
if(updateIndex) this.updateBufferBoundary(n);
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: rename to updateBufferReadIndex
|
||||||
|
|
||||||
|
updateBufferBoundary(n = 1) { //n: number of characters read
|
||||||
|
this.startIndex += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
canRead(n){
|
||||||
|
n = n || this.startIndex;
|
||||||
|
return this.buffer.length - n + 1 > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = StringSource;
|
||||||
107
node_modules/fast-xml-parser/src/v5/valueParsers/EntitiesParser.js
generated
vendored
Normal file
107
node_modules/fast-xml-parser/src/v5/valueParsers/EntitiesParser.js
generated
vendored
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
const ampEntity = { regex: /&(amp|#38|#x26);/g, val : "&"};
|
||||||
|
const htmlEntities = {
|
||||||
|
"space": { regex: /&(nbsp|#160);/g, val: " " },
|
||||||
|
// "lt" : { regex: /&(lt|#60);/g, val: "<" },
|
||||||
|
// "gt" : { regex: /&(gt|#62);/g, val: ">" },
|
||||||
|
// "amp" : { regex: /&(amp|#38);/g, val: "&" },
|
||||||
|
// "quot" : { regex: /&(quot|#34);/g, val: "\"" },
|
||||||
|
// "apos" : { regex: /&(apos|#39);/g, val: "'" },
|
||||||
|
"cent" : { regex: /&(cent|#162);/g, val: "¢" },
|
||||||
|
"pound" : { regex: /&(pound|#163);/g, val: "£" },
|
||||||
|
"yen" : { regex: /&(yen|#165);/g, val: "¥" },
|
||||||
|
"euro" : { regex: /&(euro|#8364);/g, val: "€" },
|
||||||
|
"copyright" : { regex: /&(copy|#169);/g, val: "©" },
|
||||||
|
"reg" : { regex: /&(reg|#174);/g, val: "®" },
|
||||||
|
"inr" : { regex: /&(inr|#8377);/g, val: "₹" },
|
||||||
|
"num_dec": { regex: /&#([0-9]{1,7});/g, val : (_, str) => String.fromCharCode(Number.parseInt(str, 10)) },
|
||||||
|
"num_hex": { regex: /&#x([0-9a-fA-F]{1,6});/g, val : (_, str) => String.fromCharCode(Number.parseInt(str, 16)) },
|
||||||
|
};
|
||||||
|
|
||||||
|
class EntitiesParser{
|
||||||
|
constructor(replaceHtmlEntities) {
|
||||||
|
this.replaceHtmlEntities = replaceHtmlEntities;
|
||||||
|
this.docTypeEntities = {};
|
||||||
|
this.lastEntities = {
|
||||||
|
"apos" : { regex: /&(apos|#39|#x27);/g, val : "'"},
|
||||||
|
"gt" : { regex: /&(gt|#62|#x3E);/g, val : ">"},
|
||||||
|
"lt" : { regex: /&(lt|#60|#x3C);/g, val : "<"},
|
||||||
|
"quot" : { regex: /&(quot|#34|#x22);/g, val : "\""},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
addExternalEntities(externalEntities){
|
||||||
|
const entKeys = Object.keys(externalEntities);
|
||||||
|
for (let i = 0; i < entKeys.length; i++) {
|
||||||
|
const ent = entKeys[i];
|
||||||
|
this.addExternalEntity(ent,externalEntities[ent])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addExternalEntity(key,val){
|
||||||
|
validateEntityName(key);
|
||||||
|
if(val.indexOf("&") !== -1) {
|
||||||
|
reportWarning(`Entity ${key} is not added as '&' is found in value;`)
|
||||||
|
return;
|
||||||
|
}else{
|
||||||
|
this.lastEntities[ent] = {
|
||||||
|
regex: new RegExp("&"+key+";","g"),
|
||||||
|
val : val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addDocTypeEntities(entities){
|
||||||
|
const entKeys = Object.keys(entities);
|
||||||
|
for (let i = 0; i < entKeys.length; i++) {
|
||||||
|
const ent = entKeys[i];
|
||||||
|
this.docTypeEntities[ent] = {
|
||||||
|
regex: new RegExp("&"+ent+";","g"),
|
||||||
|
val : entities[ent]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parse(val){
|
||||||
|
return this.replaceEntitiesValue(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Replace DOCTYPE entities
|
||||||
|
* 2. Replace external entities
|
||||||
|
* 3. Replace HTML entities if asked
|
||||||
|
* @param {string} val
|
||||||
|
*/
|
||||||
|
replaceEntitiesValue(val){
|
||||||
|
if(typeof val === "string" && val.length > 0){
|
||||||
|
for(let entityName in this.docTypeEntities){
|
||||||
|
const entity = this.docTypeEntities[entityName];
|
||||||
|
val = val.replace( entity.regx, entity.val);
|
||||||
|
}
|
||||||
|
for(let entityName in this.lastEntities){
|
||||||
|
const entity = this.lastEntities[entityName];
|
||||||
|
val = val.replace( entity.regex, entity.val);
|
||||||
|
}
|
||||||
|
if(this.replaceHtmlEntities){
|
||||||
|
for(let entityName in htmlEntities){
|
||||||
|
const entity = htmlEntities[entityName];
|
||||||
|
val = val.replace( entity.regex, entity.val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val = val.replace( ampEntity.regex, ampEntity.val);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//an entity name should not contains special characters that may be used in regex
|
||||||
|
//Eg !?\\\/[]$%{}^&*()<>
|
||||||
|
const specialChar = "!?\\\/[]$%{}^&*()<>|+";
|
||||||
|
|
||||||
|
function validateEntityName(name){
|
||||||
|
for (let i = 0; i < specialChar.length; i++) {
|
||||||
|
const ch = specialChar[i];
|
||||||
|
if(name.indexOf(ch) !== -1) throw new Error(`Invalid character ${ch} in entity name`);
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = EntitiesParser;
|
||||||
23
node_modules/fast-xml-parser/src/v5/valueParsers/booleanParser.js
generated
vendored
Normal file
23
node_modules/fast-xml-parser/src/v5/valueParsers/booleanParser.js
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
class boolParser{
|
||||||
|
constructor(trueList, falseList){
|
||||||
|
if(trueList)
|
||||||
|
this.trueList = trueList;
|
||||||
|
else
|
||||||
|
this.trueList = ["true"];
|
||||||
|
|
||||||
|
if(falseList)
|
||||||
|
this.falseList = falseList;
|
||||||
|
else
|
||||||
|
this.falseList = ["false"];
|
||||||
|
}
|
||||||
|
parse(val){
|
||||||
|
if (typeof val === 'string') {
|
||||||
|
//TODO: performance: don't convert
|
||||||
|
const temp = val.toLowerCase();
|
||||||
|
if(this.trueList.indexOf(temp) !== -1) return true;
|
||||||
|
else if(this.falseList.indexOf(temp) !== -1 ) return false;
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
module.exports = boolParser;
|
||||||
20
node_modules/fast-xml-parser/src/v5/valueParsers/booleanParserExt.js
generated
vendored
Normal file
20
node_modules/fast-xml-parser/src/v5/valueParsers/booleanParserExt.js
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
function boolParserExt(val){
|
||||||
|
if(isArray(val)){
|
||||||
|
for (let i = 0; i < val.length; i++) {
|
||||||
|
val[i] = parse(val[i])
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
val = parse(val)
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse(val){
|
||||||
|
if (typeof val === 'string') {
|
||||||
|
const temp = val.toLowerCase();
|
||||||
|
if(temp === 'true' || temp ==="yes" || temp==="1") return true;
|
||||||
|
else if(temp === 'false' || temp ==="no" || temp==="0") return false;
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
module.exports = boolParserExt;
|
||||||
40
node_modules/fast-xml-parser/src/v5/valueParsers/currency.js
generated
vendored
Normal file
40
node_modules/fast-xml-parser/src/v5/valueParsers/currency.js
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
const defaultOptions = {
|
||||||
|
maxLength: 200,
|
||||||
|
// locale: "en-IN"
|
||||||
|
}
|
||||||
|
const localeMap = {
|
||||||
|
"$":"en-US",
|
||||||
|
"€":"de-DE",
|
||||||
|
"£":"en-GB",
|
||||||
|
"¥":"ja-JP",
|
||||||
|
"₹":"en-IN",
|
||||||
|
}
|
||||||
|
const sign = "(?:-|\+)?";
|
||||||
|
const digitsAndSeparator = "(?:\d+|\d{1,3}(?:,\d{3})+)";
|
||||||
|
const decimalPart = "(?:\.\d{1,2})?";
|
||||||
|
const symbol = "(?:\$|€|¥|₹)?";
|
||||||
|
|
||||||
|
const currencyCheckRegex = /^\s*(?:-|\+)?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d{1,2})?\s*(?:\$|€|¥|₹)?\s*$/u;
|
||||||
|
|
||||||
|
class CurrencyParser{
|
||||||
|
constructor(options){
|
||||||
|
this.options = options || defaultOptions;
|
||||||
|
}
|
||||||
|
parse(val){
|
||||||
|
if (typeof val === 'string' && val.length <= this.options.maxLength) {
|
||||||
|
if(val.indexOf(",,") !== -1 && val.indexOf(".." !== -1)){
|
||||||
|
const match = val.match(currencyCheckRegex);
|
||||||
|
if(match){
|
||||||
|
const locale = this.options.locale || localeMap[match[2]||match[5]||"₹"];
|
||||||
|
const formatter = new Intl.NumberFormat(locale)
|
||||||
|
val = val.replace(/[^0-9,.]/g, '').trim();
|
||||||
|
val = Number(val.replace(formatter.format(1000)[1], ''));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CurrencyParser.defaultOptions = defaultOptions;
|
||||||
|
|
||||||
|
module.exports = CurrencyParser;
|
||||||
14
node_modules/fast-xml-parser/src/v5/valueParsers/join.js
generated
vendored
Normal file
14
node_modules/fast-xml-parser/src/v5/valueParsers/join.js
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {array} val
|
||||||
|
* @param {string} by
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function join(val, by=" "){
|
||||||
|
if(isArray(val)){
|
||||||
|
val.join(by)
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = join;
|
||||||
16
node_modules/fast-xml-parser/src/v5/valueParsers/number.js
generated
vendored
Normal file
16
node_modules/fast-xml-parser/src/v5/valueParsers/number.js
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
const toNumber = require("strnum");
|
||||||
|
|
||||||
|
|
||||||
|
class numParser{
|
||||||
|
constructor(options){
|
||||||
|
this.options = options;
|
||||||
|
}
|
||||||
|
parse(val){
|
||||||
|
if (typeof val === 'string') {
|
||||||
|
val = toNumber(val,this.options);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = numParser;
|
||||||
8
node_modules/fast-xml-parser/src/v5/valueParsers/trim.js
generated
vendored
Normal file
8
node_modules/fast-xml-parser/src/v5/valueParsers/trim.js
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
class trimmer{
|
||||||
|
parse(val){
|
||||||
|
if(typeof val === "string") return val.trim();
|
||||||
|
else return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = trimmer;
|
||||||
16
node_modules/fast-xml-parser/src/v6/CharsSymbol.js
generated
vendored
Normal file
16
node_modules/fast-xml-parser/src/v6/CharsSymbol.js
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
export default {
|
||||||
|
"<" : "<", //tag start
|
||||||
|
">" : ">", //tag end
|
||||||
|
"/" : "/", //close tag
|
||||||
|
"!" : "!", //comment or docttype
|
||||||
|
"!--" : "!--", //comment
|
||||||
|
"-->" : "-->", //comment end
|
||||||
|
"?" : "?", //pi
|
||||||
|
"?>" : "?>", //pi end
|
||||||
|
"?xml" : "?xml", //pi end
|
||||||
|
"![" : "![", //cdata
|
||||||
|
"]]>" : "]]>", //cdata end
|
||||||
|
"[" : "[",
|
||||||
|
"-" : "-",
|
||||||
|
"D" : "D",
|
||||||
|
}
|
||||||
104
node_modules/fast-xml-parser/src/v6/EntitiesParser.js
generated
vendored
Normal file
104
node_modules/fast-xml-parser/src/v6/EntitiesParser.js
generated
vendored
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
const ampEntity = { regex: /&(amp|#38|#x26);/g, val : "&"};
|
||||||
|
const htmlEntities = {
|
||||||
|
"space": { regex: /&(nbsp|#160);/g, val: " " },
|
||||||
|
// "lt" : { regex: /&(lt|#60);/g, val: "<" },
|
||||||
|
// "gt" : { regex: /&(gt|#62);/g, val: ">" },
|
||||||
|
// "amp" : { regex: /&(amp|#38);/g, val: "&" },
|
||||||
|
// "quot" : { regex: /&(quot|#34);/g, val: "\"" },
|
||||||
|
// "apos" : { regex: /&(apos|#39);/g, val: "'" },
|
||||||
|
"cent" : { regex: /&(cent|#162);/g, val: "¢" },
|
||||||
|
"pound" : { regex: /&(pound|#163);/g, val: "£" },
|
||||||
|
"yen" : { regex: /&(yen|#165);/g, val: "¥" },
|
||||||
|
"euro" : { regex: /&(euro|#8364);/g, val: "€" },
|
||||||
|
"copyright" : { regex: /&(copy|#169);/g, val: "©" },
|
||||||
|
"reg" : { regex: /&(reg|#174);/g, val: "®" },
|
||||||
|
"inr" : { regex: /&(inr|#8377);/g, val: "₹" },
|
||||||
|
"num_dec": { regex: /&#([0-9]{1,7});/g, val : (_, str) => String.fromCharCode(Number.parseInt(str, 10)) },
|
||||||
|
"num_hex": { regex: /&#x([0-9a-fA-F]{1,6});/g, val : (_, str) => String.fromCharCode(Number.parseInt(str, 16)) },
|
||||||
|
};
|
||||||
|
export default class EntitiesParser{
|
||||||
|
constructor(replaceHtmlEntities) {
|
||||||
|
this.replaceHtmlEntities = replaceHtmlEntities;
|
||||||
|
this.docTypeEntities = {};
|
||||||
|
this.lastEntities = {
|
||||||
|
"apos" : { regex: /&(apos|#39|#x27);/g, val : "'"},
|
||||||
|
"gt" : { regex: /&(gt|#62|#x3E);/g, val : ">"},
|
||||||
|
"lt" : { regex: /&(lt|#60|#x3C);/g, val : "<"},
|
||||||
|
"quot" : { regex: /&(quot|#34|#x22);/g, val : "\""},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
addExternalEntities(externalEntities){
|
||||||
|
const entKeys = Object.keys(externalEntities);
|
||||||
|
for (let i = 0; i < entKeys.length; i++) {
|
||||||
|
const ent = entKeys[i];
|
||||||
|
this.addExternalEntity(ent,externalEntities[ent])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addExternalEntity(key,val){
|
||||||
|
validateEntityName(key);
|
||||||
|
if(val.indexOf("&") !== -1) {
|
||||||
|
reportWarning(`Entity ${key} is not added as '&' is found in value;`)
|
||||||
|
return;
|
||||||
|
}else{
|
||||||
|
this.lastEntities[ent] = {
|
||||||
|
regex: new RegExp("&"+key+";","g"),
|
||||||
|
val : val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addDocTypeEntities(entities){
|
||||||
|
const entKeys = Object.keys(entities);
|
||||||
|
for (let i = 0; i < entKeys.length; i++) {
|
||||||
|
const ent = entKeys[i];
|
||||||
|
this.docTypeEntities[ent] = {
|
||||||
|
regex: new RegExp("&"+ent+";","g"),
|
||||||
|
val : entities[ent]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parse(val){
|
||||||
|
return this.replaceEntitiesValue(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Replace DOCTYPE entities
|
||||||
|
* 2. Replace external entities
|
||||||
|
* 3. Replace HTML entities if asked
|
||||||
|
* @param {string} val
|
||||||
|
*/
|
||||||
|
replaceEntitiesValue(val){
|
||||||
|
if(typeof val === "string" && val.length > 0){
|
||||||
|
for(let entityName in this.docTypeEntities){
|
||||||
|
const entity = this.docTypeEntities[entityName];
|
||||||
|
val = val.replace( entity.regx, entity.val);
|
||||||
|
}
|
||||||
|
for(let entityName in this.lastEntities){
|
||||||
|
const entity = this.lastEntities[entityName];
|
||||||
|
val = val.replace( entity.regex, entity.val);
|
||||||
|
}
|
||||||
|
if(this.replaceHtmlEntities){
|
||||||
|
for(let entityName in htmlEntities){
|
||||||
|
const entity = htmlEntities[entityName];
|
||||||
|
val = val.replace( entity.regex, entity.val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val = val.replace( ampEntity.regex, ampEntity.val);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//an entity name should not contains special characters that may be used in regex
|
||||||
|
//Eg !?\\\/[]$%{}^&*()<>
|
||||||
|
const specialChar = "!?\\\/[]$%{}^&*()<>|+";
|
||||||
|
|
||||||
|
function validateEntityName(name){
|
||||||
|
for (let i = 0; i < specialChar.length; i++) {
|
||||||
|
const ch = specialChar[i];
|
||||||
|
if(name.indexOf(ch) !== -1) throw new Error(`Invalid character ${ch} in entity name`);
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
61
node_modules/fast-xml-parser/src/v6/OptionsBuilder.js
generated
vendored
Executable file
61
node_modules/fast-xml-parser/src/v6/OptionsBuilder.js
generated
vendored
Executable file
@ -0,0 +1,61 @@
|
|||||||
|
|
||||||
|
import {JsObjOutputBuilder} from './OutputBuilders/JsObjBuilder.js';
|
||||||
|
|
||||||
|
export const defaultOptions = {
|
||||||
|
preserveOrder: false,
|
||||||
|
removeNSPrefix: false, // remove NS from tag name or attribute name if true
|
||||||
|
//ignoreRootElement : false,
|
||||||
|
stopNodes: [], //nested tags will not be parsed even for errors
|
||||||
|
// isArray: () => false, //User will set it
|
||||||
|
htmlEntities: false,
|
||||||
|
// skipEmptyListItem: false
|
||||||
|
tags:{
|
||||||
|
unpaired: [],
|
||||||
|
nameFor:{
|
||||||
|
cdata: false,
|
||||||
|
comment: false,
|
||||||
|
text: '#text'
|
||||||
|
},
|
||||||
|
separateTextProperty: false,
|
||||||
|
},
|
||||||
|
attributes:{
|
||||||
|
ignore: false,
|
||||||
|
booleanType: true,
|
||||||
|
entities: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
// select: ["img[src]"],
|
||||||
|
// stop: ["anim", "[ads]"]
|
||||||
|
only: [], // rest tags will be skipped. It will result in flat array
|
||||||
|
hierarchy: false, //will be used when a particular tag is set to be parsed.
|
||||||
|
skip: [], // will be skipped from parse result. on('skip') will be triggered
|
||||||
|
|
||||||
|
select: [], // on('select', tag => tag ) will be called if match
|
||||||
|
stop: [], //given tagPath will not be parsed. innerXML will be set as string value
|
||||||
|
OutputBuilder: new JsObjOutputBuilder(),
|
||||||
|
};
|
||||||
|
|
||||||
|
export const buildOptions = function(options) {
|
||||||
|
const finalOptions = { ... defaultOptions};
|
||||||
|
copyProperties(finalOptions,options)
|
||||||
|
return finalOptions;
|
||||||
|
};
|
||||||
|
|
||||||
|
function copyProperties(target, source) {
|
||||||
|
for (let key in source) {
|
||||||
|
if (source.hasOwnProperty(key)) {
|
||||||
|
if (key === 'OutputBuilder') {
|
||||||
|
target[key] = source[key];
|
||||||
|
}else if (typeof source[key] === 'object' && !Array.isArray(source[key])) {
|
||||||
|
// Recursively copy nested properties
|
||||||
|
if (typeof target[key] === 'undefined') {
|
||||||
|
target[key] = {};
|
||||||
|
}
|
||||||
|
copyProperties(target[key], source[key]);
|
||||||
|
} else {
|
||||||
|
// Copy non-nested properties
|
||||||
|
target[key] = source[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
69
node_modules/fast-xml-parser/src/v6/OutputBuilders/BaseOutputBuilder.js
generated
vendored
Normal file
69
node_modules/fast-xml-parser/src/v6/OutputBuilders/BaseOutputBuilder.js
generated
vendored
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
export default class BaseOutputBuilder{
|
||||||
|
constructor(){
|
||||||
|
// this.attributes = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
addAttribute(name, value){
|
||||||
|
if(this.options.onAttribute){
|
||||||
|
//TODO: better to pass tag path
|
||||||
|
const v = this.options.onAttribute(name, value, this.tagName);
|
||||||
|
if(v) this.attributes[v.name] = v.value;
|
||||||
|
}else{
|
||||||
|
name = this.options.attributes.prefix + name + this.options.attributes.suffix;
|
||||||
|
this.attributes[name] = this.parseValue(value, this.options.attributes.valueParsers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* parse value by chain of parsers
|
||||||
|
* @param {string} val
|
||||||
|
* @returns {any} parsed value if matching parser found
|
||||||
|
*/
|
||||||
|
parseValue = function(val, valParsers){
|
||||||
|
for (let i = 0; i < valParsers.length; i++) {
|
||||||
|
let valParser = valParsers[i];
|
||||||
|
if(typeof valParser === "string"){
|
||||||
|
valParser = this.registeredParsers[valParser];
|
||||||
|
}
|
||||||
|
if(valParser){
|
||||||
|
val = valParser.parse(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To add a nested empty tag.
|
||||||
|
* @param {string} key
|
||||||
|
* @param {any} val
|
||||||
|
*/
|
||||||
|
_addChild(key, val){}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* skip the comment if property is not set
|
||||||
|
*/
|
||||||
|
addComment(text){
|
||||||
|
if(this.options.nameFor.comment)
|
||||||
|
this._addChild(this.options.nameFor.comment, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
//store CDATA separately if property is set
|
||||||
|
//otherwise add to tag's value
|
||||||
|
addCdata(text){
|
||||||
|
if (this.options.nameFor.cdata) {
|
||||||
|
this._addChild(this.options.nameFor.cdata, text);
|
||||||
|
} else {
|
||||||
|
this.addRawValue(text || "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addRawValue = text => this.addValue(text);
|
||||||
|
|
||||||
|
addDeclaration(){
|
||||||
|
if(!this.options.declaration){
|
||||||
|
}else{
|
||||||
|
this.addPi("?xml");
|
||||||
|
}
|
||||||
|
this.attributes = {}
|
||||||
|
}
|
||||||
|
}
|
||||||
103
node_modules/fast-xml-parser/src/v6/OutputBuilders/JsArrBuilder.js
generated
vendored
Normal file
103
node_modules/fast-xml-parser/src/v6/OutputBuilders/JsArrBuilder.js
generated
vendored
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
import {buildOptions,registerCommonValueParsers} from './ParserOptionsBuilder.js';
|
||||||
|
|
||||||
|
export default class OutputBuilder{
|
||||||
|
constructor(options){
|
||||||
|
this.options = buildOptions(options);
|
||||||
|
this.registeredParsers = registerCommonValueParsers(this.options);
|
||||||
|
}
|
||||||
|
|
||||||
|
registerValueParser(name,parserInstance){//existing name will override the parser without warning
|
||||||
|
this.registeredParsers[name] = parserInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
getInstance(parserOptions){
|
||||||
|
return new JsArrBuilder(parserOptions, this.options, this.registeredParsers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const rootName = '!js_arr';
|
||||||
|
import BaseOutputBuilder from './BaseOutputBuilder.js';
|
||||||
|
|
||||||
|
class JsArrBuilder extends BaseOutputBuilder{
|
||||||
|
|
||||||
|
constructor(parserOptions, options,registeredParsers) {
|
||||||
|
super();
|
||||||
|
this.tagsStack = [];
|
||||||
|
this.parserOptions = parserOptions;
|
||||||
|
this.options = options;
|
||||||
|
this.registeredParsers = registeredParsers;
|
||||||
|
|
||||||
|
this.root = new Node(rootName);
|
||||||
|
this.currentNode = this.root;
|
||||||
|
this.attributes = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
addTag(tag){
|
||||||
|
//when a new tag is added, it should be added as child of current node
|
||||||
|
//TODO: shift this check to the parser
|
||||||
|
if(tag.name === "__proto__") tag.name = "#__proto__";
|
||||||
|
|
||||||
|
this.tagsStack.push(this.currentNode);
|
||||||
|
this.currentNode = new Node(tag.name, this.attributes);
|
||||||
|
this.attributes = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the node should be added by checking user's preference
|
||||||
|
* @param {Node} node
|
||||||
|
* @returns boolean: true if the node should not be added
|
||||||
|
*/
|
||||||
|
closeTag(){
|
||||||
|
const node = this.currentNode;
|
||||||
|
this.currentNode = this.tagsStack.pop(); //set parent node in scope
|
||||||
|
if(this.options.onClose !== undefined){
|
||||||
|
//TODO TagPathMatcher
|
||||||
|
const resultTag = this.options.onClose(node,
|
||||||
|
new TagPathMatcher(this.tagsStack,node));
|
||||||
|
|
||||||
|
if(resultTag) return;
|
||||||
|
}
|
||||||
|
this.currentNode.child.push(node); //to parent node
|
||||||
|
}
|
||||||
|
|
||||||
|
//Called by parent class methods
|
||||||
|
_addChild(key, val){
|
||||||
|
// if(key === "__proto__") tagName = "#__proto__";
|
||||||
|
this.currentNode.child.push( {[key]: val });
|
||||||
|
// this.currentNode.leafType = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add text value child node
|
||||||
|
* @param {string} text
|
||||||
|
*/
|
||||||
|
addValue(text){
|
||||||
|
this.currentNode.child.push( {[this.options.nameFor.text]: this.parseValue(text, this.options.tags.valueParsers) });
|
||||||
|
}
|
||||||
|
|
||||||
|
addPi(name){
|
||||||
|
//TODO: set pi flag
|
||||||
|
if(!this.options.ignorePiTags){
|
||||||
|
const node = new Node(name, this.attributes);
|
||||||
|
this.currentNode[":@"] = this.attributes;
|
||||||
|
this.currentNode.child.push(node);
|
||||||
|
}
|
||||||
|
this.attributes = {};
|
||||||
|
}
|
||||||
|
getOutput(){
|
||||||
|
return this.root.child[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Node{
|
||||||
|
constructor(tagname, attributes){
|
||||||
|
this.tagname = tagname;
|
||||||
|
this.child = []; //nested tags, text, cdata, comments
|
||||||
|
if(attributes && Object.keys(attributes).length > 0)
|
||||||
|
this[":@"] = attributes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = OutputBuilder;
|
||||||
100
node_modules/fast-xml-parser/src/v6/OutputBuilders/JsMinArrBuilder.js
generated
vendored
Normal file
100
node_modules/fast-xml-parser/src/v6/OutputBuilders/JsMinArrBuilder.js
generated
vendored
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
import {buildOptions,registerCommonValueParsers} from"./ParserOptionsBuilder";
|
||||||
|
|
||||||
|
export default class OutputBuilder{
|
||||||
|
constructor(options){
|
||||||
|
this.options = buildOptions(options);
|
||||||
|
this.registeredParsers = registerCommonValueParsers(this.options);
|
||||||
|
}
|
||||||
|
|
||||||
|
registerValueParser(name,parserInstance){//existing name will override the parser without warning
|
||||||
|
this.registeredParsers[name] = parserInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
getInstance(parserOptions){
|
||||||
|
return new JsMinArrBuilder(parserOptions, this.options, this.registeredParsers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
import BaseOutputBuilder from "./BaseOutputBuilder.js";
|
||||||
|
const rootName = '^';
|
||||||
|
|
||||||
|
class JsMinArrBuilder extends BaseOutputBuilder{
|
||||||
|
|
||||||
|
constructor(parserOptions, options,registeredParsers) {
|
||||||
|
super();
|
||||||
|
this.tagsStack = [];
|
||||||
|
this.parserOptions = parserOptions;
|
||||||
|
this.options = options;
|
||||||
|
this.registeredParsers = registeredParsers;
|
||||||
|
|
||||||
|
this.root = {[rootName]: []};
|
||||||
|
this.currentNode = this.root;
|
||||||
|
this.currentNodeTagName = rootName;
|
||||||
|
this.attributes = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
addTag(tag){
|
||||||
|
//when a new tag is added, it should be added as child of current node
|
||||||
|
//TODO: shift this check to the parser
|
||||||
|
if(tag.name === "__proto__") tag.name = "#__proto__";
|
||||||
|
|
||||||
|
this.tagsStack.push([this.currentNodeTagName,this.currentNode]); //this.currentNode is parent node here
|
||||||
|
this.currentNodeTagName = tag.name;
|
||||||
|
this.currentNode = { [tag.name]:[]}
|
||||||
|
if(Object.keys(this.attributes).length > 0){
|
||||||
|
this.currentNode[":@"] = this.attributes;
|
||||||
|
this.attributes = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the node should be added by checking user's preference
|
||||||
|
* @param {Node} node
|
||||||
|
* @returns boolean: true if the node should not be added
|
||||||
|
*/
|
||||||
|
closeTag(){
|
||||||
|
const node = this.currentNode;
|
||||||
|
const nodeName = this.currentNodeTagName;
|
||||||
|
const arr = this.tagsStack.pop(); //set parent node in scope
|
||||||
|
this.currentNodeTagName = arr[0];
|
||||||
|
this.currentNode = arr[1];
|
||||||
|
|
||||||
|
if(this.options.onClose !== undefined){
|
||||||
|
//TODO TagPathMatcher
|
||||||
|
const resultTag = this.options.onClose(node,
|
||||||
|
new TagPathMatcher(this.tagsStack,node));
|
||||||
|
|
||||||
|
if(resultTag) return;
|
||||||
|
}
|
||||||
|
this.currentNode[this.currentNodeTagName].push(node); //to parent node
|
||||||
|
}
|
||||||
|
|
||||||
|
//Called by parent class methods
|
||||||
|
_addChild(key, val){
|
||||||
|
// if(key === "__proto__") tagName = "#__proto__";
|
||||||
|
this.currentNode.push( {[key]: val });
|
||||||
|
// this.currentNode.leafType = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add text value child node
|
||||||
|
* @param {string} text
|
||||||
|
*/
|
||||||
|
addValue(text){
|
||||||
|
this.currentNode[this.currentNodeTagName].push( {[this.options.nameFor.text]: this.parseValue(text, this.options.tags.valueParsers) });
|
||||||
|
}
|
||||||
|
|
||||||
|
addPi(name){
|
||||||
|
if(!this.options.ignorePiTags){
|
||||||
|
const node = { [name]:[]}
|
||||||
|
if(this.attributes){
|
||||||
|
node[":@"] = this.attributes;
|
||||||
|
}
|
||||||
|
this.currentNode.push(node);
|
||||||
|
}
|
||||||
|
this.attributes = {};
|
||||||
|
}
|
||||||
|
getOutput(){
|
||||||
|
return this.root[rootName];
|
||||||
|
}
|
||||||
|
}
|
||||||
154
node_modules/fast-xml-parser/src/v6/OutputBuilders/JsObjBuilder.js
generated
vendored
Normal file
154
node_modules/fast-xml-parser/src/v6/OutputBuilders/JsObjBuilder.js
generated
vendored
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
|
||||||
|
|
||||||
|
import {buildOptions,registerCommonValueParsers} from './ParserOptionsBuilder.js';
|
||||||
|
|
||||||
|
export default class OutputBuilder{
|
||||||
|
constructor(builderOptions){
|
||||||
|
this.options = buildOptions(builderOptions);
|
||||||
|
this.registeredParsers = registerCommonValueParsers(this.options);
|
||||||
|
}
|
||||||
|
|
||||||
|
registerValueParser(name,parserInstance){//existing name will override the parser without warning
|
||||||
|
this.registeredParsers[name] = parserInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
getInstance(parserOptions){
|
||||||
|
return new JsObjBuilder(parserOptions, this.options, this.registeredParsers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
import BaseOutputBuilder from './BaseOutputBuilder.js';
|
||||||
|
const rootName = '^';
|
||||||
|
|
||||||
|
class JsObjBuilder extends BaseOutputBuilder{
|
||||||
|
|
||||||
|
constructor(parserOptions, builderOptions,registeredParsers) {
|
||||||
|
super();
|
||||||
|
//hold the raw detail of a tag and sequence with reference to the output
|
||||||
|
this.tagsStack = [];
|
||||||
|
this.parserOptions = parserOptions;
|
||||||
|
this.options = builderOptions;
|
||||||
|
this.registeredParsers = registeredParsers;
|
||||||
|
|
||||||
|
this.root = {};
|
||||||
|
this.parent = this.root;
|
||||||
|
this.tagName = rootName;
|
||||||
|
this.value = {};
|
||||||
|
this.textValue = "";
|
||||||
|
this.attributes = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
addTag(tag){
|
||||||
|
|
||||||
|
let value = "";
|
||||||
|
if( !isEmpty(this.attributes)){
|
||||||
|
value = {};
|
||||||
|
if(this.options.attributes.groupBy){
|
||||||
|
value[this.options.attributes.groupBy] = this.attributes;
|
||||||
|
}else{
|
||||||
|
value = this.attributes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.tagsStack.push([this.tagName, this.textValue, this.value]); //parent tag, parent text value, parent tag value (jsobj)
|
||||||
|
this.tagName = tag.name;
|
||||||
|
this.value = value;
|
||||||
|
this.textValue = "";
|
||||||
|
this.attributes = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the node should be added by checking user's preference
|
||||||
|
* @param {Node} node
|
||||||
|
* @returns boolean: true if the node should not be added
|
||||||
|
*/
|
||||||
|
closeTag(){
|
||||||
|
const tagName = this.tagName;
|
||||||
|
let value = this.value;
|
||||||
|
let textValue = this.textValue;
|
||||||
|
|
||||||
|
//update tag text value
|
||||||
|
if(typeof value !== "object" && !Array.isArray(value)){
|
||||||
|
value = this.parseValue(textValue.trim(), this.options.tags.valueParsers);
|
||||||
|
}else if(textValue.length > 0){
|
||||||
|
value[this.options.nameFor.text] = this.parseValue(textValue.trim(), this.options.tags.valueParsers);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let resultTag= {
|
||||||
|
tagName: tagName,
|
||||||
|
value: value
|
||||||
|
};
|
||||||
|
|
||||||
|
if(this.options.onTagClose !== undefined){
|
||||||
|
//TODO TagPathMatcher
|
||||||
|
resultTag = this.options.onClose(tagName, value, this.textValue, new TagPathMatcher(this.tagsStack,node));
|
||||||
|
|
||||||
|
if(!resultTag) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//set parent node in scope
|
||||||
|
let arr = this.tagsStack.pop();
|
||||||
|
let parentTag = arr[2];
|
||||||
|
parentTag=this._addChildTo(resultTag.tagName, resultTag.value, parentTag);
|
||||||
|
|
||||||
|
this.tagName = arr[0];
|
||||||
|
this.textValue = arr[1];
|
||||||
|
this.value = parentTag;
|
||||||
|
}
|
||||||
|
|
||||||
|
_addChild(key, val){
|
||||||
|
if(typeof this.value === "string"){
|
||||||
|
this.value = { [this.options.nameFor.text] : this.value };
|
||||||
|
}
|
||||||
|
|
||||||
|
this._addChildTo(key, val, this.value);
|
||||||
|
// this.currentNode.leafType = false;
|
||||||
|
this.attributes = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
_addChildTo(key, val, node){
|
||||||
|
if(typeof node === 'string') node = {};
|
||||||
|
if(!node[key]){
|
||||||
|
node[key] = val;
|
||||||
|
}else{ //Repeated
|
||||||
|
if(!Array.isArray(node[key])){ //but not stored as array
|
||||||
|
node[key] = [node[key]];
|
||||||
|
}
|
||||||
|
node[key].push(val);
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add text value child node
|
||||||
|
* @param {string} text
|
||||||
|
*/
|
||||||
|
addValue(text){
|
||||||
|
//TODO: use bytes join
|
||||||
|
if(this.textValue.length > 0) this.textValue += " " + text;
|
||||||
|
else this.textValue = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
addPi(name){
|
||||||
|
let value = "";
|
||||||
|
if( !isEmpty(this.attributes)){
|
||||||
|
value = {};
|
||||||
|
if(this.options.attributes.groupBy){
|
||||||
|
value[this.options.attributes.groupBy] = this.attributes;
|
||||||
|
}else{
|
||||||
|
value = this.attributes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._addChild(name, value);
|
||||||
|
|
||||||
|
}
|
||||||
|
getOutput(){
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isEmpty(obj) {
|
||||||
|
return Object.keys(obj).length === 0;
|
||||||
|
}
|
||||||
94
node_modules/fast-xml-parser/src/v6/OutputBuilders/ParserOptionsBuilder.js
generated
vendored
Normal file
94
node_modules/fast-xml-parser/src/v6/OutputBuilders/ParserOptionsBuilder.js
generated
vendored
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
import trimParser from "../valueParsers/trim";
|
||||||
|
import booleanParser from "../valueParsers/booleanParser";
|
||||||
|
import currencyParser from "../valueParsers/currency";
|
||||||
|
import numberParser from "../valueParsers/number";
|
||||||
|
|
||||||
|
const defaultOptions={
|
||||||
|
nameFor:{
|
||||||
|
text: "#text",
|
||||||
|
comment: "",
|
||||||
|
cdata: "",
|
||||||
|
},
|
||||||
|
// onTagClose: () => {},
|
||||||
|
// onAttribute: () => {},
|
||||||
|
piTag: false,
|
||||||
|
declaration: false, //"?xml"
|
||||||
|
tags: {
|
||||||
|
valueParsers: [
|
||||||
|
// "trim",
|
||||||
|
// "boolean",
|
||||||
|
// "number",
|
||||||
|
// "currency",
|
||||||
|
// "date",
|
||||||
|
]
|
||||||
|
},
|
||||||
|
attributes:{
|
||||||
|
prefix: "@_",
|
||||||
|
suffix: "",
|
||||||
|
groupBy: "",
|
||||||
|
|
||||||
|
valueParsers: [
|
||||||
|
// "trim",
|
||||||
|
// "boolean",
|
||||||
|
// "number",
|
||||||
|
// "currency",
|
||||||
|
// "date",
|
||||||
|
]
|
||||||
|
},
|
||||||
|
dataType:{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO
|
||||||
|
const withJoin = ["trim","join", /*"entities",*/"number","boolean","currency"/*, "date"*/]
|
||||||
|
const withoutJoin = ["trim", /*"entities",*/"number","boolean","currency"/*, "date"*/]
|
||||||
|
|
||||||
|
export function buildOptions(options){
|
||||||
|
//clone
|
||||||
|
const finalOptions = { ... defaultOptions};
|
||||||
|
|
||||||
|
//add config missed in cloning
|
||||||
|
finalOptions.tags.valueParsers.push(...withJoin)
|
||||||
|
if(!this.preserveOrder)
|
||||||
|
finalOptions.tags.valueParsers.push(...withoutJoin);
|
||||||
|
|
||||||
|
//add config missed in cloning
|
||||||
|
finalOptions.attributes.valueParsers.push(...withJoin)
|
||||||
|
|
||||||
|
//override configuration
|
||||||
|
copyProperties(finalOptions,options);
|
||||||
|
return finalOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyProperties(target, source) {
|
||||||
|
for (let key in source) {
|
||||||
|
if (source.hasOwnProperty(key)) {
|
||||||
|
if (typeof source[key] === 'object' && !Array.isArray(source[key])) {
|
||||||
|
// Recursively copy nested properties
|
||||||
|
if (typeof target[key] === 'undefined') {
|
||||||
|
target[key] = {};
|
||||||
|
}
|
||||||
|
copyProperties(target[key], source[key]);
|
||||||
|
} else {
|
||||||
|
// Copy non-nested properties
|
||||||
|
target[key] = source[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function registerCommonValueParsers(options){
|
||||||
|
return {
|
||||||
|
"trim": new trimParser(),
|
||||||
|
// "join": this.entityParser.parse,
|
||||||
|
"boolean": new booleanParser(),
|
||||||
|
"number": new numberParser({
|
||||||
|
hex: true,
|
||||||
|
leadingZeros: true,
|
||||||
|
eNotation: true
|
||||||
|
}),
|
||||||
|
"currency": new currencyParser(),
|
||||||
|
// "date": this.entityParser.parse,
|
||||||
|
}
|
||||||
|
}
|
||||||
0
node_modules/fast-xml-parser/src/v6/Report.js
generated
vendored
Normal file
0
node_modules/fast-xml-parser/src/v6/Report.js
generated
vendored
Normal file
81
node_modules/fast-xml-parser/src/v6/TagPath.js
generated
vendored
Normal file
81
node_modules/fast-xml-parser/src/v6/TagPath.js
generated
vendored
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
export default class TagPath{
|
||||||
|
constructor(pathStr){
|
||||||
|
let text = "";
|
||||||
|
let tName = "";
|
||||||
|
let pos;
|
||||||
|
let aName = "";
|
||||||
|
let aVal = "";
|
||||||
|
this.stack = []
|
||||||
|
|
||||||
|
for (let i = 0; i < pathStr.length; i++) {
|
||||||
|
let ch = pathStr[i];
|
||||||
|
if(ch === " ") {
|
||||||
|
if(text.length === 0) continue;
|
||||||
|
tName = text; text = "";
|
||||||
|
}else if(ch === "["){
|
||||||
|
if(tName.length === 0){
|
||||||
|
tName = text; text = "";
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
for (; i < pathStr.length; i++) {
|
||||||
|
ch = pathStr[i];
|
||||||
|
if(ch=== "=") continue;
|
||||||
|
else if(ch=== "]") {aName = text.trim(); text=""; break; i--;}
|
||||||
|
else if(ch === "'" || ch === '"'){
|
||||||
|
let attrEnd = pathStr.indexOf(ch,i+1);
|
||||||
|
aVal = pathStr.substring(i+1, attrEnd);
|
||||||
|
i = attrEnd;
|
||||||
|
}else{
|
||||||
|
text +=ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else if(ch !== " " && text.length === 0 && tName.length > 0){//reading tagName
|
||||||
|
//save previous tag
|
||||||
|
this.stack.push(new TagPathNode(tName,pos,aName,aVal));
|
||||||
|
text = ch; tName = ""; aName = ""; aVal = "";
|
||||||
|
}else{
|
||||||
|
text+=ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//last tag in the path
|
||||||
|
if(tName.length >0 || text.length>0){
|
||||||
|
this.stack.push(new TagPathNode(text||tName,pos,aName,aVal));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match(tagStack,node){
|
||||||
|
if(this.stack[0].name !== "*"){
|
||||||
|
if(this.stack.length !== tagStack.length +1) return false;
|
||||||
|
|
||||||
|
//loop through tagPath and tagStack and match
|
||||||
|
for (let i = 0; i < this.tagStack.length; i++) {
|
||||||
|
if(!this.stack[i].match(tagStack[i])) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!this.stack[this.stack.length - 1].match(node)) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TagPathNode{
|
||||||
|
constructor(name,position,attrName,attrVal){
|
||||||
|
this.name = name;
|
||||||
|
this.position = position;
|
||||||
|
this.attrName = attrName,
|
||||||
|
this.attrVal = attrVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
match(node){
|
||||||
|
let matching = true;
|
||||||
|
matching = node.name === this.name;
|
||||||
|
if(this.position) matching = node.position === this.position;
|
||||||
|
if(this.attrName) matching = node.attrs[this.attrName !== undefined];
|
||||||
|
if(this.attrVal) matching = node.attrs[this.attrName !== this.attrVal];
|
||||||
|
return matching;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log((new TagPath("* b[b]")).stack);
|
||||||
|
// console.log((new TagPath("a[a] b[b] c")).stack);
|
||||||
|
// console.log((new TagPath(" b [ b= 'cf sdadwa' ] a ")).stack);
|
||||||
13
node_modules/fast-xml-parser/src/v6/TagPathMatcher.js
generated
vendored
Normal file
13
node_modules/fast-xml-parser/src/v6/TagPathMatcher.js
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import {TagPath} from './TagPath.js';
|
||||||
|
|
||||||
|
export default class TagPathMatcher{
|
||||||
|
constructor(stack,node){
|
||||||
|
this.stack = stack;
|
||||||
|
this.node= node;
|
||||||
|
}
|
||||||
|
|
||||||
|
match(path){
|
||||||
|
const tagPath = new TagPath(path);
|
||||||
|
return tagPath.match(this.stack, this.node);
|
||||||
|
}
|
||||||
|
}
|
||||||
83
node_modules/fast-xml-parser/src/v6/XMLParser.js
generated
vendored
Executable file
83
node_modules/fast-xml-parser/src/v6/XMLParser.js
generated
vendored
Executable file
@ -0,0 +1,83 @@
|
|||||||
|
import { buildOptions} from './OptionsBuilder.js';
|
||||||
|
import Xml2JsParser from './Xml2JsParser.js';
|
||||||
|
|
||||||
|
export default class XMLParser{
|
||||||
|
|
||||||
|
constructor(options){
|
||||||
|
this.externalEntities = {};
|
||||||
|
this.options = buildOptions(options);
|
||||||
|
// console.log(this.options)
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse XML data string to JS object
|
||||||
|
* @param {string|Buffer} xmlData
|
||||||
|
* @param {boolean|Object} validationOption
|
||||||
|
*/
|
||||||
|
parse(xmlData){
|
||||||
|
if(Array.isArray(xmlData) && xmlData.byteLength !== undefined){
|
||||||
|
return this.parse(xmlData);
|
||||||
|
}else if( xmlData.toString){
|
||||||
|
xmlData = xmlData.toString();
|
||||||
|
}else{
|
||||||
|
throw new Error("XML data is accepted in String or Bytes[] form.")
|
||||||
|
}
|
||||||
|
// if( validationOption){
|
||||||
|
// if(validationOption === true) validationOption = {}; //validate with default options
|
||||||
|
|
||||||
|
// const result = validator.validate(xmlData, validationOption);
|
||||||
|
// if (result !== true) {
|
||||||
|
// throw Error( `${result.err.msg}:${result.err.line}:${result.err.col}` )
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
const parser = new Xml2JsParser(this.options);
|
||||||
|
parser.entityParser.addExternalEntities(this.externalEntities);
|
||||||
|
return parser.parse(xmlData);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse XML data buffer to JS object
|
||||||
|
* @param {string|Buffer} xmlData
|
||||||
|
* @param {boolean|Object} validationOption
|
||||||
|
*/
|
||||||
|
parseBytesArr(xmlData){
|
||||||
|
if(Array.isArray(xmlData) && xmlData.byteLength !== undefined){
|
||||||
|
}else{
|
||||||
|
throw new Error("XML data is accepted in Bytes[] form.")
|
||||||
|
}
|
||||||
|
const parser = new Xml2JsParser(this.options);
|
||||||
|
parser.entityParser.addExternalEntities(this.externalEntities);
|
||||||
|
return parser.parseBytesArr(xmlData);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse XML data stream to JS object
|
||||||
|
* @param {fs.ReadableStream} xmlDataStream
|
||||||
|
*/
|
||||||
|
parseStream(xmlDataStream){
|
||||||
|
if(!isStream(xmlDataStream)) throw new Error("FXP: Invalid stream input");
|
||||||
|
|
||||||
|
const orderedObjParser = new Xml2JsParser(this.options);
|
||||||
|
orderedObjParser.entityParser.addExternalEntities(this.externalEntities);
|
||||||
|
return orderedObjParser.parseStream(xmlDataStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add Entity which is not by default supported by this library
|
||||||
|
* @param {string} key
|
||||||
|
* @param {string} value
|
||||||
|
*/
|
||||||
|
addEntity(key, value){
|
||||||
|
if(value.indexOf("&") !== -1){
|
||||||
|
throw new Error("Entity value can't have '&'")
|
||||||
|
}else if(key.indexOf("&") !== -1 || key.indexOf(";") !== -1){
|
||||||
|
throw new Error("An entity must be set without '&' and ';'. Eg. use '#xD' for '
'")
|
||||||
|
}else if(value === "&"){
|
||||||
|
throw new Error("An entity with value '&' is not permitted");
|
||||||
|
}else{
|
||||||
|
this.externalEntities[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isStream(stream){
|
||||||
|
if(stream && typeof stream.read === "function" && typeof stream.on === "function" && typeof stream.readableEnded === "boolean") return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
235
node_modules/fast-xml-parser/src/v6/Xml2JsParser.js
generated
vendored
Normal file
235
node_modules/fast-xml-parser/src/v6/Xml2JsParser.js
generated
vendored
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
import StringSource from './inputSource/StringSource.js';
|
||||||
|
import BufferSource from './inputSource/BufferSource.js';
|
||||||
|
import {readTagExp,readClosingTagName} from './XmlPartReader.js';
|
||||||
|
import {readComment, readCdata,readDocType,readPiTag} from './XmlSpecialTagsReader.js';
|
||||||
|
import TagPath from './TagPath.js';
|
||||||
|
import TagPathMatcher from './TagPathMatcher.js';
|
||||||
|
import EntitiesParser from './EntitiesParser.js';
|
||||||
|
|
||||||
|
//To hold the data of current tag
|
||||||
|
//This is usually used to compare jpath expression against current tag
|
||||||
|
class TagDetail{
|
||||||
|
constructor(name){
|
||||||
|
this.name = name;
|
||||||
|
this.position = 0;
|
||||||
|
// this.attributes = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Xml2JsParser {
|
||||||
|
constructor(options) {
|
||||||
|
this.options = options;
|
||||||
|
|
||||||
|
this.currentTagDetail = null;
|
||||||
|
this.tagTextData = "";
|
||||||
|
this.tagsStack = [];
|
||||||
|
this.entityParser = new EntitiesParser(options.htmlEntities);
|
||||||
|
this.stopNodes = [];
|
||||||
|
for (let i = 0; i < this.options.stopNodes.length; i++) {
|
||||||
|
this.stopNodes.push(new TagPath(this.options.stopNodes[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parse(strData) {
|
||||||
|
this.source = new StringSource(strData);
|
||||||
|
this.parseXml();
|
||||||
|
return this.outputBuilder.getOutput();
|
||||||
|
}
|
||||||
|
parseBytesArr(data) {
|
||||||
|
this.source = new BufferSource(data );
|
||||||
|
this.parseXml();
|
||||||
|
return this.outputBuilder.getOutput();
|
||||||
|
}
|
||||||
|
|
||||||
|
parseXml() {
|
||||||
|
//TODO: Separate TagValueParser as separate class. So no scope issue in node builder class
|
||||||
|
|
||||||
|
//OutputBuilder should be set in XML Parser
|
||||||
|
this.outputBuilder = this.options.OutputBuilder.getInstance(this.options);
|
||||||
|
this.root = { root: true};
|
||||||
|
this.currentTagDetail = this.root;
|
||||||
|
|
||||||
|
while(this.source.canRead()){
|
||||||
|
let ch = this.source.readCh();
|
||||||
|
if (ch === "") break;
|
||||||
|
|
||||||
|
if(ch === "<"){//tagStart
|
||||||
|
let nextChar = this.source.readChAt(0);
|
||||||
|
if (nextChar === "" ) throw new Error("Unexpected end of source");
|
||||||
|
|
||||||
|
|
||||||
|
if(nextChar === "!" || nextChar === "?"){
|
||||||
|
this.source.updateBufferBoundary();
|
||||||
|
//previously collected text should be added to current node
|
||||||
|
this.addTextNode();
|
||||||
|
|
||||||
|
this.readSpecialTag(nextChar);// Read DOCTYPE, comment, CDATA, PI tag
|
||||||
|
}else if(nextChar === "/"){
|
||||||
|
this.source.updateBufferBoundary();
|
||||||
|
this.readClosingTag();
|
||||||
|
// console.log(this.source.buffer.length, this.source.readable);
|
||||||
|
// console.log(this.tagsStack.length);
|
||||||
|
}else{//opening tag
|
||||||
|
this.readOpeningTag();
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
this.tagTextData += ch;
|
||||||
|
}
|
||||||
|
}//End While loop
|
||||||
|
if(this.tagsStack.length > 0 || ( this.tagTextData !== "undefined" && this.tagTextData.trimEnd().length > 0) ) throw new Error("Unexpected data in the end of document");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* read closing paired tag. Set parent tag in scope.
|
||||||
|
* skip a node on user's choice
|
||||||
|
*/
|
||||||
|
readClosingTag(){
|
||||||
|
const tagName = this.processTagName(readClosingTagName(this.source));
|
||||||
|
// console.log(tagName, this.tagsStack.length);
|
||||||
|
this.validateClosingTag(tagName);
|
||||||
|
// All the text data collected, belongs to current tag.
|
||||||
|
if(!this.currentTagDetail.root) this.addTextNode();
|
||||||
|
this.outputBuilder.closeTag();
|
||||||
|
// Since the tag is closed now, parent tag comes in scope
|
||||||
|
this.currentTagDetail = this.tagsStack.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
validateClosingTag(tagName){
|
||||||
|
// This can't be unpaired tag, or a stop tag.
|
||||||
|
if(this.isUnpaired(tagName) || this.isStopNode(tagName)) throw new Error(`Unexpected closing tag '${tagName}'`);
|
||||||
|
// This must match with last opening tag
|
||||||
|
else if(tagName !== this.currentTagDetail.name)
|
||||||
|
throw new Error(`Unexpected closing tag '${tagName}' expecting '${this.currentTagDetail.name}'`)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read paired, unpaired, self-closing, stop and special tags.
|
||||||
|
* Create a new node
|
||||||
|
* Push paired tag in stack.
|
||||||
|
*/
|
||||||
|
readOpeningTag(){
|
||||||
|
//save previously collected text data to current node
|
||||||
|
this.addTextNode();
|
||||||
|
|
||||||
|
//create new tag
|
||||||
|
let tagExp = readTagExp(this, ">" );
|
||||||
|
|
||||||
|
// process and skip from tagsStack For unpaired tag, self closing tag, and stop node
|
||||||
|
const tagDetail = new TagDetail(tagExp.tagName);
|
||||||
|
if(this.isUnpaired(tagExp.tagName)) {
|
||||||
|
//TODO: this will lead 2 extra stack operation
|
||||||
|
this.outputBuilder.addTag(tagDetail);
|
||||||
|
this.outputBuilder.closeTag();
|
||||||
|
} else if(tagExp.selfClosing){
|
||||||
|
this.outputBuilder.addTag(tagDetail);
|
||||||
|
this.outputBuilder.closeTag();
|
||||||
|
} else if(this.isStopNode(this.currentTagDetail)){
|
||||||
|
// TODO: let's user set a stop node boundary detector for complex contents like script tag
|
||||||
|
//TODO: pass tag name only to avoid string operations
|
||||||
|
const content = source.readUptoCloseTag(`</${tagExp.tagName}`);
|
||||||
|
this.outputBuilder.addTag(tagDetail);
|
||||||
|
this.outputBuilder.addValue(content);
|
||||||
|
this.outputBuilder.closeTag();
|
||||||
|
}else{//paired tag
|
||||||
|
//set new nested tag in scope.
|
||||||
|
this.tagsStack.push(this.currentTagDetail);
|
||||||
|
this.outputBuilder.addTag(tagDetail);
|
||||||
|
this.currentTagDetail = tagDetail;
|
||||||
|
}
|
||||||
|
// console.log(tagExp.tagName,this.tagsStack.length);
|
||||||
|
// this.options.onClose()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
readSpecialTag(startCh){
|
||||||
|
if(startCh == "!"){
|
||||||
|
let nextChar = this.source.readCh();
|
||||||
|
if (nextChar === null || nextChar === undefined) throw new Error("Unexpected ending of the source");
|
||||||
|
|
||||||
|
if(nextChar === "-"){//comment
|
||||||
|
readComment(this);
|
||||||
|
}else if(nextChar === "["){//CDATA
|
||||||
|
readCdata(this);
|
||||||
|
}else if(nextChar === "D"){//DOCTYPE
|
||||||
|
readDocType(this);
|
||||||
|
}
|
||||||
|
}else if(startCh === "?"){
|
||||||
|
readPiTag(this);
|
||||||
|
}else{
|
||||||
|
throw new Error(`Invalid tag '<${startCh}' at ${this.source.line}:${this.source.col}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addTextNode = function() {
|
||||||
|
// if(this.currentTagDetail){
|
||||||
|
//save text as child node
|
||||||
|
// if(this.currentTagDetail.tagname !== '!xml')
|
||||||
|
if (this.tagTextData !== undefined && this.tagTextData !== "") { //store previously collected data as textNode
|
||||||
|
if(this.tagTextData.trim().length > 0){
|
||||||
|
//TODO: shift parsing to output builder
|
||||||
|
|
||||||
|
this.outputBuilder.addValue(this.replaceEntities(this.tagTextData));
|
||||||
|
}
|
||||||
|
this.tagTextData = "";
|
||||||
|
}
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
processAttrName(name){
|
||||||
|
if(name === "__proto__") name = "#__proto__";
|
||||||
|
name = resolveNameSpace(name, this.removeNSPrefix);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
processTagName(name){
|
||||||
|
if(name === "__proto__") name = "#__proto__";
|
||||||
|
name = resolveNameSpace(name, this.removeNSPrefix);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate tags path from tagsStack
|
||||||
|
*/
|
||||||
|
tagsPath(tagName){
|
||||||
|
//TODO: return TagPath Object. User can call match method with path
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
isUnpaired(tagName){
|
||||||
|
return this.options.tags.unpaired.indexOf(tagName) !== -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* valid expressions are
|
||||||
|
* tag nested
|
||||||
|
* * nested
|
||||||
|
* tag nested[attribute]
|
||||||
|
* tag nested[attribute=""]
|
||||||
|
* tag nested[attribute!=""]
|
||||||
|
* tag nested:0 //for future
|
||||||
|
* @param {string} tagName
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
isStopNode(node){
|
||||||
|
for (let i = 0; i < this.stopNodes.length; i++) {
|
||||||
|
const givenPath = this.stopNodes[i];
|
||||||
|
if(givenPath.match(this.tagsStack, node)) return true;
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
replaceEntities(text){
|
||||||
|
//TODO: if option is set then replace entities
|
||||||
|
return this.entityParser.parse(text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveNameSpace(name, removeNSPrefix) {
|
||||||
|
if (removeNSPrefix) {
|
||||||
|
const parts = name.split(':');
|
||||||
|
if(parts.length === 2){
|
||||||
|
if (parts[0] === 'xmlns') return '';
|
||||||
|
else return parts[1];
|
||||||
|
}else reportError(`Multiple namespaces ${name}`)
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
210
node_modules/fast-xml-parser/src/v6/XmlPartReader.js
generated
vendored
Normal file
210
node_modules/fast-xml-parser/src/v6/XmlPartReader.js
generated
vendored
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find paired tag for a stop node
|
||||||
|
* @param {string} xmlDoc
|
||||||
|
* @param {string} tagName
|
||||||
|
* @param {number} i : start index
|
||||||
|
*/
|
||||||
|
export function readStopNode(xmlDoc, tagName, i){
|
||||||
|
const startIndex = i;
|
||||||
|
// Starting at 1 since we already have an open tag
|
||||||
|
let openTagCount = 1;
|
||||||
|
|
||||||
|
for (; i < xmlDoc.length; i++) {
|
||||||
|
if( xmlDoc[i] === "<"){
|
||||||
|
if (xmlDoc[i+1] === "/") {//close tag
|
||||||
|
const closeIndex = findSubStrIndex(xmlDoc, ">", i, `${tagName} is not closed`);
|
||||||
|
let closeTagName = xmlDoc.substring(i+2,closeIndex).trim();
|
||||||
|
if(closeTagName === tagName){
|
||||||
|
openTagCount--;
|
||||||
|
if (openTagCount === 0) {
|
||||||
|
return {
|
||||||
|
tagContent: xmlDoc.substring(startIndex, i),
|
||||||
|
i : closeIndex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i=closeIndex;
|
||||||
|
} else if(xmlDoc[i+1] === '?') {
|
||||||
|
const closeIndex = findSubStrIndex(xmlDoc, "?>", i+1, "StopNode is not closed.")
|
||||||
|
i=closeIndex;
|
||||||
|
} else if(xmlDoc.substr(i + 1, 3) === '!--') {
|
||||||
|
const closeIndex = findSubStrIndex(xmlDoc, "-->", i+3, "StopNode is not closed.")
|
||||||
|
i=closeIndex;
|
||||||
|
} else if(xmlDoc.substr(i + 1, 2) === '![') {
|
||||||
|
const closeIndex = findSubStrIndex(xmlDoc, "]]>", i, "StopNode is not closed.") - 2;
|
||||||
|
i=closeIndex;
|
||||||
|
} else {
|
||||||
|
const tagData = readTagExp(xmlDoc, i, '>')
|
||||||
|
|
||||||
|
if (tagData) {
|
||||||
|
const openTagName = tagData && tagData.tagName;
|
||||||
|
if (openTagName === tagName && tagData.tagExp[tagData.tagExp.length-1] !== "/") {
|
||||||
|
openTagCount++;
|
||||||
|
}
|
||||||
|
i=tagData.closeIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}//end for loop
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read closing tag name
|
||||||
|
* @param {Source} source
|
||||||
|
* @returns tag name
|
||||||
|
*/
|
||||||
|
export function readClosingTagName(source){
|
||||||
|
let text = ""; //temporary data
|
||||||
|
while(source.canRead()){
|
||||||
|
let ch = source.readCh();
|
||||||
|
// if (ch === null || ch === undefined) break;
|
||||||
|
// source.updateBuffer();
|
||||||
|
|
||||||
|
if (ch === ">") return text.trimEnd();
|
||||||
|
else text += ch;
|
||||||
|
}
|
||||||
|
throw new Error(`Unexpected end of source. Reading '${substr}'`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read XML tag and build attributes map
|
||||||
|
* This function can be used to read normal tag, pi tag.
|
||||||
|
* This function can't be used to read comment, CDATA, DOCTYPE.
|
||||||
|
* Eg <tag attr = ' some"' attr= ">" bool>
|
||||||
|
* @param {string} xmlDoc
|
||||||
|
* @param {number} startIndex starting index
|
||||||
|
* @returns tag expression includes tag name & attribute string
|
||||||
|
*/
|
||||||
|
export function readTagExp(parser) {
|
||||||
|
let inSingleQuotes = false;
|
||||||
|
let inDoubleQuotes = false;
|
||||||
|
let i;
|
||||||
|
let EOE = false;
|
||||||
|
|
||||||
|
for (i = 0; parser.source.canRead(i); i++) {
|
||||||
|
const char = parser.source.readChAt(i);
|
||||||
|
|
||||||
|
if (char === "'" && !inDoubleQuotes) {
|
||||||
|
inSingleQuotes = !inSingleQuotes;
|
||||||
|
} else if (char === '"' && !inSingleQuotes) {
|
||||||
|
inDoubleQuotes = !inDoubleQuotes;
|
||||||
|
} else if (char === '>' && !inSingleQuotes && !inDoubleQuotes) {
|
||||||
|
// If not inside quotes, stop reading at '>'
|
||||||
|
EOE = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if(inSingleQuotes || inDoubleQuotes){
|
||||||
|
throw new Error("Invalid attribute expression. Quote is not properly closed");
|
||||||
|
}else if(!EOE) throw new Error("Unexpected closing of source. Waiting for '>'");
|
||||||
|
|
||||||
|
|
||||||
|
const exp = parser.source.readStr(i);
|
||||||
|
parser.source.updateBufferBoundary(i + 1);
|
||||||
|
return buildTagExpObj(exp, parser)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function readPiExp(parser) {
|
||||||
|
let inSingleQuotes = false;
|
||||||
|
let inDoubleQuotes = false;
|
||||||
|
let i;
|
||||||
|
let EOE = false;
|
||||||
|
|
||||||
|
for (i = 0; parser.source.canRead(i) ; i++) {
|
||||||
|
const currentChar = parser.source.readChAt(i);
|
||||||
|
const nextChar = parser.source.readChAt(i+1);
|
||||||
|
|
||||||
|
if (currentChar === "'" && !inDoubleQuotes) {
|
||||||
|
inSingleQuotes = !inSingleQuotes;
|
||||||
|
} else if (currentChar === '"' && !inSingleQuotes) {
|
||||||
|
inDoubleQuotes = !inDoubleQuotes;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!inSingleQuotes && !inDoubleQuotes) {
|
||||||
|
if (currentChar === '?' && nextChar === '>') {
|
||||||
|
EOE = true;
|
||||||
|
break; // Exit the loop when '?>' is found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(inSingleQuotes || inDoubleQuotes){
|
||||||
|
throw new Error("Invalid attribute expression. Quote is not properly closed in PI tag expression");
|
||||||
|
}else if(!EOE) throw new Error("Unexpected closing of source. Waiting for '?>'");
|
||||||
|
|
||||||
|
if(!parser.options.attributes.ignore){
|
||||||
|
//TODO: use regex to verify attributes if not set to ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
const exp = parser.source.readStr(i);
|
||||||
|
parser.source.updateBufferBoundary(i + 1);
|
||||||
|
return buildTagExpObj(exp, parser)
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildTagExpObj(exp, parser){
|
||||||
|
const tagExp = {
|
||||||
|
tagName: "",
|
||||||
|
selfClosing: false
|
||||||
|
};
|
||||||
|
let attrsExp = "";
|
||||||
|
|
||||||
|
// Check for self-closing tag before setting the name
|
||||||
|
if(exp[exp.length -1] === "/") {
|
||||||
|
tagExp.selfClosing = true;
|
||||||
|
exp = exp.slice(0, -1); // Remove the trailing slash
|
||||||
|
}
|
||||||
|
|
||||||
|
//separate tag name
|
||||||
|
let i = 0;
|
||||||
|
for (; i < exp.length; i++) {
|
||||||
|
const char = exp[i];
|
||||||
|
if(char === " "){
|
||||||
|
tagExp.tagName = exp.substring(0, i);
|
||||||
|
attrsExp = exp.substring(i + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//only tag
|
||||||
|
if(tagExp.tagName.length === 0 && i === exp.length)tagExp.tagName = exp;
|
||||||
|
|
||||||
|
tagExp.tagName = tagExp.tagName.trimEnd();
|
||||||
|
|
||||||
|
if(!parser.options.attributes.ignore && attrsExp.length > 0){
|
||||||
|
parseAttributesExp(attrsExp,parser)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tagExp;
|
||||||
|
}
|
||||||
|
|
||||||
|
const attrsRegx = new RegExp('([^\\s=]+)\\s*(=\\s*([\'"])([\\s\\S]*?)\\3)?', 'gm');
|
||||||
|
|
||||||
|
function parseAttributesExp(attrStr, parser) {
|
||||||
|
const matches = getAllMatches(attrStr, attrsRegx);
|
||||||
|
const len = matches.length; //don't make it inline
|
||||||
|
for (let i = 0; i < len; i++) {
|
||||||
|
let attrName = parser.processAttrName(matches[i][1]);
|
||||||
|
let attrVal = parser.replaceEntities(matches[i][4] || true);
|
||||||
|
|
||||||
|
parser.outputBuilder.addAttribute(attrName, attrVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const getAllMatches = function(string, regex) {
|
||||||
|
const matches = [];
|
||||||
|
let match = regex.exec(string);
|
||||||
|
while (match) {
|
||||||
|
const allmatches = [];
|
||||||
|
allmatches.startIndex = regex.lastIndex - match[0].length;
|
||||||
|
const len = match.length;
|
||||||
|
for (let index = 0; index < len; index++) {
|
||||||
|
allmatches.push(match[index]);
|
||||||
|
}
|
||||||
|
matches.push(allmatches);
|
||||||
|
match = regex.exec(string);
|
||||||
|
}
|
||||||
|
return matches;
|
||||||
|
};
|
||||||
|
|
||||||
111
node_modules/fast-xml-parser/src/v6/XmlSpecialTagsReader.js
generated
vendored
Normal file
111
node_modules/fast-xml-parser/src/v6/XmlSpecialTagsReader.js
generated
vendored
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
import {readPiExp} from './XmlPartReader.js';
|
||||||
|
|
||||||
|
export function readCdata(parser){
|
||||||
|
//<![ are already read till this point
|
||||||
|
let str = parser.source.readStr(6); //CDATA[
|
||||||
|
parser.source.updateBufferBoundary(6);
|
||||||
|
|
||||||
|
if(str !== "CDATA[") throw new Error(`Invalid CDATA expression at ${parser.source.line}:${parser.source.cols}`);
|
||||||
|
|
||||||
|
let text = parser.source.readUpto("]]>");
|
||||||
|
parser.outputBuilder.addCdata(text);
|
||||||
|
}
|
||||||
|
export function readPiTag(parser){
|
||||||
|
//<? are already read till this point
|
||||||
|
let tagExp = readPiExp(parser, "?>");
|
||||||
|
if(!tagExp) throw new Error("Invalid Pi Tag expression.");
|
||||||
|
|
||||||
|
if (tagExp.tagName === "?xml") {//TODO: test if tagName is just xml
|
||||||
|
parser.outputBuilder.addDeclaration();
|
||||||
|
} else {
|
||||||
|
parser.outputBuilder.addPi("?"+tagExp.tagName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function readComment(parser){
|
||||||
|
//<!- are already read till this point
|
||||||
|
let ch = parser.source.readCh();
|
||||||
|
if(ch !== "-") throw new Error(`Invalid comment expression at ${parser.source.line}:${parser.source.cols}`);
|
||||||
|
|
||||||
|
let text = parser.source.readUpto("-->");
|
||||||
|
parser.outputBuilder.addComment(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
const DOCTYPE_tags = {
|
||||||
|
"EL":/^EMENT\s+([^\s>]+)\s+(ANY|EMPTY|\(.+\)\s*$)/m,
|
||||||
|
"AT":/^TLIST\s+[^\s]+\s+[^\s]+\s+[^\s]+\s+[^\s]+\s+$/m,
|
||||||
|
"NO":/^TATION.+$/m
|
||||||
|
}
|
||||||
|
export function readDocType(parser){
|
||||||
|
//<!D are already read till this point
|
||||||
|
let str = parser.source.readStr(6); //OCTYPE
|
||||||
|
parser.source.updateBufferBoundary(6);
|
||||||
|
|
||||||
|
if(str !== "OCTYPE") throw new Error(`Invalid DOCTYPE expression at ${parser.source.line}:${parser.source.cols}`);
|
||||||
|
|
||||||
|
let hasBody = false, lastch = "";
|
||||||
|
|
||||||
|
while(parser.source.canRead()){
|
||||||
|
//TODO: use readChAt like used in partReader
|
||||||
|
let ch = parser.source.readCh();
|
||||||
|
if(hasBody){
|
||||||
|
if (ch === '<') { //Determine the tag type
|
||||||
|
let str = parser.source.readStr(2);
|
||||||
|
parser.source.updateBufferBoundary(2);
|
||||||
|
if(str === "EN"){ //ENTITY
|
||||||
|
let str = parser.source.readStr(4);
|
||||||
|
parser.source.updateBufferBoundary(4);
|
||||||
|
if(str !== "TITY") throw new Error("Invalid DOCTYPE ENTITY expression");
|
||||||
|
|
||||||
|
registerEntity(parser);
|
||||||
|
}else if(str === "!-") {//comment
|
||||||
|
readComment(parser);
|
||||||
|
}else{ //ELEMENT, ATTLIST, NOTATION
|
||||||
|
let dTagExp = parser.source.readUpto(">");
|
||||||
|
const regx = DOCTYPE_tags[str];
|
||||||
|
if(regx){
|
||||||
|
const match = dTagExp.match(regx);
|
||||||
|
if(!match) throw new Error("Invalid DOCTYPE");
|
||||||
|
}else throw new Error("Invalid DOCTYPE");
|
||||||
|
}
|
||||||
|
}else if( ch === '>' && lastch === "]"){//end of doctype
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}else if( ch === '>'){//end of doctype
|
||||||
|
return;
|
||||||
|
}else if( ch === '['){
|
||||||
|
hasBody = true;
|
||||||
|
}else{
|
||||||
|
lastch = ch;
|
||||||
|
}
|
||||||
|
}//End While loop
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function registerEntity(parser){
|
||||||
|
//read Entity
|
||||||
|
let attrBoundary="";
|
||||||
|
let name ="", val ="";
|
||||||
|
while(source.canRead()){
|
||||||
|
let ch = source.readCh();
|
||||||
|
|
||||||
|
if(attrBoundary){
|
||||||
|
if (ch === attrBoundary){
|
||||||
|
val = text;
|
||||||
|
text = ""
|
||||||
|
}
|
||||||
|
}else if(ch === " " || ch === "\t"){
|
||||||
|
if(!name){
|
||||||
|
name = text.trimStart();
|
||||||
|
text = "";
|
||||||
|
}
|
||||||
|
}else if (ch === '"' || ch === "'") {//start of attrBoundary
|
||||||
|
attrBoundary = ch;
|
||||||
|
}else if(ch === ">"){
|
||||||
|
parser.entityParser.addExternalEntity(name,val);
|
||||||
|
return;
|
||||||
|
}else{
|
||||||
|
text+=ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
116
node_modules/fast-xml-parser/src/v6/inputSource/BufferSource.js
generated
vendored
Normal file
116
node_modules/fast-xml-parser/src/v6/inputSource/BufferSource.js
generated
vendored
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
const Constants = {
|
||||||
|
space: 32,
|
||||||
|
tab: 9
|
||||||
|
}
|
||||||
|
export default class BufferSource{
|
||||||
|
constructor(bytesArr){
|
||||||
|
this.line = 1;
|
||||||
|
this.cols = 0;
|
||||||
|
this.buffer = bytesArr;
|
||||||
|
this.startIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
readCh() {
|
||||||
|
return String.fromCharCode(this.buffer[this.startIndex++]);
|
||||||
|
}
|
||||||
|
|
||||||
|
readChAt(index) {
|
||||||
|
return String.fromCharCode(this.buffer[this.startIndex+index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
readStr(n,from){
|
||||||
|
if(typeof from === "undefined") from = this.startIndex;
|
||||||
|
return this.buffer.slice(from, from + n).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
readUpto(stopStr) {
|
||||||
|
const inputLength = this.buffer.length;
|
||||||
|
const stopLength = stopStr.length;
|
||||||
|
const stopBuffer = Buffer.from(stopStr);
|
||||||
|
|
||||||
|
for (let i = this.startIndex; i < inputLength; i++) {
|
||||||
|
let match = true;
|
||||||
|
for (let j = 0; j < stopLength; j++) {
|
||||||
|
if (this.buffer[i + j] !== stopBuffer[j]) {
|
||||||
|
match = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
const result = this.buffer.slice(this.startIndex, i).toString();
|
||||||
|
this.startIndex = i + stopLength;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(`Unexpected end of source. Reading '${stopStr}'`);
|
||||||
|
}
|
||||||
|
|
||||||
|
readUptoCloseTag(stopStr) { //stopStr: "</tagname"
|
||||||
|
const inputLength = this.buffer.length;
|
||||||
|
const stopLength = stopStr.length;
|
||||||
|
const stopBuffer = Buffer.from(stopStr);
|
||||||
|
let stopIndex = 0;
|
||||||
|
//0: non-matching, 1: matching stop string, 2: matching closing
|
||||||
|
let match = 0;
|
||||||
|
|
||||||
|
for (let i = this.startIndex; i < inputLength; i++) {
|
||||||
|
if(match === 1){//initial part matched
|
||||||
|
if(stopIndex === 0) stopIndex = i;
|
||||||
|
if(this.buffer[i] === Constants.space || this.buffer[i] === Constants.tab) continue;
|
||||||
|
else if(this.buffer[i] === '>'){ //TODO: if it should be equivalent ASCII
|
||||||
|
match = 2;
|
||||||
|
//tag boundary found
|
||||||
|
// this.startIndex
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
match = 1;
|
||||||
|
for (let j = 0; j < stopLength; j++) {
|
||||||
|
if (this.buffer[i + j] !== stopBuffer[j]) {
|
||||||
|
match = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (match === 2) {//matched closing part
|
||||||
|
const result = this.buffer.slice(this.startIndex, stopIndex - 1 ).toString();
|
||||||
|
this.startIndex = i + 1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(`Unexpected end of source. Reading '${stopStr}'`);
|
||||||
|
}
|
||||||
|
|
||||||
|
readFromBuffer(n, shouldUpdate) {
|
||||||
|
let ch;
|
||||||
|
if (n === 1) {
|
||||||
|
ch = this.buffer[this.startIndex];
|
||||||
|
if (ch === 10) {
|
||||||
|
this.line++;
|
||||||
|
this.cols = 1;
|
||||||
|
} else {
|
||||||
|
this.cols++;
|
||||||
|
}
|
||||||
|
ch = String.fromCharCode(ch);
|
||||||
|
} else {
|
||||||
|
this.cols += n;
|
||||||
|
ch = this.buffer.slice(this.startIndex, this.startIndex + n).toString();
|
||||||
|
}
|
||||||
|
if (shouldUpdate) this.updateBuffer(n);
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateBufferBoundary(n = 1) { //n: number of characters read
|
||||||
|
this.startIndex += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
canRead(n){
|
||||||
|
n = n || this.startIndex;
|
||||||
|
return this.buffer.length - n + 1 > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
121
node_modules/fast-xml-parser/src/v6/inputSource/StringSource.js
generated
vendored
Normal file
121
node_modules/fast-xml-parser/src/v6/inputSource/StringSource.js
generated
vendored
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
const whiteSpaces = [" ", "\n", "\t"];
|
||||||
|
|
||||||
|
|
||||||
|
export default class StringSource{
|
||||||
|
constructor(str){
|
||||||
|
this.line = 1;
|
||||||
|
this.cols = 0;
|
||||||
|
this.buffer = str;
|
||||||
|
//a boundary pointer to indicate where from the buffer dat should be read
|
||||||
|
// data before this pointer can be deleted to free the memory
|
||||||
|
this.startIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
readCh() {
|
||||||
|
return this.buffer[this.startIndex++];
|
||||||
|
}
|
||||||
|
|
||||||
|
readChAt(index) {
|
||||||
|
return this.buffer[this.startIndex+index];
|
||||||
|
}
|
||||||
|
|
||||||
|
readStr(n,from){
|
||||||
|
if(typeof from === "undefined") from = this.startIndex;
|
||||||
|
return this.buffer.substring(from, from + n);
|
||||||
|
}
|
||||||
|
|
||||||
|
readUpto(stopStr) {
|
||||||
|
const inputLength = this.buffer.length;
|
||||||
|
const stopLength = stopStr.length;
|
||||||
|
|
||||||
|
for (let i = this.startIndex; i < inputLength; i++) {
|
||||||
|
let match = true;
|
||||||
|
for (let j = 0; j < stopLength; j++) {
|
||||||
|
if (this.buffer[i + j] !== stopStr[j]) {
|
||||||
|
match = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
const result = this.buffer.substring(this.startIndex, i);
|
||||||
|
this.startIndex = i + stopLength;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(`Unexpected end of source. Reading '${stopStr}'`);
|
||||||
|
}
|
||||||
|
|
||||||
|
readUptoCloseTag(stopStr) { //stopStr: "</tagname"
|
||||||
|
const inputLength = this.buffer.length;
|
||||||
|
const stopLength = stopStr.length;
|
||||||
|
let stopIndex = 0;
|
||||||
|
//0: non-matching, 1: matching stop string, 2: matching closing
|
||||||
|
let match = 0;
|
||||||
|
|
||||||
|
for (let i = this.startIndex; i < inputLength; i++) {
|
||||||
|
if(match === 1){//initial part matched
|
||||||
|
if(stopIndex === 0) stopIndex = i;
|
||||||
|
if(this.buffer[i] === ' ' || this.buffer[i] === '\t') continue;
|
||||||
|
else if(this.buffer[i] === '>'){
|
||||||
|
match = 2;
|
||||||
|
//tag boundary found
|
||||||
|
// this.startIndex
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
match = 1;
|
||||||
|
for (let j = 0; j < stopLength; j++) {
|
||||||
|
if (this.buffer[i + j] !== stopStr[j]) {
|
||||||
|
match = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (match === 2) {//matched closing part
|
||||||
|
const result = this.buffer.substring(this.startIndex, stopIndex - 1 );
|
||||||
|
this.startIndex = i + 1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(`Unexpected end of source. Reading '${stopStr}'`);
|
||||||
|
}
|
||||||
|
|
||||||
|
readFromBuffer(n, updateIndex){
|
||||||
|
let ch;
|
||||||
|
if(n===1){
|
||||||
|
ch = this.buffer[this.startIndex];
|
||||||
|
// if(ch === "\n") {
|
||||||
|
// this.line++;
|
||||||
|
// this.cols = 1;
|
||||||
|
// }else{
|
||||||
|
// this.cols++;
|
||||||
|
// }
|
||||||
|
}else{
|
||||||
|
ch = this.buffer.substring(this.startIndex, this.startIndex + n);
|
||||||
|
// if("".indexOf("\n") !== -1){
|
||||||
|
// //TODO: handle the scenario when there are multiple lines
|
||||||
|
// //TODO: col should be set to number of chars after last '\n'
|
||||||
|
// // this.cols = 1;
|
||||||
|
// }else{
|
||||||
|
// this.cols += n;
|
||||||
|
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
if(updateIndex) this.updateBufferBoundary(n);
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: rename to updateBufferReadIndex
|
||||||
|
|
||||||
|
updateBufferBoundary(n = 1) { //n: number of characters read
|
||||||
|
this.startIndex += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
canRead(n){
|
||||||
|
n = n || this.startIndex;
|
||||||
|
return this.buffer.length - n + 1 > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
105
node_modules/fast-xml-parser/src/v6/valueParsers/EntitiesParser.js
generated
vendored
Normal file
105
node_modules/fast-xml-parser/src/v6/valueParsers/EntitiesParser.js
generated
vendored
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
const ampEntity = { regex: /&(amp|#38|#x26);/g, val : "&"};
|
||||||
|
const htmlEntities = {
|
||||||
|
"space": { regex: /&(nbsp|#160);/g, val: " " },
|
||||||
|
// "lt" : { regex: /&(lt|#60);/g, val: "<" },
|
||||||
|
// "gt" : { regex: /&(gt|#62);/g, val: ">" },
|
||||||
|
// "amp" : { regex: /&(amp|#38);/g, val: "&" },
|
||||||
|
// "quot" : { regex: /&(quot|#34);/g, val: "\"" },
|
||||||
|
// "apos" : { regex: /&(apos|#39);/g, val: "'" },
|
||||||
|
"cent" : { regex: /&(cent|#162);/g, val: "¢" },
|
||||||
|
"pound" : { regex: /&(pound|#163);/g, val: "£" },
|
||||||
|
"yen" : { regex: /&(yen|#165);/g, val: "¥" },
|
||||||
|
"euro" : { regex: /&(euro|#8364);/g, val: "€" },
|
||||||
|
"copyright" : { regex: /&(copy|#169);/g, val: "©" },
|
||||||
|
"reg" : { regex: /&(reg|#174);/g, val: "®" },
|
||||||
|
"inr" : { regex: /&(inr|#8377);/g, val: "₹" },
|
||||||
|
"num_dec": { regex: /&#([0-9]{1,7});/g, val : (_, str) => String.fromCharCode(Number.parseInt(str, 10)) },
|
||||||
|
"num_hex": { regex: /&#x([0-9a-fA-F]{1,6});/g, val : (_, str) => String.fromCharCode(Number.parseInt(str, 16)) },
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class EntitiesParser{
|
||||||
|
constructor(replaceHtmlEntities) {
|
||||||
|
this.replaceHtmlEntities = replaceHtmlEntities;
|
||||||
|
this.docTypeEntities = {};
|
||||||
|
this.lastEntities = {
|
||||||
|
"apos" : { regex: /&(apos|#39|#x27);/g, val : "'"},
|
||||||
|
"gt" : { regex: /&(gt|#62|#x3E);/g, val : ">"},
|
||||||
|
"lt" : { regex: /&(lt|#60|#x3C);/g, val : "<"},
|
||||||
|
"quot" : { regex: /&(quot|#34|#x22);/g, val : "\""},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
addExternalEntities(externalEntities){
|
||||||
|
const entKeys = Object.keys(externalEntities);
|
||||||
|
for (let i = 0; i < entKeys.length; i++) {
|
||||||
|
const ent = entKeys[i];
|
||||||
|
this.addExternalEntity(ent,externalEntities[ent])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addExternalEntity(key,val){
|
||||||
|
validateEntityName(key);
|
||||||
|
if(val.indexOf("&") !== -1) {
|
||||||
|
reportWarning(`Entity ${key} is not added as '&' is found in value;`)
|
||||||
|
return;
|
||||||
|
}else{
|
||||||
|
this.lastEntities[ent] = {
|
||||||
|
regex: new RegExp("&"+key+";","g"),
|
||||||
|
val : val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addDocTypeEntities(entities){
|
||||||
|
const entKeys = Object.keys(entities);
|
||||||
|
for (let i = 0; i < entKeys.length; i++) {
|
||||||
|
const ent = entKeys[i];
|
||||||
|
this.docTypeEntities[ent] = {
|
||||||
|
regex: new RegExp("&"+ent+";","g"),
|
||||||
|
val : entities[ent]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parse(val){
|
||||||
|
return this.replaceEntitiesValue(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Replace DOCTYPE entities
|
||||||
|
* 2. Replace external entities
|
||||||
|
* 3. Replace HTML entities if asked
|
||||||
|
* @param {string} val
|
||||||
|
*/
|
||||||
|
replaceEntitiesValue(val){
|
||||||
|
if(typeof val === "string" && val.length > 0){
|
||||||
|
for(let entityName in this.docTypeEntities){
|
||||||
|
const entity = this.docTypeEntities[entityName];
|
||||||
|
val = val.replace( entity.regx, entity.val);
|
||||||
|
}
|
||||||
|
for(let entityName in this.lastEntities){
|
||||||
|
const entity = this.lastEntities[entityName];
|
||||||
|
val = val.replace( entity.regex, entity.val);
|
||||||
|
}
|
||||||
|
if(this.replaceHtmlEntities){
|
||||||
|
for(let entityName in htmlEntities){
|
||||||
|
const entity = htmlEntities[entityName];
|
||||||
|
val = val.replace( entity.regex, entity.val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val = val.replace( ampEntity.regex, ampEntity.val);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//an entity name should not contains special characters that may be used in regex
|
||||||
|
//Eg !?\\\/[]$%{}^&*()<>
|
||||||
|
const specialChar = "!?\\\/[]$%{}^&*()<>|+";
|
||||||
|
|
||||||
|
function validateEntityName(name){
|
||||||
|
for (let i = 0; i < specialChar.length; i++) {
|
||||||
|
const ch = specialChar[i];
|
||||||
|
if(name.indexOf(ch) !== -1) throw new Error(`Invalid character ${ch} in entity name`);
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
22
node_modules/fast-xml-parser/src/v6/valueParsers/booleanParser.js
generated
vendored
Normal file
22
node_modules/fast-xml-parser/src/v6/valueParsers/booleanParser.js
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
export default class boolParser{
|
||||||
|
constructor(trueList, falseList){
|
||||||
|
if(trueList)
|
||||||
|
this.trueList = trueList;
|
||||||
|
else
|
||||||
|
this.trueList = ["true"];
|
||||||
|
|
||||||
|
if(falseList)
|
||||||
|
this.falseList = falseList;
|
||||||
|
else
|
||||||
|
this.falseList = ["false"];
|
||||||
|
}
|
||||||
|
parse(val){
|
||||||
|
if (typeof val === 'string') {
|
||||||
|
//TODO: performance: don't convert
|
||||||
|
const temp = val.toLowerCase();
|
||||||
|
if(this.trueList.indexOf(temp) !== -1) return true;
|
||||||
|
else if(this.falseList.indexOf(temp) !== -1 ) return false;
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
19
node_modules/fast-xml-parser/src/v6/valueParsers/booleanParserExt.js
generated
vendored
Normal file
19
node_modules/fast-xml-parser/src/v6/valueParsers/booleanParserExt.js
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
export default function boolParserExt(val){
|
||||||
|
if(isArray(val)){
|
||||||
|
for (let i = 0; i < val.length; i++) {
|
||||||
|
val[i] = parse(val[i])
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
val = parse(val)
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse(val){
|
||||||
|
if (typeof val === 'string') {
|
||||||
|
const temp = val.toLowerCase();
|
||||||
|
if(temp === 'true' || temp ==="yes" || temp==="1") return true;
|
||||||
|
else if(temp === 'false' || temp ==="no" || temp==="0") return false;
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
38
node_modules/fast-xml-parser/src/v6/valueParsers/currency.js
generated
vendored
Normal file
38
node_modules/fast-xml-parser/src/v6/valueParsers/currency.js
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
const defaultOptions = {
|
||||||
|
maxLength: 200,
|
||||||
|
// locale: "en-IN"
|
||||||
|
}
|
||||||
|
const localeMap = {
|
||||||
|
"$":"en-US",
|
||||||
|
"€":"de-DE",
|
||||||
|
"£":"en-GB",
|
||||||
|
"¥":"ja-JP",
|
||||||
|
"₹":"en-IN",
|
||||||
|
}
|
||||||
|
const sign = "(?:-|\+)?";
|
||||||
|
const digitsAndSeparator = "(?:\d+|\d{1,3}(?:,\d{3})+)";
|
||||||
|
const decimalPart = "(?:\.\d{1,2})?";
|
||||||
|
const symbol = "(?:\$|€|¥|₹)?";
|
||||||
|
|
||||||
|
const currencyCheckRegex = /^\s*(?:-|\+)?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d{1,2})?\s*(?:\$|€|¥|₹)?\s*$/u;
|
||||||
|
|
||||||
|
export default class CurrencyParser{
|
||||||
|
constructor(options){
|
||||||
|
this.options = options || defaultOptions;
|
||||||
|
}
|
||||||
|
parse(val){
|
||||||
|
if (typeof val === 'string' && val.length <= this.options.maxLength) {
|
||||||
|
if(val.indexOf(",,") !== -1 && val.indexOf(".." !== -1)){
|
||||||
|
const match = val.match(currencyCheckRegex);
|
||||||
|
if(match){
|
||||||
|
const locale = this.options.locale || localeMap[match[2]||match[5]||"₹"];
|
||||||
|
const formatter = new Intl.NumberFormat(locale)
|
||||||
|
val = val.replace(/[^0-9,.]/g, '').trim();
|
||||||
|
val = Number(val.replace(formatter.format(1000)[1], ''));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CurrencyParser.defaultOptions = defaultOptions;
|
||||||
13
node_modules/fast-xml-parser/src/v6/valueParsers/join.js
generated
vendored
Normal file
13
node_modules/fast-xml-parser/src/v6/valueParsers/join.js
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {array} val
|
||||||
|
* @param {string} by
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export default function join(val, by=" "){
|
||||||
|
if(isArray(val)){
|
||||||
|
val.join(by)
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
14
node_modules/fast-xml-parser/src/v6/valueParsers/number.js
generated
vendored
Normal file
14
node_modules/fast-xml-parser/src/v6/valueParsers/number.js
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import toNumber from "strnum";
|
||||||
|
|
||||||
|
|
||||||
|
export default class numParser{
|
||||||
|
constructor(options){
|
||||||
|
this.options = options;
|
||||||
|
}
|
||||||
|
parse(val){
|
||||||
|
if (typeof val === 'string') {
|
||||||
|
val = toNumber(val,this.options);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
6
node_modules/fast-xml-parser/src/v6/valueParsers/trim.js
generated
vendored
Normal file
6
node_modules/fast-xml-parser/src/v6/valueParsers/trim.js
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export default class trimmer{
|
||||||
|
parse(val){
|
||||||
|
if(typeof val === "string") return val.trim();
|
||||||
|
else return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
425
node_modules/fast-xml-parser/src/validator.js
generated
vendored
Normal file
425
node_modules/fast-xml-parser/src/validator.js
generated
vendored
Normal file
@ -0,0 +1,425 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const util = require('./util');
|
||||||
|
|
||||||
|
const defaultOptions = {
|
||||||
|
allowBooleanAttributes: false, //A tag can have attributes without any value
|
||||||
|
unpairedTags: []
|
||||||
|
};
|
||||||
|
|
||||||
|
//const tagsPattern = new RegExp("<\\/?([\\w:\\-_\.]+)\\s*\/?>","g");
|
||||||
|
exports.validate = function (xmlData, options) {
|
||||||
|
options = Object.assign({}, defaultOptions, options);
|
||||||
|
|
||||||
|
//xmlData = xmlData.replace(/(\r\n|\n|\r)/gm,"");//make it single line
|
||||||
|
//xmlData = xmlData.replace(/(^\s*<\?xml.*?\?>)/g,"");//Remove XML starting tag
|
||||||
|
//xmlData = xmlData.replace(/(<!DOCTYPE[\s\w\"\.\/\-\:]+(\[.*\])*\s*>)/g,"");//Remove DOCTYPE
|
||||||
|
const tags = [];
|
||||||
|
let tagFound = false;
|
||||||
|
|
||||||
|
//indicates that the root tag has been closed (aka. depth 0 has been reached)
|
||||||
|
let reachedRoot = false;
|
||||||
|
|
||||||
|
if (xmlData[0] === '\ufeff') {
|
||||||
|
// check for byte order mark (BOM)
|
||||||
|
xmlData = xmlData.substr(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < xmlData.length; i++) {
|
||||||
|
|
||||||
|
if (xmlData[i] === '<' && xmlData[i+1] === '?') {
|
||||||
|
i+=2;
|
||||||
|
i = readPI(xmlData,i);
|
||||||
|
if (i.err) return i;
|
||||||
|
}else if (xmlData[i] === '<') {
|
||||||
|
//starting of tag
|
||||||
|
//read until you reach to '>' avoiding any '>' in attribute value
|
||||||
|
let tagStartPos = i;
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (xmlData[i] === '!') {
|
||||||
|
i = readCommentAndCDATA(xmlData, i);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
let closingTag = false;
|
||||||
|
if (xmlData[i] === '/') {
|
||||||
|
//closing tag
|
||||||
|
closingTag = true;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
//read tagname
|
||||||
|
let tagName = '';
|
||||||
|
for (; i < xmlData.length &&
|
||||||
|
xmlData[i] !== '>' &&
|
||||||
|
xmlData[i] !== ' ' &&
|
||||||
|
xmlData[i] !== '\t' &&
|
||||||
|
xmlData[i] !== '\n' &&
|
||||||
|
xmlData[i] !== '\r'; i++
|
||||||
|
) {
|
||||||
|
tagName += xmlData[i];
|
||||||
|
}
|
||||||
|
tagName = tagName.trim();
|
||||||
|
//console.log(tagName);
|
||||||
|
|
||||||
|
if (tagName[tagName.length - 1] === '/') {
|
||||||
|
//self closing tag without attributes
|
||||||
|
tagName = tagName.substring(0, tagName.length - 1);
|
||||||
|
//continue;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
if (!validateTagName(tagName)) {
|
||||||
|
let msg;
|
||||||
|
if (tagName.trim().length === 0) {
|
||||||
|
msg = "Invalid space after '<'.";
|
||||||
|
} else {
|
||||||
|
msg = "Tag '"+tagName+"' is an invalid name.";
|
||||||
|
}
|
||||||
|
return getErrorObject('InvalidTag', msg, getLineNumberForPosition(xmlData, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = readAttributeStr(xmlData, i);
|
||||||
|
if (result === false) {
|
||||||
|
return getErrorObject('InvalidAttr', "Attributes for '"+tagName+"' have open quote.", getLineNumberForPosition(xmlData, i));
|
||||||
|
}
|
||||||
|
let attrStr = result.value;
|
||||||
|
i = result.index;
|
||||||
|
|
||||||
|
if (attrStr[attrStr.length - 1] === '/') {
|
||||||
|
//self closing tag
|
||||||
|
const attrStrStart = i - attrStr.length;
|
||||||
|
attrStr = attrStr.substring(0, attrStr.length - 1);
|
||||||
|
const isValid = validateAttributeString(attrStr, options);
|
||||||
|
if (isValid === true) {
|
||||||
|
tagFound = true;
|
||||||
|
//continue; //text may presents after self closing tag
|
||||||
|
} else {
|
||||||
|
//the result from the nested function returns the position of the error within the attribute
|
||||||
|
//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
|
||||||
|
//this gives us the absolute index in the entire xml, which we can use to find the line at last
|
||||||
|
return getErrorObject(isValid.err.code, isValid.err.msg, getLineNumberForPosition(xmlData, attrStrStart + isValid.err.line));
|
||||||
|
}
|
||||||
|
} else if (closingTag) {
|
||||||
|
if (!result.tagClosed) {
|
||||||
|
return getErrorObject('InvalidTag', "Closing tag '"+tagName+"' doesn't have proper closing.", getLineNumberForPosition(xmlData, i));
|
||||||
|
} else if (attrStr.trim().length > 0) {
|
||||||
|
return getErrorObject('InvalidTag', "Closing tag '"+tagName+"' can't have attributes or invalid starting.", getLineNumberForPosition(xmlData, tagStartPos));
|
||||||
|
} else if (tags.length === 0) {
|
||||||
|
return getErrorObject('InvalidTag', "Closing tag '"+tagName+"' has not been opened.", getLineNumberForPosition(xmlData, tagStartPos));
|
||||||
|
} else {
|
||||||
|
const otg = tags.pop();
|
||||||
|
if (tagName !== otg.tagName) {
|
||||||
|
let openPos = getLineNumberForPosition(xmlData, otg.tagStartPos);
|
||||||
|
return getErrorObject('InvalidTag',
|
||||||
|
"Expected closing tag '"+otg.tagName+"' (opened in line "+openPos.line+", col "+openPos.col+") instead of closing tag '"+tagName+"'.",
|
||||||
|
getLineNumberForPosition(xmlData, tagStartPos));
|
||||||
|
}
|
||||||
|
|
||||||
|
//when there are no more tags, we reached the root level.
|
||||||
|
if (tags.length == 0) {
|
||||||
|
reachedRoot = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const isValid = validateAttributeString(attrStr, options);
|
||||||
|
if (isValid !== true) {
|
||||||
|
//the result from the nested function returns the position of the error within the attribute
|
||||||
|
//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
|
||||||
|
//this gives us the absolute index in the entire xml, which we can use to find the line at last
|
||||||
|
return getErrorObject(isValid.err.code, isValid.err.msg, getLineNumberForPosition(xmlData, i - attrStr.length + isValid.err.line));
|
||||||
|
}
|
||||||
|
|
||||||
|
//if the root level has been reached before ...
|
||||||
|
if (reachedRoot === true) {
|
||||||
|
return getErrorObject('InvalidXml', 'Multiple possible root nodes found.', getLineNumberForPosition(xmlData, i));
|
||||||
|
} else if(options.unpairedTags.indexOf(tagName) !== -1){
|
||||||
|
//don't push into stack
|
||||||
|
} else {
|
||||||
|
tags.push({tagName, tagStartPos});
|
||||||
|
}
|
||||||
|
tagFound = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//skip tag text value
|
||||||
|
//It may include comments and CDATA value
|
||||||
|
for (i++; i < xmlData.length; i++) {
|
||||||
|
if (xmlData[i] === '<') {
|
||||||
|
if (xmlData[i + 1] === '!') {
|
||||||
|
//comment or CADATA
|
||||||
|
i++;
|
||||||
|
i = readCommentAndCDATA(xmlData, i);
|
||||||
|
continue;
|
||||||
|
} else if (xmlData[i+1] === '?') {
|
||||||
|
i = readPI(xmlData, ++i);
|
||||||
|
if (i.err) return i;
|
||||||
|
} else{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (xmlData[i] === '&') {
|
||||||
|
const afterAmp = validateAmpersand(xmlData, i);
|
||||||
|
if (afterAmp == -1)
|
||||||
|
return getErrorObject('InvalidChar', "char '&' is not expected.", getLineNumberForPosition(xmlData, i));
|
||||||
|
i = afterAmp;
|
||||||
|
}else{
|
||||||
|
if (reachedRoot === true && !isWhiteSpace(xmlData[i])) {
|
||||||
|
return getErrorObject('InvalidXml', "Extra text at the end", getLineNumberForPosition(xmlData, i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} //end of reading tag text value
|
||||||
|
if (xmlData[i] === '<') {
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ( isWhiteSpace(xmlData[i])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return getErrorObject('InvalidChar', "char '"+xmlData[i]+"' is not expected.", getLineNumberForPosition(xmlData, i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tagFound) {
|
||||||
|
return getErrorObject('InvalidXml', 'Start tag expected.', 1);
|
||||||
|
}else if (tags.length == 1) {
|
||||||
|
return getErrorObject('InvalidTag', "Unclosed tag '"+tags[0].tagName+"'.", getLineNumberForPosition(xmlData, tags[0].tagStartPos));
|
||||||
|
}else if (tags.length > 0) {
|
||||||
|
return getErrorObject('InvalidXml', "Invalid '"+
|
||||||
|
JSON.stringify(tags.map(t => t.tagName), null, 4).replace(/\r?\n/g, '')+
|
||||||
|
"' found.", {line: 1, col: 1});
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
function isWhiteSpace(char){
|
||||||
|
return char === ' ' || char === '\t' || char === '\n' || char === '\r';
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Read Processing insstructions and skip
|
||||||
|
* @param {*} xmlData
|
||||||
|
* @param {*} i
|
||||||
|
*/
|
||||||
|
function readPI(xmlData, i) {
|
||||||
|
const start = i;
|
||||||
|
for (; i < xmlData.length; i++) {
|
||||||
|
if (xmlData[i] == '?' || xmlData[i] == ' ') {
|
||||||
|
//tagname
|
||||||
|
const tagname = xmlData.substr(start, i - start);
|
||||||
|
if (i > 5 && tagname === 'xml') {
|
||||||
|
return getErrorObject('InvalidXml', 'XML declaration allowed only at the start of the document.', getLineNumberForPosition(xmlData, i));
|
||||||
|
} else if (xmlData[i] == '?' && xmlData[i + 1] == '>') {
|
||||||
|
//check if valid attribut string
|
||||||
|
i++;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
function readCommentAndCDATA(xmlData, i) {
|
||||||
|
if (xmlData.length > i + 5 && xmlData[i + 1] === '-' && xmlData[i + 2] === '-') {
|
||||||
|
//comment
|
||||||
|
for (i += 3; i < xmlData.length; i++) {
|
||||||
|
if (xmlData[i] === '-' && xmlData[i + 1] === '-' && xmlData[i + 2] === '>') {
|
||||||
|
i += 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
xmlData.length > i + 8 &&
|
||||||
|
xmlData[i + 1] === 'D' &&
|
||||||
|
xmlData[i + 2] === 'O' &&
|
||||||
|
xmlData[i + 3] === 'C' &&
|
||||||
|
xmlData[i + 4] === 'T' &&
|
||||||
|
xmlData[i + 5] === 'Y' &&
|
||||||
|
xmlData[i + 6] === 'P' &&
|
||||||
|
xmlData[i + 7] === 'E'
|
||||||
|
) {
|
||||||
|
let angleBracketsCount = 1;
|
||||||
|
for (i += 8; i < xmlData.length; i++) {
|
||||||
|
if (xmlData[i] === '<') {
|
||||||
|
angleBracketsCount++;
|
||||||
|
} else if (xmlData[i] === '>') {
|
||||||
|
angleBracketsCount--;
|
||||||
|
if (angleBracketsCount === 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
xmlData.length > i + 9 &&
|
||||||
|
xmlData[i + 1] === '[' &&
|
||||||
|
xmlData[i + 2] === 'C' &&
|
||||||
|
xmlData[i + 3] === 'D' &&
|
||||||
|
xmlData[i + 4] === 'A' &&
|
||||||
|
xmlData[i + 5] === 'T' &&
|
||||||
|
xmlData[i + 6] === 'A' &&
|
||||||
|
xmlData[i + 7] === '['
|
||||||
|
) {
|
||||||
|
for (i += 8; i < xmlData.length; i++) {
|
||||||
|
if (xmlData[i] === ']' && xmlData[i + 1] === ']' && xmlData[i + 2] === '>') {
|
||||||
|
i += 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
const doubleQuote = '"';
|
||||||
|
const singleQuote = "'";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keep reading xmlData until '<' is found outside the attribute value.
|
||||||
|
* @param {string} xmlData
|
||||||
|
* @param {number} i
|
||||||
|
*/
|
||||||
|
function readAttributeStr(xmlData, i) {
|
||||||
|
let attrStr = '';
|
||||||
|
let startChar = '';
|
||||||
|
let tagClosed = false;
|
||||||
|
for (; i < xmlData.length; i++) {
|
||||||
|
if (xmlData[i] === doubleQuote || xmlData[i] === singleQuote) {
|
||||||
|
if (startChar === '') {
|
||||||
|
startChar = xmlData[i];
|
||||||
|
} else if (startChar !== xmlData[i]) {
|
||||||
|
//if vaue is enclosed with double quote then single quotes are allowed inside the value and vice versa
|
||||||
|
} else {
|
||||||
|
startChar = '';
|
||||||
|
}
|
||||||
|
} else if (xmlData[i] === '>') {
|
||||||
|
if (startChar === '') {
|
||||||
|
tagClosed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
attrStr += xmlData[i];
|
||||||
|
}
|
||||||
|
if (startChar !== '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
value: attrStr,
|
||||||
|
index: i,
|
||||||
|
tagClosed: tagClosed
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select all the attributes whether valid or invalid.
|
||||||
|
*/
|
||||||
|
const validAttrStrRegxp = new RegExp('(\\s*)([^\\s=]+)(\\s*=)?(\\s*([\'"])(([\\s\\S])*?)\\5)?', 'g');
|
||||||
|
|
||||||
|
//attr, ="sd", a="amit's", a="sd"b="saf", ab cd=""
|
||||||
|
|
||||||
|
function validateAttributeString(attrStr, options) {
|
||||||
|
//console.log("start:"+attrStr+":end");
|
||||||
|
|
||||||
|
//if(attrStr.trim().length === 0) return true; //empty string
|
||||||
|
|
||||||
|
const matches = util.getAllMatches(attrStr, validAttrStrRegxp);
|
||||||
|
const attrNames = {};
|
||||||
|
|
||||||
|
for (let i = 0; i < matches.length; i++) {
|
||||||
|
if (matches[i][1].length === 0) {
|
||||||
|
//nospace before attribute name: a="sd"b="saf"
|
||||||
|
return getErrorObject('InvalidAttr', "Attribute '"+matches[i][2]+"' has no space in starting.", getPositionFromMatch(matches[i]))
|
||||||
|
} else if (matches[i][3] !== undefined && matches[i][4] === undefined) {
|
||||||
|
return getErrorObject('InvalidAttr', "Attribute '"+matches[i][2]+"' is without value.", getPositionFromMatch(matches[i]));
|
||||||
|
} else if (matches[i][3] === undefined && !options.allowBooleanAttributes) {
|
||||||
|
//independent attribute: ab
|
||||||
|
return getErrorObject('InvalidAttr', "boolean attribute '"+matches[i][2]+"' is not allowed.", getPositionFromMatch(matches[i]));
|
||||||
|
}
|
||||||
|
/* else if(matches[i][6] === undefined){//attribute without value: ab=
|
||||||
|
return { err: { code:"InvalidAttr",msg:"attribute " + matches[i][2] + " has no value assigned."}};
|
||||||
|
} */
|
||||||
|
const attrName = matches[i][2];
|
||||||
|
if (!validateAttrName(attrName)) {
|
||||||
|
return getErrorObject('InvalidAttr', "Attribute '"+attrName+"' is an invalid name.", getPositionFromMatch(matches[i]));
|
||||||
|
}
|
||||||
|
if (!attrNames.hasOwnProperty(attrName)) {
|
||||||
|
//check for duplicate attribute.
|
||||||
|
attrNames[attrName] = 1;
|
||||||
|
} else {
|
||||||
|
return getErrorObject('InvalidAttr', "Attribute '"+attrName+"' is repeated.", getPositionFromMatch(matches[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateNumberAmpersand(xmlData, i) {
|
||||||
|
let re = /\d/;
|
||||||
|
if (xmlData[i] === 'x') {
|
||||||
|
i++;
|
||||||
|
re = /[\da-fA-F]/;
|
||||||
|
}
|
||||||
|
for (; i < xmlData.length; i++) {
|
||||||
|
if (xmlData[i] === ';')
|
||||||
|
return i;
|
||||||
|
if (!xmlData[i].match(re))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateAmpersand(xmlData, i) {
|
||||||
|
// https://www.w3.org/TR/xml/#dt-charref
|
||||||
|
i++;
|
||||||
|
if (xmlData[i] === ';')
|
||||||
|
return -1;
|
||||||
|
if (xmlData[i] === '#') {
|
||||||
|
i++;
|
||||||
|
return validateNumberAmpersand(xmlData, i);
|
||||||
|
}
|
||||||
|
let count = 0;
|
||||||
|
for (; i < xmlData.length; i++, count++) {
|
||||||
|
if (xmlData[i].match(/\w/) && count < 20)
|
||||||
|
continue;
|
||||||
|
if (xmlData[i] === ';')
|
||||||
|
break;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getErrorObject(code, message, lineNumber) {
|
||||||
|
return {
|
||||||
|
err: {
|
||||||
|
code: code,
|
||||||
|
msg: message,
|
||||||
|
line: lineNumber.line || lineNumber,
|
||||||
|
col: lineNumber.col,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateAttrName(attrName) {
|
||||||
|
return util.isName(attrName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// const startsWithXML = /^xml/i;
|
||||||
|
|
||||||
|
function validateTagName(tagname) {
|
||||||
|
return util.isName(tagname) /* && !tagname.match(startsWithXML) */;
|
||||||
|
}
|
||||||
|
|
||||||
|
//this function returns the line number for the character at the given index
|
||||||
|
function getLineNumberForPosition(xmlData, index) {
|
||||||
|
const lines = xmlData.substring(0, index).split(/\r?\n/);
|
||||||
|
return {
|
||||||
|
line: lines.length,
|
||||||
|
|
||||||
|
// column number is last line's length + 1, because column numbering starts at 1:
|
||||||
|
col: lines[lines.length - 1].length + 1
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//this function returns the position of the first character of match within attrStr
|
||||||
|
function getPositionFromMatch(match) {
|
||||||
|
return match.startIndex + match[1].length;
|
||||||
|
}
|
||||||
286
node_modules/fast-xml-parser/src/xmlbuilder/json2xml.js
generated
vendored
Normal file
286
node_modules/fast-xml-parser/src/xmlbuilder/json2xml.js
generated
vendored
Normal file
@ -0,0 +1,286 @@
|
|||||||
|
'use strict';
|
||||||
|
//parse Empty Node as self closing node
|
||||||
|
const buildFromOrderedJs = require('./orderedJs2Xml');
|
||||||
|
const getIgnoreAttributesFn = require('../ignoreAttributes')
|
||||||
|
|
||||||
|
const defaultOptions = {
|
||||||
|
attributeNamePrefix: '@_',
|
||||||
|
attributesGroupName: false,
|
||||||
|
textNodeName: '#text',
|
||||||
|
ignoreAttributes: true,
|
||||||
|
cdataPropName: false,
|
||||||
|
format: false,
|
||||||
|
indentBy: ' ',
|
||||||
|
suppressEmptyNode: false,
|
||||||
|
suppressUnpairedNode: true,
|
||||||
|
suppressBooleanAttributes: true,
|
||||||
|
tagValueProcessor: function(key, a) {
|
||||||
|
return a;
|
||||||
|
},
|
||||||
|
attributeValueProcessor: function(attrName, a) {
|
||||||
|
return a;
|
||||||
|
},
|
||||||
|
preserveOrder: false,
|
||||||
|
commentPropName: false,
|
||||||
|
unpairedTags: [],
|
||||||
|
entities: [
|
||||||
|
{ regex: new RegExp("&", "g"), val: "&" },//it must be on top
|
||||||
|
{ regex: new RegExp(">", "g"), val: ">" },
|
||||||
|
{ regex: new RegExp("<", "g"), val: "<" },
|
||||||
|
{ regex: new RegExp("\'", "g"), val: "'" },
|
||||||
|
{ regex: new RegExp("\"", "g"), val: """ }
|
||||||
|
],
|
||||||
|
processEntities: true,
|
||||||
|
stopNodes: [],
|
||||||
|
// transformTagName: false,
|
||||||
|
// transformAttributeName: false,
|
||||||
|
oneListGroup: false
|
||||||
|
};
|
||||||
|
|
||||||
|
function Builder(options) {
|
||||||
|
this.options = Object.assign({}, defaultOptions, options);
|
||||||
|
if (this.options.ignoreAttributes === true || this.options.attributesGroupName) {
|
||||||
|
this.isAttribute = function(/*a*/) {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
this.ignoreAttributesFn = getIgnoreAttributesFn(this.options.ignoreAttributes)
|
||||||
|
this.attrPrefixLen = this.options.attributeNamePrefix.length;
|
||||||
|
this.isAttribute = isAttribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.processTextOrObjNode = processTextOrObjNode
|
||||||
|
|
||||||
|
if (this.options.format) {
|
||||||
|
this.indentate = indentate;
|
||||||
|
this.tagEndChar = '>\n';
|
||||||
|
this.newLine = '\n';
|
||||||
|
} else {
|
||||||
|
this.indentate = function() {
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
this.tagEndChar = '>';
|
||||||
|
this.newLine = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Builder.prototype.build = function(jObj) {
|
||||||
|
if(this.options.preserveOrder){
|
||||||
|
return buildFromOrderedJs(jObj, this.options);
|
||||||
|
}else {
|
||||||
|
if(Array.isArray(jObj) && this.options.arrayNodeName && this.options.arrayNodeName.length > 1){
|
||||||
|
jObj = {
|
||||||
|
[this.options.arrayNodeName] : jObj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.j2x(jObj, 0, []).val;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Builder.prototype.j2x = function(jObj, level, ajPath) {
|
||||||
|
let attrStr = '';
|
||||||
|
let val = '';
|
||||||
|
const jPath = ajPath.join('.')
|
||||||
|
for (let key in jObj) {
|
||||||
|
if(!Object.prototype.hasOwnProperty.call(jObj, key)) continue;
|
||||||
|
if (typeof jObj[key] === 'undefined') {
|
||||||
|
// supress undefined node only if it is not an attribute
|
||||||
|
if (this.isAttribute(key)) {
|
||||||
|
val += '';
|
||||||
|
}
|
||||||
|
} else if (jObj[key] === null) {
|
||||||
|
// null attribute should be ignored by the attribute list, but should not cause the tag closing
|
||||||
|
if (this.isAttribute(key)) {
|
||||||
|
val += '';
|
||||||
|
} else if (key === this.options.cdataPropName) {
|
||||||
|
val += '';
|
||||||
|
} else if (key[0] === '?') {
|
||||||
|
val += this.indentate(level) + '<' + key + '?' + this.tagEndChar;
|
||||||
|
} else {
|
||||||
|
val += this.indentate(level) + '<' + key + '/' + this.tagEndChar;
|
||||||
|
}
|
||||||
|
// val += this.indentate(level) + '<' + key + '/' + this.tagEndChar;
|
||||||
|
} else if (jObj[key] instanceof Date) {
|
||||||
|
val += this.buildTextValNode(jObj[key], key, '', level);
|
||||||
|
} else if (typeof jObj[key] !== 'object') {
|
||||||
|
//premitive type
|
||||||
|
const attr = this.isAttribute(key);
|
||||||
|
if (attr && !this.ignoreAttributesFn(attr, jPath)) {
|
||||||
|
attrStr += this.buildAttrPairStr(attr, '' + jObj[key]);
|
||||||
|
} else if (!attr) {
|
||||||
|
//tag value
|
||||||
|
if (key === this.options.textNodeName) {
|
||||||
|
let newval = this.options.tagValueProcessor(key, '' + jObj[key]);
|
||||||
|
val += this.replaceEntitiesValue(newval);
|
||||||
|
} else {
|
||||||
|
val += this.buildTextValNode(jObj[key], key, '', level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (Array.isArray(jObj[key])) {
|
||||||
|
//repeated nodes
|
||||||
|
const arrLen = jObj[key].length;
|
||||||
|
let listTagVal = "";
|
||||||
|
let listTagAttr = "";
|
||||||
|
for (let j = 0; j < arrLen; j++) {
|
||||||
|
const item = jObj[key][j];
|
||||||
|
if (typeof item === 'undefined') {
|
||||||
|
// supress undefined node
|
||||||
|
} else if (item === null) {
|
||||||
|
if(key[0] === "?") val += this.indentate(level) + '<' + key + '?' + this.tagEndChar;
|
||||||
|
else val += this.indentate(level) + '<' + key + '/' + this.tagEndChar;
|
||||||
|
// val += this.indentate(level) + '<' + key + '/' + this.tagEndChar;
|
||||||
|
} else if (typeof item === 'object') {
|
||||||
|
if(this.options.oneListGroup){
|
||||||
|
const result = this.j2x(item, level + 1, ajPath.concat(key));
|
||||||
|
listTagVal += result.val;
|
||||||
|
if (this.options.attributesGroupName && item.hasOwnProperty(this.options.attributesGroupName)) {
|
||||||
|
listTagAttr += result.attrStr
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
listTagVal += this.processTextOrObjNode(item, key, level, ajPath)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.options.oneListGroup) {
|
||||||
|
let textValue = this.options.tagValueProcessor(key, item);
|
||||||
|
textValue = this.replaceEntitiesValue(textValue);
|
||||||
|
listTagVal += textValue;
|
||||||
|
} else {
|
||||||
|
listTagVal += this.buildTextValNode(item, key, '', level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(this.options.oneListGroup){
|
||||||
|
listTagVal = this.buildObjectNode(listTagVal, key, listTagAttr, level);
|
||||||
|
}
|
||||||
|
val += listTagVal;
|
||||||
|
} else {
|
||||||
|
//nested node
|
||||||
|
if (this.options.attributesGroupName && key === this.options.attributesGroupName) {
|
||||||
|
const Ks = Object.keys(jObj[key]);
|
||||||
|
const L = Ks.length;
|
||||||
|
for (let j = 0; j < L; j++) {
|
||||||
|
attrStr += this.buildAttrPairStr(Ks[j], '' + jObj[key][Ks[j]]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val += this.processTextOrObjNode(jObj[key], key, level, ajPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {attrStr: attrStr, val: val};
|
||||||
|
};
|
||||||
|
|
||||||
|
Builder.prototype.buildAttrPairStr = function(attrName, val){
|
||||||
|
val = this.options.attributeValueProcessor(attrName, '' + val);
|
||||||
|
val = this.replaceEntitiesValue(val);
|
||||||
|
if (this.options.suppressBooleanAttributes && val === "true") {
|
||||||
|
return ' ' + attrName;
|
||||||
|
} else return ' ' + attrName + '="' + val + '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
function processTextOrObjNode (object, key, level, ajPath) {
|
||||||
|
const result = this.j2x(object, level + 1, ajPath.concat(key));
|
||||||
|
if (object[this.options.textNodeName] !== undefined && Object.keys(object).length === 1) {
|
||||||
|
return this.buildTextValNode(object[this.options.textNodeName], key, result.attrStr, level);
|
||||||
|
} else {
|
||||||
|
return this.buildObjectNode(result.val, key, result.attrStr, level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Builder.prototype.buildObjectNode = function(val, key, attrStr, level) {
|
||||||
|
if(val === ""){
|
||||||
|
if(key[0] === "?") return this.indentate(level) + '<' + key + attrStr+ '?' + this.tagEndChar;
|
||||||
|
else {
|
||||||
|
return this.indentate(level) + '<' + key + attrStr + this.closeTag(key) + this.tagEndChar;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
|
||||||
|
let tagEndExp = '</' + key + this.tagEndChar;
|
||||||
|
let piClosingChar = "";
|
||||||
|
|
||||||
|
if(key[0] === "?") {
|
||||||
|
piClosingChar = "?";
|
||||||
|
tagEndExp = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// attrStr is an empty string in case the attribute came as undefined or null
|
||||||
|
if ((attrStr || attrStr === '') && val.indexOf('<') === -1) {
|
||||||
|
return ( this.indentate(level) + '<' + key + attrStr + piClosingChar + '>' + val + tagEndExp );
|
||||||
|
} else if (this.options.commentPropName !== false && key === this.options.commentPropName && piClosingChar.length === 0) {
|
||||||
|
return this.indentate(level) + `<!--${val}-->` + this.newLine;
|
||||||
|
}else {
|
||||||
|
return (
|
||||||
|
this.indentate(level) + '<' + key + attrStr + piClosingChar + this.tagEndChar +
|
||||||
|
val +
|
||||||
|
this.indentate(level) + tagEndExp );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Builder.prototype.closeTag = function(key){
|
||||||
|
let closeTag = "";
|
||||||
|
if(this.options.unpairedTags.indexOf(key) !== -1){ //unpaired
|
||||||
|
if(!this.options.suppressUnpairedNode) closeTag = "/"
|
||||||
|
}else if(this.options.suppressEmptyNode){ //empty
|
||||||
|
closeTag = "/";
|
||||||
|
}else{
|
||||||
|
closeTag = `></${key}`
|
||||||
|
}
|
||||||
|
return closeTag;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildEmptyObjNode(val, key, attrStr, level) {
|
||||||
|
if (val !== '') {
|
||||||
|
return this.buildObjectNode(val, key, attrStr, level);
|
||||||
|
} else {
|
||||||
|
if(key[0] === "?") return this.indentate(level) + '<' + key + attrStr+ '?' + this.tagEndChar;
|
||||||
|
else {
|
||||||
|
return this.indentate(level) + '<' + key + attrStr + '/' + this.tagEndChar;
|
||||||
|
// return this.buildTagStr(level,key, attrStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Builder.prototype.buildTextValNode = function(val, key, attrStr, level) {
|
||||||
|
if (this.options.cdataPropName !== false && key === this.options.cdataPropName) {
|
||||||
|
return this.indentate(level) + `<![CDATA[${val}]]>` + this.newLine;
|
||||||
|
}else if (this.options.commentPropName !== false && key === this.options.commentPropName) {
|
||||||
|
return this.indentate(level) + `<!--${val}-->` + this.newLine;
|
||||||
|
}else if(key[0] === "?") {//PI tag
|
||||||
|
return this.indentate(level) + '<' + key + attrStr+ '?' + this.tagEndChar;
|
||||||
|
}else{
|
||||||
|
let textValue = this.options.tagValueProcessor(key, val);
|
||||||
|
textValue = this.replaceEntitiesValue(textValue);
|
||||||
|
|
||||||
|
if( textValue === ''){
|
||||||
|
return this.indentate(level) + '<' + key + attrStr + this.closeTag(key) + this.tagEndChar;
|
||||||
|
}else{
|
||||||
|
return this.indentate(level) + '<' + key + attrStr + '>' +
|
||||||
|
textValue +
|
||||||
|
'</' + key + this.tagEndChar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Builder.prototype.replaceEntitiesValue = function(textValue){
|
||||||
|
if(textValue && textValue.length > 0 && this.options.processEntities){
|
||||||
|
for (let i=0; i<this.options.entities.length; i++) {
|
||||||
|
const entity = this.options.entities[i];
|
||||||
|
textValue = textValue.replace(entity.regex, entity.val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return textValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
function indentate(level) {
|
||||||
|
return this.options.indentBy.repeat(level);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isAttribute(name /*, options*/) {
|
||||||
|
if (name.startsWith(this.options.attributeNamePrefix) && name !== this.options.textNodeName) {
|
||||||
|
return name.substr(this.attrPrefixLen);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Builder;
|
||||||
135
node_modules/fast-xml-parser/src/xmlbuilder/orderedJs2Xml.js
generated
vendored
Normal file
135
node_modules/fast-xml-parser/src/xmlbuilder/orderedJs2Xml.js
generated
vendored
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
const EOL = "\n";
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {array} jArray
|
||||||
|
* @param {any} options
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function toXml(jArray, options) {
|
||||||
|
let indentation = "";
|
||||||
|
if (options.format && options.indentBy.length > 0) {
|
||||||
|
indentation = EOL;
|
||||||
|
}
|
||||||
|
return arrToStr(jArray, options, "", indentation);
|
||||||
|
}
|
||||||
|
|
||||||
|
function arrToStr(arr, options, jPath, indentation) {
|
||||||
|
let xmlStr = "";
|
||||||
|
let isPreviousElementTag = false;
|
||||||
|
|
||||||
|
for (let i = 0; i < arr.length; i++) {
|
||||||
|
const tagObj = arr[i];
|
||||||
|
const tagName = propName(tagObj);
|
||||||
|
if(tagName === undefined) continue;
|
||||||
|
|
||||||
|
let newJPath = "";
|
||||||
|
if (jPath.length === 0) newJPath = tagName
|
||||||
|
else newJPath = `${jPath}.${tagName}`;
|
||||||
|
|
||||||
|
if (tagName === options.textNodeName) {
|
||||||
|
let tagText = tagObj[tagName];
|
||||||
|
if (!isStopNode(newJPath, options)) {
|
||||||
|
tagText = options.tagValueProcessor(tagName, tagText);
|
||||||
|
tagText = replaceEntitiesValue(tagText, options);
|
||||||
|
}
|
||||||
|
if (isPreviousElementTag) {
|
||||||
|
xmlStr += indentation;
|
||||||
|
}
|
||||||
|
xmlStr += tagText;
|
||||||
|
isPreviousElementTag = false;
|
||||||
|
continue;
|
||||||
|
} else if (tagName === options.cdataPropName) {
|
||||||
|
if (isPreviousElementTag) {
|
||||||
|
xmlStr += indentation;
|
||||||
|
}
|
||||||
|
xmlStr += `<![CDATA[${tagObj[tagName][0][options.textNodeName]}]]>`;
|
||||||
|
isPreviousElementTag = false;
|
||||||
|
continue;
|
||||||
|
} else if (tagName === options.commentPropName) {
|
||||||
|
xmlStr += indentation + `<!--${tagObj[tagName][0][options.textNodeName]}-->`;
|
||||||
|
isPreviousElementTag = true;
|
||||||
|
continue;
|
||||||
|
} else if (tagName[0] === "?") {
|
||||||
|
const attStr = attr_to_str(tagObj[":@"], options);
|
||||||
|
const tempInd = tagName === "?xml" ? "" : indentation;
|
||||||
|
let piTextNodeName = tagObj[tagName][0][options.textNodeName];
|
||||||
|
piTextNodeName = piTextNodeName.length !== 0 ? " " + piTextNodeName : ""; //remove extra spacing
|
||||||
|
xmlStr += tempInd + `<${tagName}${piTextNodeName}${attStr}?>`;
|
||||||
|
isPreviousElementTag = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let newIdentation = indentation;
|
||||||
|
if (newIdentation !== "") {
|
||||||
|
newIdentation += options.indentBy;
|
||||||
|
}
|
||||||
|
const attStr = attr_to_str(tagObj[":@"], options);
|
||||||
|
const tagStart = indentation + `<${tagName}${attStr}`;
|
||||||
|
const tagValue = arrToStr(tagObj[tagName], options, newJPath, newIdentation);
|
||||||
|
if (options.unpairedTags.indexOf(tagName) !== -1) {
|
||||||
|
if (options.suppressUnpairedNode) xmlStr += tagStart + ">";
|
||||||
|
else xmlStr += tagStart + "/>";
|
||||||
|
} else if ((!tagValue || tagValue.length === 0) && options.suppressEmptyNode) {
|
||||||
|
xmlStr += tagStart + "/>";
|
||||||
|
} else if (tagValue && tagValue.endsWith(">")) {
|
||||||
|
xmlStr += tagStart + `>${tagValue}${indentation}</${tagName}>`;
|
||||||
|
} else {
|
||||||
|
xmlStr += tagStart + ">";
|
||||||
|
if (tagValue && indentation !== "" && (tagValue.includes("/>") || tagValue.includes("</"))) {
|
||||||
|
xmlStr += indentation + options.indentBy + tagValue + indentation;
|
||||||
|
} else {
|
||||||
|
xmlStr += tagValue;
|
||||||
|
}
|
||||||
|
xmlStr += `</${tagName}>`;
|
||||||
|
}
|
||||||
|
isPreviousElementTag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return xmlStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
function propName(obj) {
|
||||||
|
const keys = Object.keys(obj);
|
||||||
|
for (let i = 0; i < keys.length; i++) {
|
||||||
|
const key = keys[i];
|
||||||
|
if(!obj.hasOwnProperty(key)) continue;
|
||||||
|
if (key !== ":@") return key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function attr_to_str(attrMap, options) {
|
||||||
|
let attrStr = "";
|
||||||
|
if (attrMap && !options.ignoreAttributes) {
|
||||||
|
for (let attr in attrMap) {
|
||||||
|
if(!attrMap.hasOwnProperty(attr)) continue;
|
||||||
|
let attrVal = options.attributeValueProcessor(attr, attrMap[attr]);
|
||||||
|
attrVal = replaceEntitiesValue(attrVal, options);
|
||||||
|
if (attrVal === true && options.suppressBooleanAttributes) {
|
||||||
|
attrStr += ` ${attr.substr(options.attributeNamePrefix.length)}`;
|
||||||
|
} else {
|
||||||
|
attrStr += ` ${attr.substr(options.attributeNamePrefix.length)}="${attrVal}"`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return attrStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isStopNode(jPath, options) {
|
||||||
|
jPath = jPath.substr(0, jPath.length - options.textNodeName.length - 1);
|
||||||
|
let tagName = jPath.substr(jPath.lastIndexOf(".") + 1);
|
||||||
|
for (let index in options.stopNodes) {
|
||||||
|
if (options.stopNodes[index] === jPath || options.stopNodes[index] === "*." + tagName) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function replaceEntitiesValue(textValue, options) {
|
||||||
|
if (textValue && textValue.length > 0 && options.processEntities) {
|
||||||
|
for (let i = 0; i < options.entities.length; i++) {
|
||||||
|
const entity = options.entities[i];
|
||||||
|
textValue = textValue.replace(entity.regex, entity.val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return textValue;
|
||||||
|
}
|
||||||
|
module.exports = toXml;
|
||||||
0
node_modules/fast-xml-parser/src/xmlbuilder/prettifyJs2Xml.js
generated
vendored
Normal file
0
node_modules/fast-xml-parser/src/xmlbuilder/prettifyJs2Xml.js
generated
vendored
Normal file
153
node_modules/fast-xml-parser/src/xmlparser/DocTypeReader.js
generated
vendored
Normal file
153
node_modules/fast-xml-parser/src/xmlparser/DocTypeReader.js
generated
vendored
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
const util = require('../util');
|
||||||
|
|
||||||
|
//TODO: handle comments
|
||||||
|
function readDocType(xmlData, i){
|
||||||
|
|
||||||
|
const entities = {};
|
||||||
|
if( xmlData[i + 3] === 'O' &&
|
||||||
|
xmlData[i + 4] === 'C' &&
|
||||||
|
xmlData[i + 5] === 'T' &&
|
||||||
|
xmlData[i + 6] === 'Y' &&
|
||||||
|
xmlData[i + 7] === 'P' &&
|
||||||
|
xmlData[i + 8] === 'E')
|
||||||
|
{
|
||||||
|
i = i+9;
|
||||||
|
let angleBracketsCount = 1;
|
||||||
|
let hasBody = false, comment = false;
|
||||||
|
let exp = "";
|
||||||
|
for(;i<xmlData.length;i++){
|
||||||
|
if (xmlData[i] === '<' && !comment) { //Determine the tag type
|
||||||
|
if( hasBody && isEntity(xmlData, i)){
|
||||||
|
i += 7;
|
||||||
|
let entityName, val;
|
||||||
|
[entityName, val,i] = readEntityExp(xmlData,i+1);
|
||||||
|
if(val.indexOf("&") === -1) //Parameter entities are not supported
|
||||||
|
entities[ validateEntityName(entityName) ] = {
|
||||||
|
regx : RegExp( `&${entityName};`,"g"),
|
||||||
|
val: val
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if( hasBody && isElement(xmlData, i)) i += 8;//Not supported
|
||||||
|
else if( hasBody && isAttlist(xmlData, i)) i += 8;//Not supported
|
||||||
|
else if( hasBody && isNotation(xmlData, i)) i += 9;//Not supported
|
||||||
|
else if( isComment) comment = true;
|
||||||
|
else throw new Error("Invalid DOCTYPE");
|
||||||
|
|
||||||
|
angleBracketsCount++;
|
||||||
|
exp = "";
|
||||||
|
} else if (xmlData[i] === '>') { //Read tag content
|
||||||
|
if(comment){
|
||||||
|
if( xmlData[i - 1] === "-" && xmlData[i - 2] === "-"){
|
||||||
|
comment = false;
|
||||||
|
angleBracketsCount--;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
angleBracketsCount--;
|
||||||
|
}
|
||||||
|
if (angleBracketsCount === 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}else if( xmlData[i] === '['){
|
||||||
|
hasBody = true;
|
||||||
|
}else{
|
||||||
|
exp += xmlData[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(angleBracketsCount !== 0){
|
||||||
|
throw new Error(`Unclosed DOCTYPE`);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
throw new Error(`Invalid Tag instead of DOCTYPE`);
|
||||||
|
}
|
||||||
|
return {entities, i};
|
||||||
|
}
|
||||||
|
|
||||||
|
function readEntityExp(xmlData,i){
|
||||||
|
//External entities are not supported
|
||||||
|
// <!ENTITY ext SYSTEM "http://normal-website.com" >
|
||||||
|
|
||||||
|
//Parameter entities are not supported
|
||||||
|
// <!ENTITY entityname "&anotherElement;">
|
||||||
|
|
||||||
|
//Internal entities are supported
|
||||||
|
// <!ENTITY entityname "replacement text">
|
||||||
|
|
||||||
|
//read EntityName
|
||||||
|
let entityName = "";
|
||||||
|
for (; i < xmlData.length && (xmlData[i] !== "'" && xmlData[i] !== '"' ); i++) {
|
||||||
|
// if(xmlData[i] === " ") continue;
|
||||||
|
// else
|
||||||
|
entityName += xmlData[i];
|
||||||
|
}
|
||||||
|
entityName = entityName.trim();
|
||||||
|
if(entityName.indexOf(" ") !== -1) throw new Error("External entites are not supported");
|
||||||
|
|
||||||
|
//read Entity Value
|
||||||
|
const startChar = xmlData[i++];
|
||||||
|
let val = ""
|
||||||
|
for (; i < xmlData.length && xmlData[i] !== startChar ; i++) {
|
||||||
|
val += xmlData[i];
|
||||||
|
}
|
||||||
|
return [entityName, val, i];
|
||||||
|
}
|
||||||
|
|
||||||
|
function isComment(xmlData, i){
|
||||||
|
if(xmlData[i+1] === '!' &&
|
||||||
|
xmlData[i+2] === '-' &&
|
||||||
|
xmlData[i+3] === '-') return true
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
function isEntity(xmlData, i){
|
||||||
|
if(xmlData[i+1] === '!' &&
|
||||||
|
xmlData[i+2] === 'E' &&
|
||||||
|
xmlData[i+3] === 'N' &&
|
||||||
|
xmlData[i+4] === 'T' &&
|
||||||
|
xmlData[i+5] === 'I' &&
|
||||||
|
xmlData[i+6] === 'T' &&
|
||||||
|
xmlData[i+7] === 'Y') return true
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
function isElement(xmlData, i){
|
||||||
|
if(xmlData[i+1] === '!' &&
|
||||||
|
xmlData[i+2] === 'E' &&
|
||||||
|
xmlData[i+3] === 'L' &&
|
||||||
|
xmlData[i+4] === 'E' &&
|
||||||
|
xmlData[i+5] === 'M' &&
|
||||||
|
xmlData[i+6] === 'E' &&
|
||||||
|
xmlData[i+7] === 'N' &&
|
||||||
|
xmlData[i+8] === 'T') return true
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
function isAttlist(xmlData, i){
|
||||||
|
if(xmlData[i+1] === '!' &&
|
||||||
|
xmlData[i+2] === 'A' &&
|
||||||
|
xmlData[i+3] === 'T' &&
|
||||||
|
xmlData[i+4] === 'T' &&
|
||||||
|
xmlData[i+5] === 'L' &&
|
||||||
|
xmlData[i+6] === 'I' &&
|
||||||
|
xmlData[i+7] === 'S' &&
|
||||||
|
xmlData[i+8] === 'T') return true
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
function isNotation(xmlData, i){
|
||||||
|
if(xmlData[i+1] === '!' &&
|
||||||
|
xmlData[i+2] === 'N' &&
|
||||||
|
xmlData[i+3] === 'O' &&
|
||||||
|
xmlData[i+4] === 'T' &&
|
||||||
|
xmlData[i+5] === 'A' &&
|
||||||
|
xmlData[i+6] === 'T' &&
|
||||||
|
xmlData[i+7] === 'I' &&
|
||||||
|
xmlData[i+8] === 'O' &&
|
||||||
|
xmlData[i+9] === 'N') return true
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateEntityName(name){
|
||||||
|
if (util.isName(name))
|
||||||
|
return name;
|
||||||
|
else
|
||||||
|
throw new Error(`Invalid entity name ${name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = readDocType;
|
||||||
48
node_modules/fast-xml-parser/src/xmlparser/OptionsBuilder.js
generated
vendored
Normal file
48
node_modules/fast-xml-parser/src/xmlparser/OptionsBuilder.js
generated
vendored
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
|
||||||
|
const defaultOptions = {
|
||||||
|
preserveOrder: false,
|
||||||
|
attributeNamePrefix: '@_',
|
||||||
|
attributesGroupName: false,
|
||||||
|
textNodeName: '#text',
|
||||||
|
ignoreAttributes: true,
|
||||||
|
removeNSPrefix: false, // remove NS from tag name or attribute name if true
|
||||||
|
allowBooleanAttributes: false, //a tag can have attributes without any value
|
||||||
|
//ignoreRootElement : false,
|
||||||
|
parseTagValue: true,
|
||||||
|
parseAttributeValue: false,
|
||||||
|
trimValues: true, //Trim string values of tag and attributes
|
||||||
|
cdataPropName: false,
|
||||||
|
numberParseOptions: {
|
||||||
|
hex: true,
|
||||||
|
leadingZeros: true,
|
||||||
|
eNotation: true
|
||||||
|
},
|
||||||
|
tagValueProcessor: function(tagName, val) {
|
||||||
|
return val;
|
||||||
|
},
|
||||||
|
attributeValueProcessor: function(attrName, val) {
|
||||||
|
return val;
|
||||||
|
},
|
||||||
|
stopNodes: [], //nested tags will not be parsed even for errors
|
||||||
|
alwaysCreateTextNode: false,
|
||||||
|
isArray: () => false,
|
||||||
|
commentPropName: false,
|
||||||
|
unpairedTags: [],
|
||||||
|
processEntities: true,
|
||||||
|
htmlEntities: false,
|
||||||
|
ignoreDeclaration: false,
|
||||||
|
ignorePiTags: false,
|
||||||
|
transformTagName: false,
|
||||||
|
transformAttributeName: false,
|
||||||
|
updateTag: function(tagName, jPath, attrs){
|
||||||
|
return tagName
|
||||||
|
},
|
||||||
|
// skipEmptyListItem: false
|
||||||
|
};
|
||||||
|
|
||||||
|
const buildOptions = function(options) {
|
||||||
|
return Object.assign({}, defaultOptions, options);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.buildOptions = buildOptions;
|
||||||
|
exports.defaultOptions = defaultOptions;
|
||||||
606
node_modules/fast-xml-parser/src/xmlparser/OrderedObjParser.js
generated
vendored
Normal file
606
node_modules/fast-xml-parser/src/xmlparser/OrderedObjParser.js
generated
vendored
Normal file
@ -0,0 +1,606 @@
|
|||||||
|
'use strict';
|
||||||
|
///@ts-check
|
||||||
|
|
||||||
|
const util = require('../util');
|
||||||
|
const xmlNode = require('./xmlNode');
|
||||||
|
const readDocType = require("./DocTypeReader");
|
||||||
|
const toNumber = require("strnum");
|
||||||
|
const getIgnoreAttributesFn = require('../ignoreAttributes')
|
||||||
|
|
||||||
|
// const regx =
|
||||||
|
// '<((!\\[CDATA\\[([\\s\\S]*?)(]]>))|((NAME:)?(NAME))([^>]*)>|((\\/)(NAME)\\s*>))([^<]*)'
|
||||||
|
// .replace(/NAME/g, util.nameRegexp);
|
||||||
|
|
||||||
|
//const tagsRegx = new RegExp("<(\\/?[\\w:\\-\._]+)([^>]*)>(\\s*"+cdataRegx+")*([^<]+)?","g");
|
||||||
|
//const tagsRegx = new RegExp("<(\\/?)((\\w*:)?([\\w:\\-\._]+))([^>]*)>([^<]*)("+cdataRegx+"([^<]*))*([^<]+)?","g");
|
||||||
|
|
||||||
|
class OrderedObjParser{
|
||||||
|
constructor(options){
|
||||||
|
this.options = options;
|
||||||
|
this.currentNode = null;
|
||||||
|
this.tagsNodeStack = [];
|
||||||
|
this.docTypeEntities = {};
|
||||||
|
this.lastEntities = {
|
||||||
|
"apos" : { regex: /&(apos|#39|#x27);/g, val : "'"},
|
||||||
|
"gt" : { regex: /&(gt|#62|#x3E);/g, val : ">"},
|
||||||
|
"lt" : { regex: /&(lt|#60|#x3C);/g, val : "<"},
|
||||||
|
"quot" : { regex: /&(quot|#34|#x22);/g, val : "\""},
|
||||||
|
};
|
||||||
|
this.ampEntity = { regex: /&(amp|#38|#x26);/g, val : "&"};
|
||||||
|
this.htmlEntities = {
|
||||||
|
"space": { regex: /&(nbsp|#160);/g, val: " " },
|
||||||
|
// "lt" : { regex: /&(lt|#60);/g, val: "<" },
|
||||||
|
// "gt" : { regex: /&(gt|#62);/g, val: ">" },
|
||||||
|
// "amp" : { regex: /&(amp|#38);/g, val: "&" },
|
||||||
|
// "quot" : { regex: /&(quot|#34);/g, val: "\"" },
|
||||||
|
// "apos" : { regex: /&(apos|#39);/g, val: "'" },
|
||||||
|
"cent" : { regex: /&(cent|#162);/g, val: "¢" },
|
||||||
|
"pound" : { regex: /&(pound|#163);/g, val: "£" },
|
||||||
|
"yen" : { regex: /&(yen|#165);/g, val: "¥" },
|
||||||
|
"euro" : { regex: /&(euro|#8364);/g, val: "€" },
|
||||||
|
"copyright" : { regex: /&(copy|#169);/g, val: "©" },
|
||||||
|
"reg" : { regex: /&(reg|#174);/g, val: "®" },
|
||||||
|
"inr" : { regex: /&(inr|#8377);/g, val: "₹" },
|
||||||
|
"num_dec": { regex: /&#([0-9]{1,7});/g, val : (_, str) => String.fromCharCode(Number.parseInt(str, 10)) },
|
||||||
|
"num_hex": { regex: /&#x([0-9a-fA-F]{1,6});/g, val : (_, str) => String.fromCharCode(Number.parseInt(str, 16)) },
|
||||||
|
};
|
||||||
|
this.addExternalEntities = addExternalEntities;
|
||||||
|
this.parseXml = parseXml;
|
||||||
|
this.parseTextData = parseTextData;
|
||||||
|
this.resolveNameSpace = resolveNameSpace;
|
||||||
|
this.buildAttributesMap = buildAttributesMap;
|
||||||
|
this.isItStopNode = isItStopNode;
|
||||||
|
this.replaceEntitiesValue = replaceEntitiesValue;
|
||||||
|
this.readStopNodeData = readStopNodeData;
|
||||||
|
this.saveTextToParentTag = saveTextToParentTag;
|
||||||
|
this.addChild = addChild;
|
||||||
|
this.ignoreAttributesFn = getIgnoreAttributesFn(this.options.ignoreAttributes)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function addExternalEntities(externalEntities){
|
||||||
|
const entKeys = Object.keys(externalEntities);
|
||||||
|
for (let i = 0; i < entKeys.length; i++) {
|
||||||
|
const ent = entKeys[i];
|
||||||
|
this.lastEntities[ent] = {
|
||||||
|
regex: new RegExp("&"+ent+";","g"),
|
||||||
|
val : externalEntities[ent]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} val
|
||||||
|
* @param {string} tagName
|
||||||
|
* @param {string} jPath
|
||||||
|
* @param {boolean} dontTrim
|
||||||
|
* @param {boolean} hasAttributes
|
||||||
|
* @param {boolean} isLeafNode
|
||||||
|
* @param {boolean} escapeEntities
|
||||||
|
*/
|
||||||
|
function parseTextData(val, tagName, jPath, dontTrim, hasAttributes, isLeafNode, escapeEntities) {
|
||||||
|
if (val !== undefined) {
|
||||||
|
if (this.options.trimValues && !dontTrim) {
|
||||||
|
val = val.trim();
|
||||||
|
}
|
||||||
|
if(val.length > 0){
|
||||||
|
if(!escapeEntities) val = this.replaceEntitiesValue(val);
|
||||||
|
|
||||||
|
const newval = this.options.tagValueProcessor(tagName, val, jPath, hasAttributes, isLeafNode);
|
||||||
|
if(newval === null || newval === undefined){
|
||||||
|
//don't parse
|
||||||
|
return val;
|
||||||
|
}else if(typeof newval !== typeof val || newval !== val){
|
||||||
|
//overwrite
|
||||||
|
return newval;
|
||||||
|
}else if(this.options.trimValues){
|
||||||
|
return parseValue(val, this.options.parseTagValue, this.options.numberParseOptions);
|
||||||
|
}else{
|
||||||
|
const trimmedVal = val.trim();
|
||||||
|
if(trimmedVal === val){
|
||||||
|
return parseValue(val, this.options.parseTagValue, this.options.numberParseOptions);
|
||||||
|
}else{
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveNameSpace(tagname) {
|
||||||
|
if (this.options.removeNSPrefix) {
|
||||||
|
const tags = tagname.split(':');
|
||||||
|
const prefix = tagname.charAt(0) === '/' ? '/' : '';
|
||||||
|
if (tags[0] === 'xmlns') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
if (tags.length === 2) {
|
||||||
|
tagname = prefix + tags[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tagname;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: change regex to capture NS
|
||||||
|
//const attrsRegx = new RegExp("([\\w\\-\\.\\:]+)\\s*=\\s*(['\"])((.|\n)*?)\\2","gm");
|
||||||
|
const attrsRegx = new RegExp('([^\\s=]+)\\s*(=\\s*([\'"])([\\s\\S]*?)\\3)?', 'gm');
|
||||||
|
|
||||||
|
function buildAttributesMap(attrStr, jPath, tagName) {
|
||||||
|
if (this.options.ignoreAttributes !== true && typeof attrStr === 'string') {
|
||||||
|
// attrStr = attrStr.replace(/\r?\n/g, ' ');
|
||||||
|
//attrStr = attrStr || attrStr.trim();
|
||||||
|
|
||||||
|
const matches = util.getAllMatches(attrStr, attrsRegx);
|
||||||
|
const len = matches.length; //don't make it inline
|
||||||
|
const attrs = {};
|
||||||
|
for (let i = 0; i < len; i++) {
|
||||||
|
const attrName = this.resolveNameSpace(matches[i][1]);
|
||||||
|
if (this.ignoreAttributesFn(attrName, jPath)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
let oldVal = matches[i][4];
|
||||||
|
let aName = this.options.attributeNamePrefix + attrName;
|
||||||
|
if (attrName.length) {
|
||||||
|
if (this.options.transformAttributeName) {
|
||||||
|
aName = this.options.transformAttributeName(aName);
|
||||||
|
}
|
||||||
|
if(aName === "__proto__") aName = "#__proto__";
|
||||||
|
if (oldVal !== undefined) {
|
||||||
|
if (this.options.trimValues) {
|
||||||
|
oldVal = oldVal.trim();
|
||||||
|
}
|
||||||
|
oldVal = this.replaceEntitiesValue(oldVal);
|
||||||
|
const newVal = this.options.attributeValueProcessor(attrName, oldVal, jPath);
|
||||||
|
if(newVal === null || newVal === undefined){
|
||||||
|
//don't parse
|
||||||
|
attrs[aName] = oldVal;
|
||||||
|
}else if(typeof newVal !== typeof oldVal || newVal !== oldVal){
|
||||||
|
//overwrite
|
||||||
|
attrs[aName] = newVal;
|
||||||
|
}else{
|
||||||
|
//parse
|
||||||
|
attrs[aName] = parseValue(
|
||||||
|
oldVal,
|
||||||
|
this.options.parseAttributeValue,
|
||||||
|
this.options.numberParseOptions
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (this.options.allowBooleanAttributes) {
|
||||||
|
attrs[aName] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!Object.keys(attrs).length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.options.attributesGroupName) {
|
||||||
|
const attrCollection = {};
|
||||||
|
attrCollection[this.options.attributesGroupName] = attrs;
|
||||||
|
return attrCollection;
|
||||||
|
}
|
||||||
|
return attrs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const parseXml = function(xmlData) {
|
||||||
|
xmlData = xmlData.replace(/\r\n?/g, "\n"); //TODO: remove this line
|
||||||
|
const xmlObj = new xmlNode('!xml');
|
||||||
|
let currentNode = xmlObj;
|
||||||
|
let textData = "";
|
||||||
|
let jPath = "";
|
||||||
|
for(let i=0; i< xmlData.length; i++){//for each char in XML data
|
||||||
|
const ch = xmlData[i];
|
||||||
|
if(ch === '<'){
|
||||||
|
// const nextIndex = i+1;
|
||||||
|
// const _2ndChar = xmlData[nextIndex];
|
||||||
|
if( xmlData[i+1] === '/') {//Closing Tag
|
||||||
|
const closeIndex = findClosingIndex(xmlData, ">", i, "Closing Tag is not closed.")
|
||||||
|
let tagName = xmlData.substring(i+2,closeIndex).trim();
|
||||||
|
|
||||||
|
if(this.options.removeNSPrefix){
|
||||||
|
const colonIndex = tagName.indexOf(":");
|
||||||
|
if(colonIndex !== -1){
|
||||||
|
tagName = tagName.substr(colonIndex+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.options.transformTagName) {
|
||||||
|
tagName = this.options.transformTagName(tagName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(currentNode){
|
||||||
|
textData = this.saveTextToParentTag(textData, currentNode, jPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
//check if last tag of nested tag was unpaired tag
|
||||||
|
const lastTagName = jPath.substring(jPath.lastIndexOf(".")+1);
|
||||||
|
if(tagName && this.options.unpairedTags.indexOf(tagName) !== -1 ){
|
||||||
|
throw new Error(`Unpaired tag can not be used as closing tag: </${tagName}>`);
|
||||||
|
}
|
||||||
|
let propIndex = 0
|
||||||
|
if(lastTagName && this.options.unpairedTags.indexOf(lastTagName) !== -1 ){
|
||||||
|
propIndex = jPath.lastIndexOf('.', jPath.lastIndexOf('.')-1)
|
||||||
|
this.tagsNodeStack.pop();
|
||||||
|
}else{
|
||||||
|
propIndex = jPath.lastIndexOf(".");
|
||||||
|
}
|
||||||
|
jPath = jPath.substring(0, propIndex);
|
||||||
|
|
||||||
|
currentNode = this.tagsNodeStack.pop();//avoid recursion, set the parent tag scope
|
||||||
|
textData = "";
|
||||||
|
i = closeIndex;
|
||||||
|
} else if( xmlData[i+1] === '?') {
|
||||||
|
|
||||||
|
let tagData = readTagExp(xmlData,i, false, "?>");
|
||||||
|
if(!tagData) throw new Error("Pi Tag is not closed.");
|
||||||
|
|
||||||
|
textData = this.saveTextToParentTag(textData, currentNode, jPath);
|
||||||
|
if( (this.options.ignoreDeclaration && tagData.tagName === "?xml") || this.options.ignorePiTags){
|
||||||
|
|
||||||
|
}else{
|
||||||
|
|
||||||
|
const childNode = new xmlNode(tagData.tagName);
|
||||||
|
childNode.add(this.options.textNodeName, "");
|
||||||
|
|
||||||
|
if(tagData.tagName !== tagData.tagExp && tagData.attrExpPresent){
|
||||||
|
childNode[":@"] = this.buildAttributesMap(tagData.tagExp, jPath, tagData.tagName);
|
||||||
|
}
|
||||||
|
this.addChild(currentNode, childNode, jPath)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
i = tagData.closeIndex + 1;
|
||||||
|
} else if(xmlData.substr(i + 1, 3) === '!--') {
|
||||||
|
const endIndex = findClosingIndex(xmlData, "-->", i+4, "Comment is not closed.")
|
||||||
|
if(this.options.commentPropName){
|
||||||
|
const comment = xmlData.substring(i + 4, endIndex - 2);
|
||||||
|
|
||||||
|
textData = this.saveTextToParentTag(textData, currentNode, jPath);
|
||||||
|
|
||||||
|
currentNode.add(this.options.commentPropName, [ { [this.options.textNodeName] : comment } ]);
|
||||||
|
}
|
||||||
|
i = endIndex;
|
||||||
|
} else if( xmlData.substr(i + 1, 2) === '!D') {
|
||||||
|
const result = readDocType(xmlData, i);
|
||||||
|
this.docTypeEntities = result.entities;
|
||||||
|
i = result.i;
|
||||||
|
}else if(xmlData.substr(i + 1, 2) === '![') {
|
||||||
|
const closeIndex = findClosingIndex(xmlData, "]]>", i, "CDATA is not closed.") - 2;
|
||||||
|
const tagExp = xmlData.substring(i + 9,closeIndex);
|
||||||
|
|
||||||
|
textData = this.saveTextToParentTag(textData, currentNode, jPath);
|
||||||
|
|
||||||
|
let val = this.parseTextData(tagExp, currentNode.tagname, jPath, true, false, true, true);
|
||||||
|
if(val == undefined) val = "";
|
||||||
|
|
||||||
|
//cdata should be set even if it is 0 length string
|
||||||
|
if(this.options.cdataPropName){
|
||||||
|
currentNode.add(this.options.cdataPropName, [ { [this.options.textNodeName] : tagExp } ]);
|
||||||
|
}else{
|
||||||
|
currentNode.add(this.options.textNodeName, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
i = closeIndex + 2;
|
||||||
|
}else {//Opening tag
|
||||||
|
let result = readTagExp(xmlData,i, this.options.removeNSPrefix);
|
||||||
|
let tagName= result.tagName;
|
||||||
|
const rawTagName = result.rawTagName;
|
||||||
|
let tagExp = result.tagExp;
|
||||||
|
let attrExpPresent = result.attrExpPresent;
|
||||||
|
let closeIndex = result.closeIndex;
|
||||||
|
|
||||||
|
if (this.options.transformTagName) {
|
||||||
|
tagName = this.options.transformTagName(tagName);
|
||||||
|
}
|
||||||
|
|
||||||
|
//save text as child node
|
||||||
|
if (currentNode && textData) {
|
||||||
|
if(currentNode.tagname !== '!xml'){
|
||||||
|
//when nested tag is found
|
||||||
|
textData = this.saveTextToParentTag(textData, currentNode, jPath, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//check if last tag was unpaired tag
|
||||||
|
const lastTag = currentNode;
|
||||||
|
if(lastTag && this.options.unpairedTags.indexOf(lastTag.tagname) !== -1 ){
|
||||||
|
currentNode = this.tagsNodeStack.pop();
|
||||||
|
jPath = jPath.substring(0, jPath.lastIndexOf("."));
|
||||||
|
}
|
||||||
|
if(tagName !== xmlObj.tagname){
|
||||||
|
jPath += jPath ? "." + tagName : tagName;
|
||||||
|
}
|
||||||
|
if (this.isItStopNode(this.options.stopNodes, jPath, tagName)) {
|
||||||
|
let tagContent = "";
|
||||||
|
//self-closing tag
|
||||||
|
if(tagExp.length > 0 && tagExp.lastIndexOf("/") === tagExp.length - 1){
|
||||||
|
if(tagName[tagName.length - 1] === "/"){ //remove trailing '/'
|
||||||
|
tagName = tagName.substr(0, tagName.length - 1);
|
||||||
|
jPath = jPath.substr(0, jPath.length - 1);
|
||||||
|
tagExp = tagName;
|
||||||
|
}else{
|
||||||
|
tagExp = tagExp.substr(0, tagExp.length - 1);
|
||||||
|
}
|
||||||
|
i = result.closeIndex;
|
||||||
|
}
|
||||||
|
//unpaired tag
|
||||||
|
else if(this.options.unpairedTags.indexOf(tagName) !== -1){
|
||||||
|
|
||||||
|
i = result.closeIndex;
|
||||||
|
}
|
||||||
|
//normal tag
|
||||||
|
else{
|
||||||
|
//read until closing tag is found
|
||||||
|
const result = this.readStopNodeData(xmlData, rawTagName, closeIndex + 1);
|
||||||
|
if(!result) throw new Error(`Unexpected end of ${rawTagName}`);
|
||||||
|
i = result.i;
|
||||||
|
tagContent = result.tagContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
const childNode = new xmlNode(tagName);
|
||||||
|
if(tagName !== tagExp && attrExpPresent){
|
||||||
|
childNode[":@"] = this.buildAttributesMap(tagExp, jPath, tagName);
|
||||||
|
}
|
||||||
|
if(tagContent) {
|
||||||
|
tagContent = this.parseTextData(tagContent, tagName, jPath, true, attrExpPresent, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
jPath = jPath.substr(0, jPath.lastIndexOf("."));
|
||||||
|
childNode.add(this.options.textNodeName, tagContent);
|
||||||
|
|
||||||
|
this.addChild(currentNode, childNode, jPath)
|
||||||
|
}else{
|
||||||
|
//selfClosing tag
|
||||||
|
if(tagExp.length > 0 && tagExp.lastIndexOf("/") === tagExp.length - 1){
|
||||||
|
if(tagName[tagName.length - 1] === "/"){ //remove trailing '/'
|
||||||
|
tagName = tagName.substr(0, tagName.length - 1);
|
||||||
|
jPath = jPath.substr(0, jPath.length - 1);
|
||||||
|
tagExp = tagName;
|
||||||
|
}else{
|
||||||
|
tagExp = tagExp.substr(0, tagExp.length - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.options.transformTagName) {
|
||||||
|
tagName = this.options.transformTagName(tagName);
|
||||||
|
}
|
||||||
|
|
||||||
|
const childNode = new xmlNode(tagName);
|
||||||
|
if(tagName !== tagExp && attrExpPresent){
|
||||||
|
childNode[":@"] = this.buildAttributesMap(tagExp, jPath, tagName);
|
||||||
|
}
|
||||||
|
this.addChild(currentNode, childNode, jPath)
|
||||||
|
jPath = jPath.substr(0, jPath.lastIndexOf("."));
|
||||||
|
}
|
||||||
|
//opening tag
|
||||||
|
else{
|
||||||
|
const childNode = new xmlNode( tagName);
|
||||||
|
this.tagsNodeStack.push(currentNode);
|
||||||
|
|
||||||
|
if(tagName !== tagExp && attrExpPresent){
|
||||||
|
childNode[":@"] = this.buildAttributesMap(tagExp, jPath, tagName);
|
||||||
|
}
|
||||||
|
this.addChild(currentNode, childNode, jPath)
|
||||||
|
currentNode = childNode;
|
||||||
|
}
|
||||||
|
textData = "";
|
||||||
|
i = closeIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
textData += xmlData[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return xmlObj.child;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addChild(currentNode, childNode, jPath){
|
||||||
|
const result = this.options.updateTag(childNode.tagname, jPath, childNode[":@"])
|
||||||
|
if(result === false){
|
||||||
|
}else if(typeof result === "string"){
|
||||||
|
childNode.tagname = result
|
||||||
|
currentNode.addChild(childNode);
|
||||||
|
}else{
|
||||||
|
currentNode.addChild(childNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const replaceEntitiesValue = function(val){
|
||||||
|
|
||||||
|
if(this.options.processEntities){
|
||||||
|
for(let entityName in this.docTypeEntities){
|
||||||
|
const entity = this.docTypeEntities[entityName];
|
||||||
|
val = val.replace( entity.regx, entity.val);
|
||||||
|
}
|
||||||
|
for(let entityName in this.lastEntities){
|
||||||
|
const entity = this.lastEntities[entityName];
|
||||||
|
val = val.replace( entity.regex, entity.val);
|
||||||
|
}
|
||||||
|
if(this.options.htmlEntities){
|
||||||
|
for(let entityName in this.htmlEntities){
|
||||||
|
const entity = this.htmlEntities[entityName];
|
||||||
|
val = val.replace( entity.regex, entity.val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val = val.replace( this.ampEntity.regex, this.ampEntity.val);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
function saveTextToParentTag(textData, currentNode, jPath, isLeafNode) {
|
||||||
|
if (textData) { //store previously collected data as textNode
|
||||||
|
if(isLeafNode === undefined) isLeafNode = currentNode.child.length === 0
|
||||||
|
|
||||||
|
textData = this.parseTextData(textData,
|
||||||
|
currentNode.tagname,
|
||||||
|
jPath,
|
||||||
|
false,
|
||||||
|
currentNode[":@"] ? Object.keys(currentNode[":@"]).length !== 0 : false,
|
||||||
|
isLeafNode);
|
||||||
|
|
||||||
|
if (textData !== undefined && textData !== "")
|
||||||
|
currentNode.add(this.options.textNodeName, textData);
|
||||||
|
textData = "";
|
||||||
|
}
|
||||||
|
return textData;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: use jPath to simplify the logic
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string[]} stopNodes
|
||||||
|
* @param {string} jPath
|
||||||
|
* @param {string} currentTagName
|
||||||
|
*/
|
||||||
|
function isItStopNode(stopNodes, jPath, currentTagName){
|
||||||
|
const allNodesExp = "*." + currentTagName;
|
||||||
|
for (const stopNodePath in stopNodes) {
|
||||||
|
const stopNodeExp = stopNodes[stopNodePath];
|
||||||
|
if( allNodesExp === stopNodeExp || jPath === stopNodeExp ) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the tag Expression and where it is ending handling single-double quotes situation
|
||||||
|
* @param {string} xmlData
|
||||||
|
* @param {number} i starting index
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function tagExpWithClosingIndex(xmlData, i, closingChar = ">"){
|
||||||
|
let attrBoundary;
|
||||||
|
let tagExp = "";
|
||||||
|
for (let index = i; index < xmlData.length; index++) {
|
||||||
|
let ch = xmlData[index];
|
||||||
|
if (attrBoundary) {
|
||||||
|
if (ch === attrBoundary) attrBoundary = "";//reset
|
||||||
|
} else if (ch === '"' || ch === "'") {
|
||||||
|
attrBoundary = ch;
|
||||||
|
} else if (ch === closingChar[0]) {
|
||||||
|
if(closingChar[1]){
|
||||||
|
if(xmlData[index + 1] === closingChar[1]){
|
||||||
|
return {
|
||||||
|
data: tagExp,
|
||||||
|
index: index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
return {
|
||||||
|
data: tagExp,
|
||||||
|
index: index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (ch === '\t') {
|
||||||
|
ch = " "
|
||||||
|
}
|
||||||
|
tagExp += ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function findClosingIndex(xmlData, str, i, errMsg){
|
||||||
|
const closingIndex = xmlData.indexOf(str, i);
|
||||||
|
if(closingIndex === -1){
|
||||||
|
throw new Error(errMsg)
|
||||||
|
}else{
|
||||||
|
return closingIndex + str.length - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function readTagExp(xmlData,i, removeNSPrefix, closingChar = ">"){
|
||||||
|
const result = tagExpWithClosingIndex(xmlData, i+1, closingChar);
|
||||||
|
if(!result) return;
|
||||||
|
let tagExp = result.data;
|
||||||
|
const closeIndex = result.index;
|
||||||
|
const separatorIndex = tagExp.search(/\s/);
|
||||||
|
let tagName = tagExp;
|
||||||
|
let attrExpPresent = true;
|
||||||
|
if(separatorIndex !== -1){//separate tag name and attributes expression
|
||||||
|
tagName = tagExp.substring(0, separatorIndex);
|
||||||
|
tagExp = tagExp.substring(separatorIndex + 1).trimStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
const rawTagName = tagName;
|
||||||
|
if(removeNSPrefix){
|
||||||
|
const colonIndex = tagName.indexOf(":");
|
||||||
|
if(colonIndex !== -1){
|
||||||
|
tagName = tagName.substr(colonIndex+1);
|
||||||
|
attrExpPresent = tagName !== result.data.substr(colonIndex + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
tagName: tagName,
|
||||||
|
tagExp: tagExp,
|
||||||
|
closeIndex: closeIndex,
|
||||||
|
attrExpPresent: attrExpPresent,
|
||||||
|
rawTagName: rawTagName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* find paired tag for a stop node
|
||||||
|
* @param {string} xmlData
|
||||||
|
* @param {string} tagName
|
||||||
|
* @param {number} i
|
||||||
|
*/
|
||||||
|
function readStopNodeData(xmlData, tagName, i){
|
||||||
|
const startIndex = i;
|
||||||
|
// Starting at 1 since we already have an open tag
|
||||||
|
let openTagCount = 1;
|
||||||
|
|
||||||
|
for (; i < xmlData.length; i++) {
|
||||||
|
if( xmlData[i] === "<"){
|
||||||
|
if (xmlData[i+1] === "/") {//close tag
|
||||||
|
const closeIndex = findClosingIndex(xmlData, ">", i, `${tagName} is not closed`);
|
||||||
|
let closeTagName = xmlData.substring(i+2,closeIndex).trim();
|
||||||
|
if(closeTagName === tagName){
|
||||||
|
openTagCount--;
|
||||||
|
if (openTagCount === 0) {
|
||||||
|
return {
|
||||||
|
tagContent: xmlData.substring(startIndex, i),
|
||||||
|
i : closeIndex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i=closeIndex;
|
||||||
|
} else if(xmlData[i+1] === '?') {
|
||||||
|
const closeIndex = findClosingIndex(xmlData, "?>", i+1, "StopNode is not closed.")
|
||||||
|
i=closeIndex;
|
||||||
|
} else if(xmlData.substr(i + 1, 3) === '!--') {
|
||||||
|
const closeIndex = findClosingIndex(xmlData, "-->", i+3, "StopNode is not closed.")
|
||||||
|
i=closeIndex;
|
||||||
|
} else if(xmlData.substr(i + 1, 2) === '![') {
|
||||||
|
const closeIndex = findClosingIndex(xmlData, "]]>", i, "StopNode is not closed.") - 2;
|
||||||
|
i=closeIndex;
|
||||||
|
} else {
|
||||||
|
const tagData = readTagExp(xmlData, i, '>')
|
||||||
|
|
||||||
|
if (tagData) {
|
||||||
|
const openTagName = tagData && tagData.tagName;
|
||||||
|
if (openTagName === tagName && tagData.tagExp[tagData.tagExp.length-1] !== "/") {
|
||||||
|
openTagCount++;
|
||||||
|
}
|
||||||
|
i=tagData.closeIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}//end for loop
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseValue(val, shouldParse, options) {
|
||||||
|
if (shouldParse && typeof val === 'string') {
|
||||||
|
//console.log(options)
|
||||||
|
const newval = val.trim();
|
||||||
|
if(newval === 'true' ) return true;
|
||||||
|
else if(newval === 'false' ) return false;
|
||||||
|
else return toNumber(val, options);
|
||||||
|
} else {
|
||||||
|
if (util.isExist(val)) {
|
||||||
|
return val;
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = OrderedObjParser;
|
||||||
58
node_modules/fast-xml-parser/src/xmlparser/XMLParser.js
generated
vendored
Normal file
58
node_modules/fast-xml-parser/src/xmlparser/XMLParser.js
generated
vendored
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
const { buildOptions} = require("./OptionsBuilder");
|
||||||
|
const OrderedObjParser = require("./OrderedObjParser");
|
||||||
|
const { prettify} = require("./node2json");
|
||||||
|
const validator = require('../validator');
|
||||||
|
|
||||||
|
class XMLParser{
|
||||||
|
|
||||||
|
constructor(options){
|
||||||
|
this.externalEntities = {};
|
||||||
|
this.options = buildOptions(options);
|
||||||
|
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse XML dats to JS object
|
||||||
|
* @param {string|Buffer} xmlData
|
||||||
|
* @param {boolean|Object} validationOption
|
||||||
|
*/
|
||||||
|
parse(xmlData,validationOption){
|
||||||
|
if(typeof xmlData === "string"){
|
||||||
|
}else if( xmlData.toString){
|
||||||
|
xmlData = xmlData.toString();
|
||||||
|
}else{
|
||||||
|
throw new Error("XML data is accepted in String or Bytes[] form.")
|
||||||
|
}
|
||||||
|
if( validationOption){
|
||||||
|
if(validationOption === true) validationOption = {}; //validate with default options
|
||||||
|
|
||||||
|
const result = validator.validate(xmlData, validationOption);
|
||||||
|
if (result !== true) {
|
||||||
|
throw Error( `${result.err.msg}:${result.err.line}:${result.err.col}` )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const orderedObjParser = new OrderedObjParser(this.options);
|
||||||
|
orderedObjParser.addExternalEntities(this.externalEntities);
|
||||||
|
const orderedResult = orderedObjParser.parseXml(xmlData);
|
||||||
|
if(this.options.preserveOrder || orderedResult === undefined) return orderedResult;
|
||||||
|
else return prettify(orderedResult, this.options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add Entity which is not by default supported by this library
|
||||||
|
* @param {string} key
|
||||||
|
* @param {string} value
|
||||||
|
*/
|
||||||
|
addEntity(key, value){
|
||||||
|
if(value.indexOf("&") !== -1){
|
||||||
|
throw new Error("Entity value can't have '&'")
|
||||||
|
}else if(key.indexOf("&") !== -1 || key.indexOf(";") !== -1){
|
||||||
|
throw new Error("An entity must be set without '&' and ';'. Eg. use '#xD' for '
'")
|
||||||
|
}else if(value === "&"){
|
||||||
|
throw new Error("An entity with value '&' is not permitted");
|
||||||
|
}else{
|
||||||
|
this.externalEntities[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = XMLParser;
|
||||||
113
node_modules/fast-xml-parser/src/xmlparser/node2json.js
generated
vendored
Normal file
113
node_modules/fast-xml-parser/src/xmlparser/node2json.js
generated
vendored
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {array} node
|
||||||
|
* @param {any} options
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function prettify(node, options){
|
||||||
|
return compress( node, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {array} arr
|
||||||
|
* @param {object} options
|
||||||
|
* @param {string} jPath
|
||||||
|
* @returns object
|
||||||
|
*/
|
||||||
|
function compress(arr, options, jPath){
|
||||||
|
let text;
|
||||||
|
const compressedObj = {};
|
||||||
|
for (let i = 0; i < arr.length; i++) {
|
||||||
|
const tagObj = arr[i];
|
||||||
|
const property = propName(tagObj);
|
||||||
|
let newJpath = "";
|
||||||
|
if(jPath === undefined) newJpath = property;
|
||||||
|
else newJpath = jPath + "." + property;
|
||||||
|
|
||||||
|
if(property === options.textNodeName){
|
||||||
|
if(text === undefined) text = tagObj[property];
|
||||||
|
else text += "" + tagObj[property];
|
||||||
|
}else if(property === undefined){
|
||||||
|
continue;
|
||||||
|
}else if(tagObj[property]){
|
||||||
|
|
||||||
|
let val = compress(tagObj[property], options, newJpath);
|
||||||
|
const isLeaf = isLeafTag(val, options);
|
||||||
|
|
||||||
|
if(tagObj[":@"]){
|
||||||
|
assignAttributes( val, tagObj[":@"], newJpath, options);
|
||||||
|
}else if(Object.keys(val).length === 1 && val[options.textNodeName] !== undefined && !options.alwaysCreateTextNode){
|
||||||
|
val = val[options.textNodeName];
|
||||||
|
}else if(Object.keys(val).length === 0){
|
||||||
|
if(options.alwaysCreateTextNode) val[options.textNodeName] = "";
|
||||||
|
else val = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(compressedObj[property] !== undefined && compressedObj.hasOwnProperty(property)) {
|
||||||
|
if(!Array.isArray(compressedObj[property])) {
|
||||||
|
compressedObj[property] = [ compressedObj[property] ];
|
||||||
|
}
|
||||||
|
compressedObj[property].push(val);
|
||||||
|
}else{
|
||||||
|
//TODO: if a node is not an array, then check if it should be an array
|
||||||
|
//also determine if it is a leaf node
|
||||||
|
if (options.isArray(property, newJpath, isLeaf )) {
|
||||||
|
compressedObj[property] = [val];
|
||||||
|
}else{
|
||||||
|
compressedObj[property] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// if(text && text.length > 0) compressedObj[options.textNodeName] = text;
|
||||||
|
if(typeof text === "string"){
|
||||||
|
if(text.length > 0) compressedObj[options.textNodeName] = text;
|
||||||
|
}else if(text !== undefined) compressedObj[options.textNodeName] = text;
|
||||||
|
return compressedObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
function propName(obj){
|
||||||
|
const keys = Object.keys(obj);
|
||||||
|
for (let i = 0; i < keys.length; i++) {
|
||||||
|
const key = keys[i];
|
||||||
|
if(key !== ":@") return key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function assignAttributes(obj, attrMap, jpath, options){
|
||||||
|
if (attrMap) {
|
||||||
|
const keys = Object.keys(attrMap);
|
||||||
|
const len = keys.length; //don't make it inline
|
||||||
|
for (let i = 0; i < len; i++) {
|
||||||
|
const atrrName = keys[i];
|
||||||
|
if (options.isArray(atrrName, jpath + "." + atrrName, true, true)) {
|
||||||
|
obj[atrrName] = [ attrMap[atrrName] ];
|
||||||
|
} else {
|
||||||
|
obj[atrrName] = attrMap[atrrName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isLeafTag(obj, options){
|
||||||
|
const { textNodeName } = options;
|
||||||
|
const propCount = Object.keys(obj).length;
|
||||||
|
|
||||||
|
if (propCount === 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
propCount === 1 &&
|
||||||
|
(obj[textNodeName] || typeof obj[textNodeName] === "boolean" || obj[textNodeName] === 0)
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
exports.prettify = prettify;
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user